Program: gdcm
Module: $RCSfile: gdcmPixelReadConvert.cxx,v $
Language: C++
- Date: $Date: 2005/01/26 11:42:02 $
- Version: $Revision: 1.35 $
+ Date: $Date: 2005/02/01 10:29:55 $
+ Version: $Revision: 1.43 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
namespace gdcm
{
+//-----------------------------------------------------------------------------
#define str2num(str, typeNum) *((typeNum *)(str))
-
//-----------------------------------------------------------------------------
// Constructor / Destructor
PixelReadConvert::PixelReadConvert()
LutBlueData =0;
}
+PixelReadConvert::~PixelReadConvert()
+{
+ Squeeze();
+}
+
+//-----------------------------------------------------------------------------
+// Public
void PixelReadConvert::Squeeze()
{
if ( RGB )
- {
delete [] RGB;
- }
RGB = 0;
if ( Raw )
- {
delete [] Raw;
- }
Raw = 0;
if ( LutRGBA )
- {
delete [] LutRGBA;
- }
LutRGBA = 0;
}
-PixelReadConvert::~PixelReadConvert()
-{
- Squeeze();
-}
-
void PixelReadConvert::AllocateRGB()
{
- if ( RGB ) {
+ if ( RGB )
delete [] RGB;
- }
- RGB = new uint8_t[ RGBSize ];
+ RGB = new uint8_t[RGBSize];
}
void PixelReadConvert::AllocateRaw()
{
- if ( Raw ) {
+ if ( Raw )
delete [] Raw;
- }
- Raw = new uint8_t[ RawSize ];
+ Raw = new uint8_t[RawSize];
}
/**
uint8_t b0, b1, b2;
fp->read( (char*)&b0, 1);
- if ( fp->fail() || fp->eof() )//Fp->gcount() == 1
+ if ( fp->fail() || fp->eof() )
{
throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
"Unfound first block" );
}
fp->read( (char*)&b1, 1 );
- if ( fp->fail() || fp->eof())//Fp->gcount() == 1
+ if ( fp->fail() || fp->eof())
{
throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
"Unfound second block" );
}
fp->read( (char*)&b2, 1 );
- if ( fp->fail() || fp->eof())//Fp->gcount() == 1
+ if ( fp->fail() || fp->eof())
{
throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
"Unfound second block" );
}
}
-/**
- * \brief Try to deal with RLE 16 Bits.
- * We assume the RLE has already been parsed and loaded in
- * Raw (through \ref ReadAndDecompressJPEGFile ).
- * We here need to make 16 Bits Pixels from Low Byte and
- * High Byte 'Planes'...(for what it may mean)
- * @return Boolean
- */
-bool PixelReadConvert::DecompressRLE16BitsFromRLE8Bits( int NumberOfFrames )
-{
- size_t pixelNumber = XSize * YSize;
- size_t rawSize = XSize * YSize * NumberOfFrames;
-
- // We assumed Raw contains the decoded RLE pixels but as
- // 8 bits per pixel. In order to convert those pixels to 16 bits
- // per pixel we cannot work in place within Raw and hence
- // we copy it in a safe place, say copyRaw.
-
- uint8_t* copyRaw = new uint8_t[ rawSize * 2 ];
- memmove( copyRaw, Raw, rawSize * 2 );
-
- uint8_t* x = Raw;
- uint8_t* a = copyRaw;
- uint8_t* b = a + pixelNumber;
-
- for ( int i = 0; i < NumberOfFrames; i++ )
- {
- for ( unsigned int j = 0; j < pixelNumber; j++ )
- {
- *(x++) = *(b++);
- *(x++) = *(a++);
- }
- }
-
- delete[] copyRaw;
-
- /// \todo check that operator new []didn't fail, and sometimes return false
- return true;
-}
-
-/**
- * \brief Implementation of the RLE decoding algorithm for decompressing
- * a RLE fragment. [refer to PS 3.5-2003, section G.3.2 p 86]
- * @param subRaw Sub region of \ref Raw where the decoded fragment
- * should be placed.
- * @param fragmentSize The length of the binary fragment as found on the disk.
- * @param RawSegmentSize The expected length of the fragment ONCE
- * Raw.
- * @param fp File Pointer: on entry the position should be the one of
- * the fragment to be decoded.
- */
-bool PixelReadConvert::ReadAndDecompressRLEFragment( uint8_t *subRaw,
- long fragmentSize,
- long RawSegmentSize,
- std::ifstream *fp )
-{
- int8_t count;
- long numberOfOutputBytes = 0;
- long numberOfReadBytes = 0;
-
- while( numberOfOutputBytes < RawSegmentSize )
- {
- fp->read( (char*)&count, 1 );
- numberOfReadBytes += 1;
- if ( count >= 0 )
- // Note: count <= 127 comparison is always true due to limited range
- // of data type int8_t [since the maximum of an exact width
- // signed integer of width N is 2^(N-1) - 1, which for int8_t
- // is 127].
- {
- fp->read( (char*)subRaw, count + 1);
- numberOfReadBytes += count + 1;
- subRaw += count + 1;
- numberOfOutputBytes += count + 1;
- }
- else
- {
- if ( ( count <= -1 ) && ( count >= -127 ) )
- {
- int8_t newByte;
- fp->read( (char*)&newByte, 1);
- numberOfReadBytes += 1;
- for( int i = 0; i < -count + 1; i++ )
- {
- subRaw[i] = newByte;
- }
- subRaw += -count + 1;
- numberOfOutputBytes += -count + 1;
- }
- }
- // if count = 128 output nothing
-
- if ( numberOfReadBytes > fragmentSize )
- {
- gdcmVerboseMacro( "Read more bytes than the segment size.");
- return false;
- }
- }
- return true;
-}
-
-/**
- * \brief Reads from disk the Pixel Data of 'Run Length Encoded'
- * Dicom encapsulated file and decompress it.
- * @param fp already open File Pointer
- * at which the pixel data should be copied
- * @return Boolean
- */
-bool PixelReadConvert::ReadAndDecompressRLEFile( std::ifstream *fp )
-{
- uint8_t *subRaw = Raw;
- long RawSegmentSize = XSize * YSize;
-
- // Loop on the frame[s]
- for( RLEFramesInfo::RLEFrameList::iterator
- it = RLEInfo->Frames.begin();
- it != RLEInfo->Frames.end();
- ++it )
- {
- // Loop on the fragments
- for( unsigned int k = 1; k <= (*it)->GetNumberOfFragments(); k++ )
- {
- fp->seekg( (*it)->GetOffset(k) , std::ios::beg );
- (void)ReadAndDecompressRLEFragment( subRaw,
- (*it)->GetLength(k),
- RawSegmentSize,
- fp );
- subRaw += RawSegmentSize;
- }
- }
-
- if ( BitsAllocated == 16 )
- {
- // Try to deal with RLE 16 Bits
- (void)DecompressRLE16BitsFromRLE8Bits( ZSize );
- }
-
- return true;
-}
/**
* \brief Swap the bytes, according to \ref SwapCode.
}
}
-
-/**
- * \brief Reads from disk the Pixel Data of JPEG Dicom encapsulated
- * file and decompress it. This function assumes that each
- * jpeg fragment contains a whole frame (jpeg file).
- * @param fp File Pointer
- * @return Boolean
- */
-bool PixelReadConvert::ReadAndDecompressJPEGFramesFromFile( std::ifstream *fp )
-{
- // Pointer to the Raw image
- //uint8_t *localRaw = Raw;
-
- // Precompute the offset localRaw will be shifted with
- int length = XSize * YSize * SamplesPerPixel;
- int numberBytes = BitsAllocated / 8;
-
-// // Loop on the fragment[s]
-// for( JPEGFragmentsInfo::JPEGFragmentsList::iterator
-// it = JPEGInfo->Fragments.begin();
-// it != JPEGInfo->Fragments.end();
-// ++it )
-// {
-// (*it)->DecompressJPEGFramesFromFile(fp, localRaw, BitsStored );
-//
-// // Advance to next free location in Raw
-// // for next fragment decompression (if any)
-//
-// localRaw += length * numberBytes;
-// }
- JPEGInfo->DecompressJPEGFramesFromFile(fp, Raw, BitsStored, numberBytes, length );
- return true;
-}
-
-/**
- * \brief Reads from disk the Pixel Data of JPEG Dicom encapsulated
- * file and decompress it. This function assumes that the dicom
- * image is a single frame split into several JPEG fragments.
- * Those fragments will be glued together into a memory buffer
- * before being read.
- * @param fp File Pointer
- * @return Boolean
- */
-bool PixelReadConvert::
-ReadAndDecompressJPEGSingleFrameFragmentsFromFile( std::ifstream *fp )
-{
- // Loop on the fragment[s] to get total length
- size_t totalLength = JPEGInfo->GetFragmentsLength();
-
- // Concatenate the jpeg fragments into a local buffer
- JOCTET *buffer = new JOCTET [totalLength];
- // Fill in the buffer:
- JPEGInfo->ReadAllFragments(fp, buffer);
-
- // kludge: // FIXME
- JPEGFragmentsInfo::JPEGFragmentsList::const_iterator it = JPEGInfo->Fragments.begin();
- (*it)->DecompressJPEGSingleFrameFragmentsFromFile(buffer, totalLength, Raw, BitsStored);
-
- // free local buffer
- delete [] buffer;
-
- return true;
-}
-
-/**
- * \brief Reads from disk the Pixel Data of JPEG Dicom encapsulated
- * file and decompress it. This function handles the generic
- * and complex case where the DICOM contains several frames,
- * and some of the frames are possibly split into several JPEG
- * fragments.
- * @param fp File Pointer
- * @return Boolean
- */
-bool PixelReadConvert::
-ReadAndDecompressJPEGFragmentedFramesFromFile( std::ifstream *fp )
-{
- // Loop on the fragment[s] to get total length
- size_t totalLength = JPEGInfo->GetFragmentsLength();
-
- // Concatenate the jpeg fragments into a local buffer
- JOCTET *buffer = new JOCTET [totalLength];
- // Fill in the buffer:
- JPEGInfo->ReadAllFragments(fp, buffer);
-
- size_t howManyRead = 0;
- size_t howManyWritten = 0;
- size_t fragmentLength = 0;
-
- JPEGFragmentsInfo::JPEGFragmentsList::const_iterator it;
- for( it = JPEGInfo->Fragments.begin() ;
- (it != JPEGInfo->Fragments.end()) && (howManyRead < totalLength);
- ++it )
- {
- fragmentLength += (*it)->GetLength();
-
- if (howManyRead > fragmentLength) continue;
-
- (*it)->DecompressJPEGFragmentedFramesFromFile(buffer, Raw, BitsStored, howManyRead, howManyWritten, totalLength);
-
- if (howManyRead < fragmentLength)
- howManyRead = fragmentLength;
- }
-
- // free local buffer
- delete [] buffer;
-
- return true;
-}
-
/**
* \brief Reads from disk the Pixel Data of JPEG Dicom encapsulated
* file and decompress it.
if ( IsJPEG2000 )
{
gdcmVerboseMacro( "Sorry, JPEG2000 not yet taken into account" );
- fp->seekg( (*JPEGInfo->Fragments.begin())->GetOffset(), std::ios::beg);
+ fp->seekg( JPEGInfo->GetFirstFragment()->GetOffset(), std::ios::beg);
// if ( ! gdcm_read_JPEG2000_file( fp,Raw ) )
- gdcmVerboseMacro( "Wrong Blue LUT descriptor" );
return false;
}
if ( IsJPEGLS )
{
gdcmVerboseMacro( "Sorry, JPEG-LS not yet taken into account" );
- fp->seekg( (*JPEGInfo->Fragments.begin())->GetOffset(), std::ios::beg);
+ fp->seekg( JPEGInfo->GetFirstFragment()->GetOffset(), std::ios::beg);
// if ( ! gdcm_read_JPEGLS_file( fp,Raw ) )
return false;
}
- if ( ( ZSize == 1 ) && ( JPEGInfo->Fragments.size() > 1 ) )
- {
- // we have one frame split into several fragments
- // we will pack those fragments into a single buffer and
- // read from it
- return ReadAndDecompressJPEGSingleFrameFragmentsFromFile( fp );
- }
- else if (JPEGInfo->Fragments.size() == (size_t)ZSize)
- {
- }
-// if ( ( ZSize == 1 ) && ( JPEGInfo->Fragments.size() > 1 ) )
-// {
-// // we have one frame split into several fragments
-// // we will pack those fragments into a single buffer and
-// // read from it
-// return ReadAndDecompressJPEGSingleFrameFragmentsFromFile( fp );
-// }
-// else if (JPEGInfo->Fragments.size() == (size_t)ZSize)
-// {
- // suppose each fragment is a frame
- return ReadAndDecompressJPEGFramesFromFile( fp );
-// }
-// else
-// {
-// // The dicom image contains frames containing fragments of images
-// // a more complex algorithm :-)
-// return ReadAndDecompressJPEGFragmentedFramesFromFile( fp );
-// }
+ // else ??
+ // Precompute the offset localRaw will be shifted with
+ int length = XSize * YSize * SamplesPerPixel;
+ int numberBytes = BitsAllocated / 8;
+
+ JPEGInfo->DecompressFromFile(fp, Raw, BitsStored, numberBytes, length );
+ return true;
}
/**
bool PixelReadConvert::ReadAndDecompressPixelData( std::ifstream *fp )
{
// ComputeRawAndRGBSizes is already made by
- // ::GrabInformationsFromHeader. So, the structure sizes are
+ // ::GrabInformationsFromfile. So, the structure sizes are
// correct
Squeeze();
}
else if ( IsRLELossless )
{
- if ( ! ReadAndDecompressRLEFile( fp ) )
+ if ( ! RLEInfo->DecompressRLEFile( fp, Raw, XSize, YSize, ZSize, BitsAllocated ) )
{
gdcmVerboseMacro( "RLE decompressor failed." );
return false;
}
}
-void PixelReadConvert::GrabInformationsFromHeader( File *header )
+void PixelReadConvert::GrabInformationsFromFile( File *file )
{
// Number of Bits Allocated for storing a Pixel is defaulted to 16
- // when absent from the header.
- BitsAllocated = header->GetBitsAllocated();
+ // when absent from the file.
+ BitsAllocated = file->GetBitsAllocated();
if ( BitsAllocated == 0 )
{
BitsAllocated = 16;
}
// Number of "Bits Stored", defaulted to number of "Bits Allocated"
- // when absent from the header.
- BitsStored = header->GetBitsStored();
+ // when absent from the file.
+ BitsStored = file->GetBitsStored();
if ( BitsStored == 0 )
{
BitsStored = BitsAllocated;
}
// High Bit Position, defaulted to "Bits Allocated" - 1
- HighBitPosition = header->GetHighBitPosition();
+ HighBitPosition = file->GetHighBitPosition();
if ( HighBitPosition == 0 )
{
HighBitPosition = BitsAllocated - 1;
}
- XSize = header->GetXSize();
- YSize = header->GetYSize();
- ZSize = header->GetZSize();
- SamplesPerPixel = header->GetSamplesPerPixel();
- PixelSize = header->GetPixelSize();
- PixelSign = header->IsSignedPixelData();
- SwapCode = header->GetSwapCode();
- std::string ts = header->GetTransferSyntax();
+ XSize = file->GetXSize();
+ YSize = file->GetYSize();
+ ZSize = file->GetZSize();
+ SamplesPerPixel = file->GetSamplesPerPixel();
+ PixelSize = file->GetPixelSize();
+ PixelSign = file->IsSignedPixelData();
+ SwapCode = file->GetSwapCode();
+ std::string ts = file->GetTransferSyntax();
IsRaw =
- ( ! header->IsDicomV3() )
+ ( ! file->IsDicomV3() )
|| Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRLittleEndian
|| Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRLittleEndianDLXGE
|| Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRLittleEndian
IsJPEGLossless = Global::GetTS()->IsJPEGLossless(ts);
IsRLELossless = Global::GetTS()->IsRLELossless(ts);
- PixelOffset = header->GetPixelOffset();
- PixelDataLength = header->GetPixelAreaLength();
- RLEInfo = header->GetRLEInfo();
- JPEGInfo = header->GetJPEGInfo();
-
- PlanarConfiguration = header->GetPlanarConfiguration();
- IsMonochrome = header->IsMonochrome();
- IsPaletteColor = header->IsPaletteColor();
- IsYBRFull = header->IsYBRFull();
+ PixelOffset = file->GetPixelOffset();
+ PixelDataLength = file->GetPixelAreaLength();
+ RLEInfo = file->GetRLEInfo();
+ JPEGInfo = file->GetJPEGInfo();
+
+ PlanarConfiguration = file->GetPlanarConfiguration();
+ IsMonochrome = file->IsMonochrome();
+ IsPaletteColor = file->IsPaletteColor();
+ IsYBRFull = file->IsYBRFull();
/////////////////////////////////////////////////////////////////
// LUT section:
- HasLUT = header->HasLUT();
+ HasLUT = file->HasLUT();
if ( HasLUT )
{
// Just in case some access to a File element requires disk access.
- LutRedDescriptor = header->GetEntryValue( 0x0028, 0x1101 );
- LutGreenDescriptor = header->GetEntryValue( 0x0028, 0x1102 );
- LutBlueDescriptor = header->GetEntryValue( 0x0028, 0x1103 );
+ LutRedDescriptor = file->GetEntryValue( 0x0028, 0x1101 );
+ LutGreenDescriptor = file->GetEntryValue( 0x0028, 0x1102 );
+ LutBlueDescriptor = file->GetEntryValue( 0x0028, 0x1103 );
// Depending on the value of Document::MAX_SIZE_LOAD_ELEMENT_VALUE
// [ refer to invocation of Document::SetMaxSizeLoadEntry() in
/// parsed from. Fix that. FIXME.
////// Red round
- header->LoadEntryBinArea(0x0028, 0x1201);
- LutRedData = (uint8_t*)header->GetEntryBinArea( 0x0028, 0x1201 );
+ file->LoadEntryBinArea(0x0028, 0x1201);
+ LutRedData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1201 );
if ( ! LutRedData )
{
gdcmVerboseMacro( "Unable to read Red LUT data" );
}
////// Green round:
- header->LoadEntryBinArea(0x0028, 0x1202);
- LutGreenData = (uint8_t*)header->GetEntryBinArea(0x0028, 0x1202 );
+ file->LoadEntryBinArea(0x0028, 0x1202);
+ LutGreenData = (uint8_t*)file->GetEntryBinArea(0x0028, 0x1202 );
if ( ! LutGreenData)
{
gdcmVerboseMacro( "Unable to read Green LUT data" );
}
////// Blue round:
- header->LoadEntryBinArea(0x0028, 0x1203);
- LutBlueData = (uint8_t*)header->GetEntryBinArea( 0x0028, 0x1203 );
+ file->LoadEntryBinArea(0x0028, 0x1203);
+ LutBlueData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1203 );
if ( ! LutBlueData )
{
gdcmVerboseMacro( "Unable to read Blue LUT data" );
// forge the 4 * 8 Bits Red/Green/Blue/Alpha LUT
LutRGBA = new uint8_t[ 1024 ]; // 256 * 4 (R, G, B, Alpha)
if ( !LutRGBA )
- {
return;
- }
+
memset( LutRGBA, 0, 1024 );
int mult;
return true;
}
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
/**
* \brief Print self.
* @param indent Indentation string to be prepended during printing.
}
}
+//-----------------------------------------------------------------------------
} // end namespace gdcm
// NOTES on File internal calls