#include "gdcmImageRegionReader.h"
#include "gdcmImageHelper.h"
#include "gdcmBoxRegion.h"
#include "gdcmRAWCodec.h"
#include "gdcmRLECodec.h"
#include "gdcmJPEG2000Codec.h"
#include "gdcmJPEGCodec.h"
#include "gdcmJPEGLSCodec.h"
namespace gdcm
{
class ImageRegionReaderInternals
{
public:
ImageRegionReaderInternals()
{
TheRegion = nullptr;
Modified = false;
FileOffset = -1;
}
~ImageRegionReaderInternals()
{
delete TheRegion;
}
void SetRegion(Region const & r)
{
delete TheRegion;
TheRegion = r.Clone();
gdcm_assert( TheRegion );
Modified = true;
}
Region *GetRegion() const
{
return TheRegion;
}
std::streampos GetFileOffset() const
{
return FileOffset;
}
void SetFileOffset( std::streampos f )
{
FileOffset = f;
}
private:
Region *TheRegion;
bool Modified;
std::streamoff FileOffset;
};
ImageRegionReader::ImageRegionReader()
{
Internals = new ImageRegionReaderInternals;
}
ImageRegionReader::~ImageRegionReader()
{
delete Internals;
}
void ImageRegionReader::SetRegion(Region const & region)
{
Internals->SetRegion( region );
}
Region const &ImageRegionReader::GetRegion() const
{
if( Internals->GetRegion() )
{
return *Internals->GetRegion();
}
else
{
static BoxRegion full;
std::vector<unsigned int> dims = ImageHelper::GetDimensionsValue(GetFile());
full.SetDomain(0, dims[0] - 1,
0, dims[1] - 1,
0, dims[2] - 1 );
return full;
}
}
size_t ImageRegionReader::ComputeBufferLength() const
{
size_t npixels = 0;
if( Internals->GetRegion() )
{
if( !Internals->GetRegion()->IsValid() )
{
gdcmDebugMacro( "Sorry not a valid extent. Giving up" );
return 0;
}
npixels = this->Internals->GetRegion()->Area();
}
else
{
std::vector<unsigned int> dims = ImageHelper::GetDimensionsValue(GetFile());
BoxRegion full;
full.SetDomain(0, dims[0] - 1,
0, dims[1] - 1,
0, dims[2] - 1 );
if(! full.IsValid() )
{
gdcmDebugMacro( "Sorry not a valid extent. Giving up" );
return 0;
}
npixels = full.Area();
}
const PixelFormat pixelInfo = ImageHelper::GetPixelFormatValue(GetFile());
const size_t bytesPerPixel = pixelInfo.GetPixelSize();
return npixels*bytesPerPixel;
}
bool ImageRegionReader::ReadInformation()
{
std::set<Tag> st;
Tag tpixeldata(0x7fe0, 0x0010); st.insert(tpixeldata);
if (!ReadUpToTag(tpixeldata, st))
{
gdcmWarningMacro("Failed ReadUpToTag.");
return false;
}
const bool iseof = GetStreamPtr()->eof();
if( iseof )
{
gdcmDebugMacro( "No Pixel Data, sorry" );
return false;
}
std::streampos fileoffset = GetStreamPtr()->tellg();
gdcm_assert( fileoffset != std::streampos(-1) );
Internals->SetFileOffset( fileoffset );
const File &file = GetFile();
const DataSet &ds = file.GetDataSet(); (void)ds;
MediaStorage ms;
ms.SetFromFile(file);
gdcm_assert( ms != MediaStorage::VLWholeSlideMicroscopyImageStorage );
if( !MediaStorage::IsImage( ms ) )
{
gdcmDebugMacro( "Not an image recognized. Giving up");
return false;
}
if( !ReadImageInternal(ms, false) )
{
return false;
}
Image& pixeldata = GetImage();
std::vector<double> spacing = ImageHelper::GetSpacingValue(*F);
if( !spacing.empty() )
{
gdcm_assert( spacing.size() >= pixeldata.GetNumberOfDimensions() ); pixeldata.SetSpacing( spacing.data() );
if( spacing.size() > pixeldata.GetNumberOfDimensions() ) {
pixeldata.SetSpacing(pixeldata.GetNumberOfDimensions(), spacing[pixeldata.GetNumberOfDimensions()] );
}
}
std::vector<double> origin = ImageHelper::GetOriginValue(*F);
if( !origin.empty() )
{
pixeldata.SetOrigin( origin.data() );
if( origin.size() > pixeldata.GetNumberOfDimensions() ) {
pixeldata.SetOrigin(pixeldata.GetNumberOfDimensions(), origin[pixeldata.GetNumberOfDimensions()] );
}
}
std::vector<double> dircos = ImageHelper::GetDirectionCosinesValue(*F);
if( !dircos.empty() )
{
pixeldata.SetDirectionCosines( dircos.data() );
}
std::vector<double> is = ImageHelper::GetRescaleInterceptSlopeValue(*F);
pixeldata.SetIntercept( is[0] );
pixeldata.SetSlope( is[1] );
return true;
}
BoxRegion ImageRegionReader::ComputeBoundingBox()
{
BoxRegion boundingbox;
if( Internals->GetRegion() )
boundingbox = this->Internals->GetRegion()->ComputeBoundingBox();
else
{
std::vector<unsigned int> dims = ImageHelper::GetDimensionsValue(GetFile());
boundingbox.SetDomain(
0, dims[0] - 1,
0, dims[1] - 1,
0, dims[2] - 1 );
}
return boundingbox;
}
bool ImageRegionReader::ReadRAWIntoBuffer(char *buffer, size_t buflen)
{
(void)buflen;
std::vector<unsigned int> dimensions = ImageHelper::GetDimensionsValue(GetFile());
PixelFormat pixelInfo = ImageHelper::GetPixelFormatValue(GetFile());
const FileMetaInformation &header = GetFile().GetHeader();
const TransferSyntax &ts = header.GetDataSetTransferSyntax();
bool needbyteswap = (ts == TransferSyntax::ImplicitVRBigEndianPrivateGE || ts == TransferSyntax::ExplicitVRBigEndian );
RAWCodec theCodec;
if( !theCodec.CanDecode( ts ) ) return false;
theCodec.SetPlanarConfiguration(
ImageHelper::GetPlanarConfigurationValue(GetFile()));
if( ImageHelper::GetPhotometricInterpretationValue(GetFile()) == PhotometricInterpretation::YBR_FULL_422 ) return false;
theCodec.SetPhotometricInterpretation(
ImageHelper::GetPhotometricInterpretationValue(GetFile()));
theCodec.SetPixelFormat( ImageHelper::GetPixelFormatValue(GetFile()) );
theCodec.SetNeedByteSwap( needbyteswap );
theCodec.SetNeedOverlayCleanup( pixelInfo.GetBitsAllocated() != pixelInfo.GetBitsStored() );
theCodec.SetDimensions(ImageHelper::GetDimensionsValue(GetFile()));
std::istream* theStream = GetStreamPtr();
BoxRegion boundingbox = ComputeBoundingBox();
unsigned int xmin = boundingbox.GetXMin();
unsigned int xmax = boundingbox.GetXMax();
unsigned int ymin = boundingbox.GetYMin();
unsigned int ymax = boundingbox.GetYMax();
unsigned int zmin = boundingbox.GetZMin();
unsigned int zmax = boundingbox.GetZMax();
gdcm_assert( xmax >= xmin );
gdcm_assert( ymax >= ymin );
unsigned int rowsize = xmax - xmin + 1;
unsigned int colsize = ymax - ymin + 1;
unsigned int bytesPerPixel = pixelInfo.GetPixelSize();
std::vector<char> buffer1;
buffer1.resize( rowsize*bytesPerPixel );
char *tmpBuffer1 = buffer1.data();
std::vector<char> buffer2;
buffer2.resize( rowsize*bytesPerPixel );
char *tmpBuffer2 = buffer2.data();
unsigned int y, z;
std::streamoff theOffset;
for (z = zmin; z <= zmax; ++z)
{
for (y = ymin; y <= ymax; ++y)
{
theStream->seekg(std::ios::beg);
theOffset = (size_t)Internals->GetFileOffset() + (z*dimensions[1]*dimensions[0] + y*dimensions[0] + xmin)*bytesPerPixel;
theStream->seekg(theOffset);
theStream->read(tmpBuffer1, rowsize*bytesPerPixel);
if (!theCodec.DecodeBytes(tmpBuffer1, rowsize*bytesPerPixel,
tmpBuffer2, rowsize*bytesPerPixel))
{
return false;
}
#if 0#endif
memcpy(&(buffer[((z-zmin)*rowsize*colsize + (y-ymin)*rowsize)*bytesPerPixel]),
tmpBuffer2, rowsize*bytesPerPixel);
}
}
return true;
}
bool ImageRegionReader::ReadRLEIntoBuffer(char *buffer, size_t buflen)
{
(void)buflen;
std::vector<unsigned int> dimensions = ImageHelper::GetDimensionsValue(GetFile());
const PixelFormat pixelInfo = ImageHelper::GetPixelFormatValue(GetFile());
const FileMetaInformation &header = GetFile().GetHeader();
const TransferSyntax &ts = header.GetDataSetTransferSyntax();
bool needbyteswap = (ts == TransferSyntax::ImplicitVRBigEndianPrivateGE || ts == TransferSyntax::ExplicitVRBigEndian );
RLECodec theCodec;
if( !theCodec.CanDecode( ts ) ) return false;
theCodec.SetPlanarConfiguration(
ImageHelper::GetPlanarConfigurationValue(GetFile()));
theCodec.SetPhotometricInterpretation(
ImageHelper::GetPhotometricInterpretationValue(GetFile()));
theCodec.SetPixelFormat( ImageHelper::GetPixelFormatValue(GetFile()) );
theCodec.SetNeedByteSwap( needbyteswap );
theCodec.SetNeedOverlayCleanup( pixelInfo.GetBitsAllocated() != pixelInfo.GetBitsStored() );
std::vector<unsigned int> d = ImageHelper::GetDimensionsValue(GetFile());
theCodec.SetDimensions(d );
theCodec.SetNumberOfDimensions( 2 );
if( d[2] > 1 )
theCodec.SetNumberOfDimensions( 3 );
std::istream* theStream = GetStreamPtr();
BoxRegion boundingbox = ComputeBoundingBox();
unsigned int xmin = boundingbox.GetXMin();
unsigned int xmax = boundingbox.GetXMax();
unsigned int ymin = boundingbox.GetYMin();
unsigned int ymax = boundingbox.GetYMax();
unsigned int zmin = boundingbox.GetZMin();
unsigned int zmax = boundingbox.GetZMax();
gdcm_assert( xmax >= xmin );
gdcm_assert( ymax >= ymin );
bool ret = theCodec.DecodeExtent(
buffer,
xmin, xmax,
ymin, ymax,
zmin, zmax,
*theStream
);
return ret;
}
bool ImageRegionReader::ReadJPEG2000IntoBuffer(char *buffer, size_t buflen)
{
(void)buflen;
std::vector<unsigned int> dimensions = ImageHelper::GetDimensionsValue(GetFile());
const PixelFormat pixelInfo = ImageHelper::GetPixelFormatValue(GetFile());
const FileMetaInformation &header = GetFile().GetHeader();
const TransferSyntax &ts = header.GetDataSetTransferSyntax();
bool needbyteswap = (ts == TransferSyntax::ImplicitVRBigEndianPrivateGE || ts == TransferSyntax::ExplicitVRBigEndian );
JPEG2000Codec theCodec;
if( !theCodec.CanDecode( ts ) ) return false;
theCodec.SetPlanarConfiguration(
ImageHelper::GetPlanarConfigurationValue(GetFile()));
theCodec.SetPhotometricInterpretation(
ImageHelper::GetPhotometricInterpretationValue(GetFile()));
theCodec.SetPixelFormat( ImageHelper::GetPixelFormatValue(GetFile()) );
theCodec.SetNeedByteSwap( needbyteswap );
theCodec.SetNeedOverlayCleanup( pixelInfo.GetBitsAllocated() != pixelInfo.GetBitsStored() );
std::vector<unsigned int> d = ImageHelper::GetDimensionsValue(GetFile());
theCodec.SetDimensions(d );
theCodec.SetNumberOfDimensions( 2 );
if( d[2] > 1 )
theCodec.SetNumberOfDimensions( 3 );
std::istream* theStream = GetStreamPtr();
BoxRegion boundingbox = ComputeBoundingBox();
unsigned int xmin = boundingbox.GetXMin();
unsigned int xmax = boundingbox.GetXMax();
unsigned int ymin = boundingbox.GetYMin();
unsigned int ymax = boundingbox.GetYMax();
unsigned int zmin = boundingbox.GetZMin();
unsigned int zmax = boundingbox.GetZMax();
gdcm_assert( xmax >= xmin );
gdcm_assert( ymax >= ymin );
bool ret = theCodec.DecodeExtent(
buffer,
xmin, xmax,
ymin, ymax,
zmin, zmax,
*theStream
);
return ret;
}
bool ImageRegionReader::ReadJPEGIntoBuffer(char *buffer, size_t buflen)
{
(void)buflen;
std::vector<unsigned int> dimensions = ImageHelper::GetDimensionsValue(GetFile());
const PixelFormat pixelInfo = ImageHelper::GetPixelFormatValue(GetFile());
const FileMetaInformation &header = GetFile().GetHeader();
const TransferSyntax &ts = header.GetDataSetTransferSyntax();
bool needbyteswap = (ts == TransferSyntax::ImplicitVRBigEndianPrivateGE || ts == TransferSyntax::ExplicitVRBigEndian );
JPEGCodec theCodec;
if( !theCodec.CanDecode( ts ) ) return false;
theCodec.SetPlanarConfiguration(
ImageHelper::GetPlanarConfigurationValue(GetFile()));
theCodec.SetPhotometricInterpretation(
ImageHelper::GetPhotometricInterpretationValue(GetFile()));
theCodec.SetNeedByteSwap( needbyteswap );
theCodec.SetNeedOverlayCleanup( pixelInfo.GetBitsAllocated() != pixelInfo.GetBitsStored() );
std::vector<unsigned int> d = ImageHelper::GetDimensionsValue(GetFile());
theCodec.SetDimensions(d );
theCodec.SetNumberOfDimensions( 2 );
if( d[2] > 1 )
theCodec.SetNumberOfDimensions( 3 );
theCodec.SetPixelFormat( ImageHelper::GetPixelFormatValue(GetFile()) );
std::istream* theStream = GetStreamPtr();
BoxRegion boundingbox = ComputeBoundingBox();
unsigned int xmin = boundingbox.GetXMin();
unsigned int xmax = boundingbox.GetXMax();
unsigned int ymin = boundingbox.GetYMin();
unsigned int ymax = boundingbox.GetYMax();
unsigned int zmin = boundingbox.GetZMin();
unsigned int zmax = boundingbox.GetZMax();
gdcm_assert( xmax >= xmin );
gdcm_assert( ymax >= ymin );
bool ret = theCodec.DecodeExtent(
buffer,
xmin, xmax,
ymin, ymax,
zmin, zmax,
*theStream
);
return ret;
}
bool ImageRegionReader::ReadJPEGLSIntoBuffer(char *buffer, size_t buflen)
{
(void)buflen;
std::vector<unsigned int> dimensions = ImageHelper::GetDimensionsValue(GetFile());
const PixelFormat pixelInfo = ImageHelper::GetPixelFormatValue(GetFile());
const FileMetaInformation &header = GetFile().GetHeader();
const TransferSyntax &ts = header.GetDataSetTransferSyntax();
bool needbyteswap = (ts == TransferSyntax::ImplicitVRBigEndianPrivateGE || ts == TransferSyntax::ExplicitVRBigEndian );
JPEGLSCodec theCodec;
if( !theCodec.CanDecode( ts ) ) return false;
theCodec.SetPlanarConfiguration(
ImageHelper::GetPlanarConfigurationValue(GetFile()));
theCodec.SetPhotometricInterpretation(
ImageHelper::GetPhotometricInterpretationValue(GetFile()));
theCodec.SetPixelFormat( ImageHelper::GetPixelFormatValue(GetFile()) );
theCodec.SetNeedByteSwap( needbyteswap );
theCodec.SetNeedOverlayCleanup( pixelInfo.GetBitsAllocated() != pixelInfo.GetBitsStored() );
std::vector<unsigned int> d = ImageHelper::GetDimensionsValue(GetFile());
theCodec.SetDimensions(d );
theCodec.SetNumberOfDimensions( 2 );
if( d[2] > 1 )
theCodec.SetNumberOfDimensions( 3 );
std::istream* theStream = GetStreamPtr();
BoxRegion boundingbox = ComputeBoundingBox();
unsigned int xmin = boundingbox.GetXMin();
unsigned int xmax = boundingbox.GetXMax();
unsigned int ymin = boundingbox.GetYMin();
unsigned int ymax = boundingbox.GetYMax();
unsigned int zmin = boundingbox.GetZMin();
unsigned int zmax = boundingbox.GetZMax();
gdcm_assert( xmax >= xmin );
gdcm_assert( ymax >= ymin );
bool ret = theCodec.DecodeExtent(
buffer,
xmin, xmax,
ymin, ymax,
zmin, zmax,
*theStream
);
return ret;
}
bool ImageRegionReader::ReadIntoBuffer(char *buffer, size_t buflen)
{
size_t thelen = ComputeBufferLength();
if( thelen == 0 )
{
gdcmDebugMacro( "Cannot load an image of 0 bytes" );
return false;
}
if( buflen < thelen )
{
gdcmDebugMacro( "buffer cannot be smaller than computed buffer length" );
return false;
}
gdcm_assert( Internals->GetFileOffset() != std::streampos(-1) );
gdcmDebugMacro( "Using FileOffset: " << Internals->GetFileOffset() );
std::istream* theStream = GetStreamPtr();
theStream->seekg( Internals->GetFileOffset() );
bool success = false;
if( !success ) success = ReadRAWIntoBuffer(buffer, buflen);
if( !success ) success = ReadRLEIntoBuffer(buffer, buflen);
if( !success ) success = ReadJPEGIntoBuffer(buffer, buflen);
if( !success ) success = ReadJPEGLSIntoBuffer(buffer, buflen);
if( !success ) success = ReadJPEG2000IntoBuffer(buffer, buflen);
return success;
}
bool ImageRegionReader::Read()
{
return false;
}
}