From: frog Date: Fri, 15 Oct 2004 10:43:27 +0000 (+0000) Subject: * src/gdcmDebug.cxx last ditch attempt to get warning/error messages X-Git-Tag: Version0.6.bp~60 X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=commitdiff_plain;h=c132b43ebda61490fe85f62a88969b6cfb9e400d;p=gdcm.git * src/gdcmDebug.cxx last ditch attempt to get warning/error messages displayed on Win32 when a brutal abort() occurs (because of uncatched exception). See TODO new entry of this commit for more on this. * TODO added new entry. * CLEANUP_ROUND (12) for gdcmPixelConvert (nicotine is my friend stage) src/gdcmFile.[cxx|h] and gdcmPixelConvert.[cxx|h]: - HandleColor is no longer called from gdcmFile.cxx - gdcmPixelConvert.cxx clean up on method arguments and internal variable names for semantical coherence. --- diff --git a/ChangeLog b/ChangeLog index 5dc6bbe3..979ade06 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2004-10-15 Eric Boix + * src/gdcmDebug.cxx last ditch attempt to get warning/error messages + displayed on Win32 when a brutal abort() occurs (because of uncatched + exception). See TODO new entry of this commit for more on this. + * TODO added new entry. + * CLEANUP_ROUND (12) for gdcmPixelConvert (nicotine is my friend stage) + src/gdcmFile.[cxx|h] and gdcmPixelConvert.[cxx|h]: + - HandleColor is no longer called from gdcmFile.cxx + - gdcmPixelConvert.cxx clean up on method arguments and internal + variable names for semantical coherence. + 2004-10-14 Mathieu Malaterre * Finished lossless transition, not only do we now read all lossless jpeg images, without the need of the Cornwell lib, but we do read them properly now diff --git a/TODO b/TODO index 51890575..343b8051 100644 --- a/TODO +++ b/TODO @@ -67,6 +67,45 @@ et si on prenait: radical + 147.144.143.155 + IP + time() ----------------------------------------------------------------------------- +Description: [BUG] Better handling of unfound Dicom dictionary. + When gdcm doesn't find the Dicom dictionary (because it's + path to the directory of dictionary is uncorrect, either + because the install relative layout was broken after file moves + or because the environnement variable GDCM_DICT_PATH is + unpropely set), gdcm will: + 1/ print a warning + 2/ throw an exception (that is internaly UNcatched by gdcm) + that in most cases provoques the caller application to + exit uncleanly (uncatched excpetions in fine call abort() ). + Additionaly on Win32 the warning print isn't displayed because + exiting occurs prior to cerr or cout is flushed properly. +Date: 2004 Oct 15 +Attributed: +Details: fixes (from dirty to clean) + 1/ force Win32 to flush it's buffer so at least the user gets some + reason why it's application exited (when called in command + environement). Note: it looks like the "cerr << flush" fails. Sigh. + 2/ within gdcm catch the exception, display a decent warning, and + return to caller. + 3/ see the comment below on how to enhance the API and fix things + really cleanly. +Comments: ENH proposal: + The caller migth not be aware of the path to the dictionaries + on invocation of gdcm (think this path is set by the Interface + because the caller wants to skip the default gdcm dictionary in order + to provide his own ones e.g. another language based one). + Hence, gdcm should postpone the parsing of the default dictionary + instead of doing it on library entry. + This would enable two things: + - It would give a chance to the caller to set the path to + the dictionaries he whishes to use, through a call to + newly created DictSet::SetDictionaryPath( string ). + - It would avoid the burden of using the GDCM_DICT_PATH + environnement variable and enable GDCM CONTROL FROM WITHIN + THE API. Optionaly, if the caller didn't use the API to + provide his prefered path, gdcm could still default to + GDCM_DICT_PATH... +----------------------------------------------------------------------------- Description: vtk/vtkGdcmReader doesn't positionate the normal to the image Date: 2004 Oct 1 Attributed: diff --git a/src/gdcmDebug.cxx b/src/gdcmDebug.cxx index ffa95ed3..787c529c 100644 --- a/src/gdcmDebug.cxx +++ b/src/gdcmDebug.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmDebug.cxx,v $ Language: C++ - Date: $Date: 2004/10/13 14:15:29 $ - Version: $Revision: 1.9 $ + Date: $Date: 2004/10/15 10:43:27 $ + Version: $Revision: 1.10 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -53,7 +53,7 @@ void Debug::Verbose(int level, const char * msg1, const char * msg2) { return ; } - std::cerr << "gdcm::" << msg1 << ' ' << msg2 << std::endl; + std::cerr << "gdcm::" << msg1 << ' ' << msg2 << std::endl << std::flush; } /** @@ -68,7 +68,7 @@ void Debug::Error(bool test, const char * msg1, const char * msg2) { return; } - std::cerr << "gdcm::" << msg1 << ' ' << msg2 << std::endl; + std::cerr << "gdcm::" << msg1 << ' ' << msg2 << std::endl << std::flush; Exit(1); } @@ -81,7 +81,8 @@ void Debug::Error(bool test, const char * msg1, const char * msg2) void Debug::Error(const char* msg1, const char* msg2, const char* msg3) { - std::cerr << "gdcm::" << msg1 << ' ' << msg2 << ' ' << msg3 << std::endl; + std::cerr << "gdcm::" << msg1 << ' ' << msg2 << ' ' << msg3 + << std::endl << std::flush; Exit(1); } @@ -101,7 +102,8 @@ void Debug::Assert(int level, bool test, const char * msg1, } if (!test) { - std::cerr << "gdcm::" << msg1 << ' ' << msg2 << std::endl; + std::cerr << "gdcm::" << msg1 << ' ' << msg2 + << std::endl << std::flush; } } diff --git a/src/gdcmFile.cxx b/src/gdcmFile.cxx index b91e7be5..02e6a08a 100644 --- a/src/gdcmFile.cxx +++ b/src/gdcmFile.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmFile.cxx,v $ Language: C++ - Date: $Date: 2004/10/13 14:56:07 $ - Version: $Revision: 1.143 $ + Date: $Date: 2004/10/15 10:43:27 $ + Version: $Revision: 1.144 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -138,7 +138,7 @@ void File::Initialise() PixelConverter.SetPixelDataLength( HeaderInternal->GetPixelAreaLength() ); PixelConverter.SetRLEInfo( &(HeaderInternal->RLEInfo) ); PixelConverter.SetJPEGInfo( &(HeaderInternal->JPEGInfo) ); - PixelConverter.SetDecompressedSize( ImageDataSize ); + PixelConverter.SetHasLUT( HeaderInternal->HasLUT() ); PixelConverter.SetPlanarConfiguration( HeaderInternal->GetPlanarConfiguration() ); @@ -564,10 +564,13 @@ void File::GetImageDataIntoVectorRaw (void* destination, size_t maxSize) } FILE* fp = HeaderInternal->OpenFile(); - PixelConverter.ReadAndDecompressPixelData( destination, fp ); + PixelConverter.ReadAndDecompressPixelData( fp ); HeaderInternal->CloseFile(); - - if ( ! PixelConverter.HandleColor( (uint8_t*)destination ) ) + memmove( destination, + (void*)PixelConverter.GetDecompressed(), + PixelConverter.GetDecompressedSize() ); + + if ( ! PixelConverter.IsDecompressedRGB() ) { return; } diff --git a/src/gdcmPixelConvert.cxx b/src/gdcmPixelConvert.cxx index 330e0f82..b9e5e3ab 100644 --- a/src/gdcmPixelConvert.cxx +++ b/src/gdcmPixelConvert.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmPixelConvert.cxx,v $ Language: C++ - Date: $Date: 2004/10/14 22:35:02 $ - Version: $Revision: 1.13 $ + Date: $Date: 2004/10/15 10:43:28 $ + Version: $Revision: 1.14 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -90,37 +90,35 @@ void PixelConvert::AllocateDecompressed() * \brief Read from file a 12 bits per pixel image and uncompress it * into a 16 bits per pixel image. */ -void PixelConvert::ReadAndDecompress12BitsTo16Bits( - uint8_t* pixelZone, - FILE* filePtr) +void PixelConvert::ReadAndDecompress12BitsTo16Bits( FILE* fp ) throw ( FormatError ) { int nbPixels = XSize * YSize; - uint16_t* destination = (uint16_t*)pixelZone; + uint16_t* localDecompres = (uint16_t*)Decompressed; for( int p = 0; p < nbPixels; p += 2 ) { uint8_t b0, b1, b2; size_t ItemRead; - ItemRead = fread( &b0, 1, 1, filePtr); + ItemRead = fread( &b0, 1, 1, fp ); if ( ItemRead != 1 ) { - throw FormatError( "File::ReadAndDecompress12BitsTo16Bits()", + throw FormatError( "PixelConvert::ReadAndDecompress12BitsTo16Bits()", "Unfound first block" ); } - ItemRead = fread( &b1, 1, 1, filePtr); + ItemRead = fread( &b1, 1, 1, fp ); if ( ItemRead != 1 ) { - throw FormatError( "File::ReadAndDecompress12BitsTo16Bits()", + throw FormatError( "PixelConvert::ReadAndDecompress12BitsTo16Bits()", "Unfound second block" ); } - ItemRead = fread( &b2, 1, 1, filePtr); + ItemRead = fread( &b2, 1, 1, fp ); if ( ItemRead != 1 ) { - throw FormatError( "File::ReadAndDecompress12BitsTo16Bits()", + throw FormatError( "PixelConvert::ReadAndDecompress12BitsTo16Bits()", "Unfound second block" ); } @@ -128,10 +126,10 @@ void PixelConvert::ReadAndDecompress12BitsTo16Bits( // // 2 pixels 12bit = [0xABCDEF] // 2 pixels 16bit = [0x0ABD] + [0x0FCE] - // A B D - *destination++ = ((b0 >> 4) << 8) + ((b0 & 0x0f) << 4) + (b1 & 0x0f); - // F C E - *destination++ = ((b2 & 0x0f) << 8) + ((b1 >> 4) << 4) + (b2 >> 4); + // A B D + *localDecompres++ = ((b0 >> 4) << 8) + ((b0 & 0x0f) << 4) + (b1 & 0x0f); + // F C E + *localDecompres++ = ((b2 & 0x0f) << 8) + ((b1 >> 4) << 4) + (b2 >> 4); /// \todo JPR Troubles expected on Big-Endian processors ? } @@ -140,28 +138,26 @@ void PixelConvert::ReadAndDecompress12BitsTo16Bits( /** * \brief Try to deal with RLE 16 Bits. * We assume the RLE has allready been parsed and loaded in - * Uncompressed (through \ref ReadAndDecompressJPEGFile ). + * Decompressed (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 PixelConvert::UncompressRLE16BitsFromRLE8Bits( - int NumberOfFrames, - uint8_t* fixMemUncompressed ) +bool PixelConvert::DecompressRLE16BitsFromRLE8Bits( int NumberOfFrames ) { size_t PixelNumber = XSize * YSize; - size_t fixMemUncompressedSize = XSize * YSize * NumberOfFrames; + size_t uncompressedSize = XSize * YSize * NumberOfFrames; - // We assumed Uncompressed contains the decoded RLE pixels but as + // We assumed Decompressed 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 Uncompressed and hence - // we copy Uncompressed in a safe place, say OldUncompressed. + // per pixel we cannot work in place within Decompressed and hence + // we copy it in a safe place, say copyDecompressed. - uint8_t* OldUncompressed = new uint8_t[ fixMemUncompressedSize * 2 ]; - memmove( OldUncompressed, fixMemUncompressed, fixMemUncompressedSize * 2); + uint8_t* copyDecompressed = new uint8_t[ uncompressedSize * 2 ]; + memmove( copyDecompressed, Decompressed, uncompressedSize * 2 ); - uint8_t* x = fixMemUncompressed; - uint8_t* a = OldUncompressed; + uint8_t* x = Decompressed; + uint8_t* a = copyDecompressed; uint8_t* b = a + PixelNumber; for ( int i = 0; i < NumberOfFrames; i++ ) @@ -173,7 +169,7 @@ bool PixelConvert::UncompressRLE16BitsFromRLE8Bits( } } - delete[] OldUncompressed; + delete[] copyDecompressed; /// \todo check that operator new []didn't fail, and sometimes return false return true; @@ -182,11 +178,18 @@ bool PixelConvert::UncompressRLE16BitsFromRLE8Bits( /** * \brief Implementation of the RLE decoding algorithm for uncompressing * a RLE fragment. [refer to PS 3.5-2003, section G.3.2 p 86] + * @param subDecompressed Sub region of \ref Decompressed where the de + * decoded fragment should be placed. + * @param fragmentSize The length of the binary fragment as found on the disk. + * @param uncompressedSegmentSize The expected length of the fragment ONCE + * decompressed. + * @param fp File Pointer: on entry the position should be the one of + * the fragment to be decoded. */ -bool PixelConvert::ReadAndUncompressRLEFragment( uint8_t* decodedZone, - long fragmentSize, - long uncompressedSegmentSize, - FILE* fp ) +bool PixelConvert::ReadAndDecompressRLEFragment( uint8_t* subDecompressed, + long fragmentSize, + long uncompressedSegmentSize, + FILE* fp ) { int8_t count; long numberOfOutputBytes = 0; @@ -202,9 +205,9 @@ bool PixelConvert::ReadAndUncompressRLEFragment( uint8_t* decodedZone, // signed integer of width N is 2^(N-1) - 1, which for int8_t // is 127]. { - fread( decodedZone, count + 1, 1, fp); - numberOfReadBytes += count + 1; - decodedZone += count + 1; + fread( subDecompressed, count + 1, 1, fp); + numberOfReadBytes += count + 1; + subDecompressed += count + 1; numberOfOutputBytes += count + 1; } else @@ -216,9 +219,9 @@ bool PixelConvert::ReadAndUncompressRLEFragment( uint8_t* decodedZone, numberOfReadBytes += 1; for( int i = 0; i < -count + 1; i++ ) { - decodedZone[i] = newByte; + subDecompressed[i] = newByte; } - decodedZone += -count + 1; + subDecompressed += -count + 1; numberOfOutputBytes += -count + 1; } } @@ -226,8 +229,8 @@ bool PixelConvert::ReadAndUncompressRLEFragment( uint8_t* decodedZone, if ( numberOfReadBytes > fragmentSize ) { - dbg.Verbose(0, "File::gdcm_read_RLE_fragment: we read more " - "bytes than the segment size."); + dbg.Verbose(0, "PixelConvert::ReadAndDecompressRLEFragment: we " + "read more bytes than the segment size."); return false; } } @@ -238,16 +241,13 @@ bool PixelConvert::ReadAndUncompressRLEFragment( uint8_t* decodedZone, * \brief Reads from disk the Pixel Data of 'Run Length Encoded' * Dicom encapsulated file and uncompress it. * @param fp already open File Pointer - * @param image_buffer destination Address (in caller's memory space) * at which the pixel data should be copied * @return Boolean */ -bool PixelConvert::ReadAndDecompressRLEFile( - void* image_buffer, - FILE* fp ) +bool PixelConvert::ReadAndDecompressRLEFile( FILE* fp ) { - uint8_t* im = (uint8_t*)image_buffer; - long uncompressedSegmentSize = XSize * YSize; + uint8_t* subDecompressed = Decompressed; + long decompressedSegmentSize = XSize * YSize; // Loop on the frame[s] for( RLEFramesInfo::RLEFrameList::iterator @@ -259,35 +259,33 @@ bool PixelConvert::ReadAndDecompressRLEFile( for( int k = 1; k <= (*it)->NumberFragments; k++ ) { fseek( fp, (*it)->Offset[k] ,SEEK_SET ); - (void)PixelConvert::ReadAndUncompressRLEFragment( - (uint8_t*) im, (*it)->Length[k], - uncompressedSegmentSize, fp ); - im += uncompressedSegmentSize; + (void)ReadAndDecompressRLEFragment( subDecompressed, + (*it)->Length[k], + decompressedSegmentSize, + fp ); + subDecompressed += decompressedSegmentSize; } } if ( BitsAllocated == 16 ) { // Try to deal with RLE 16 Bits - (void)UncompressRLE16BitsFromRLE8Bits( ZSize, - (uint8_t*) image_buffer); + (void)DecompressRLE16BitsFromRLE8Bits( ZSize ); } return true; } /** - * \brief Swap the bytes, according to swap code. - * \warning not end user intended - * @param im area to deal with + * \brief Swap the bytes, according to \ref SwapCode. */ -void PixelConvert::SwapZone( uint8_t* im ) +void PixelConvert::ConvertSwapZone() { unsigned int i; if( BitsAllocated == 16 ) { - uint16_t* im16 = (uint16_t*)im; + uint16_t* im16 = (uint16_t*)Decompressed; switch( SwapCode ) { case 0: @@ -304,15 +302,16 @@ void PixelConvert::SwapZone( uint8_t* im ) } break; default: - dbg.Verbose( 0, "PixelConvert::SwapZone: SwapCode value " + dbg.Verbose( 0, "PixelConvert::ConvertSwapZone: SwapCode value " "(16 bits) not allowed." ); } } else if( BitsAllocated == 32 ) { uint32_t s32; - uint16_t fort, faible; - uint32_t* im32 = (uint32_t*)im; + uint16_t high; + uint16_t low; + uint32_t* im32 = (uint32_t*)Decompressed; switch ( SwapCode ) { case 0: @@ -321,36 +320,36 @@ void PixelConvert::SwapZone( uint8_t* im ) case 4321: for( i = 0; i < DecompressedSize / 4; i++ ) { - faible = im32[i] & 0x0000ffff; // 4321 - fort = im32[i] >> 16; - fort = ( fort >> 8 ) | ( fort << 8 ); - faible = ( faible >> 8 ) | ( faible << 8); - s32 = faible; - im32[i] = ( s32 << 16 ) | fort; + low = im32[i] & 0x0000ffff; // 4321 + high = im32[i] >> 16; + high = ( high >> 8 ) | ( high << 8 ); + low = ( low >> 8 ) | ( low << 8 ); + s32 = low; + im32[i] = ( s32 << 16 ) | high; } break; case 2143: for( i = 0; i < DecompressedSize / 4; i++ ) { - faible = im32[i] & 0x0000ffff; // 2143 - fort = im32[i] >> 16; - fort = ( fort >> 8 ) | ( fort << 8 ); - faible = ( faible >> 8) | ( faible << 8); - s32 = fort; - im32[i] = ( s32 << 16 ) | faible; + low = im32[i] & 0x0000ffff; // 2143 + high = im32[i] >> 16; + high = ( high >> 8 ) | ( high << 8 ); + low = ( low >> 8 ) | ( low << 8 ); + s32 = high; + im32[i] = ( s32 << 16 ) | low; } break; case 3412: for( i = 0; i < DecompressedSize / 4; i++ ) { - faible = im32[i] & 0x0000ffff; // 3412 - fort = im32[i] >> 16; - s32 = faible; - im32[i] = ( s32 << 16 ) | fort; + low = im32[i] & 0x0000ffff; // 3412 + high = im32[i] >> 16; + s32 = low; + im32[i] = ( s32 << 16 ) | high; } break; default: - dbg.Verbose( 0, "PixelConvert::SwapZone: SwapCode value " + dbg.Verbose( 0, "PixelConvert::ConvertSwapZone: SwapCode value " "(32 bits) not allowed." ); } } @@ -359,11 +358,11 @@ void PixelConvert::SwapZone( uint8_t* im ) /** * \brief Deal with endianity i.e. re-arange bytes inside the integer */ -void PixelConvert::ReorderEndianity( uint8_t* pixelZone ) +void PixelConvert::ConvertReorderEndianity() { if ( BitsAllocated != 8 ) { - SwapZone( pixelZone ); + ConvertSwapZone(); } // Special kludge in order to deal with xmedcon broken images: @@ -372,7 +371,7 @@ void PixelConvert::ReorderEndianity( uint8_t* pixelZone ) && ( ! PixelSign ) ) { int l = (int)( DecompressedSize / ( BitsAllocated / 8 ) ); - uint16_t *deb = (uint16_t *)pixelZone; + uint16_t *deb = (uint16_t *)Decompressed; for(int i = 0; iFragments.begin(); @@ -405,7 +402,7 @@ bool PixelConvert::ReadAndDecompressJPEGFile( if ( IsJPEG2000 ) { - if ( ! gdcm_read_JPEG2000_file( fp, destination ) ) + if ( ! gdcm_read_JPEG2000_file( fp,localDecompressed ) ) { return false; } @@ -413,7 +410,7 @@ bool PixelConvert::ReadAndDecompressJPEGFile( else if ( BitsStored == 8) { // JPEG Lossy : call to IJG 6b - if ( ! gdcm_read_JPEG_file8( fp, destination ) ) + if ( ! gdcm_read_JPEG_file8( fp, localDecompressed ) ) { return false; } @@ -421,7 +418,7 @@ bool PixelConvert::ReadAndDecompressJPEGFile( else if ( BitsStored == 12) { // Reading Fragment pixels - if ( ! gdcm_read_JPEG_file12 ( fp, destination ) ) + if ( ! gdcm_read_JPEG_file12 ( fp, localDecompressed ) ) { return false; } @@ -429,7 +426,7 @@ bool PixelConvert::ReadAndDecompressJPEGFile( else if ( BitsStored == 16) { // Reading Fragment pixels - if ( ! gdcm_read_JPEG_file16 ( fp, destination ) ) + if ( ! gdcm_read_JPEG_file16 ( fp, localDecompressed ) ) { return false; } @@ -438,28 +435,26 @@ bool PixelConvert::ReadAndDecompressJPEGFile( else { // other JPEG lossy not supported - dbg.Error(" File::ReadAndDecompressJPEGFile: unknown jpeg lossy " - " compression "); + dbg.Error("PixelConvert::ReadAndDecompressJPEGFile: unknown " + "jpeg lossy compression "); return false; } - // Advance to next free location in destination + // Advance to next free location in Decompressed // for next fragment decompression (if any) int length = XSize * YSize * SamplesPerPixel; int numberBytes = BitsAllocated / 8; - - destination += length * numberBytes; + + localDecompressed += length * numberBytes; } return true; } /** * \brief Re-arrange the bits within the bytes. - * @param pixelZone zone * @return Boolean */ -bool PixelConvert::ReArrangeBits( uint8_t* pixelZone ) - throw ( FormatError ) +bool PixelConvert::ConvertReArrangeBits() throw ( FormatError ) { if ( BitsStored != BitsAllocated ) { @@ -468,7 +463,7 @@ bool PixelConvert::ReArrangeBits( uint8_t* pixelZone ) { uint16_t mask = 0xffff; mask = mask >> ( BitsAllocated - BitsStored ); - uint16_t* deb = (uint16_t*)pixelZone; + uint16_t* deb = (uint16_t*)Decompressed; for(int i = 0; i> (BitsStored - HighBitPosition - 1)) & mask; @@ -479,7 +474,7 @@ bool PixelConvert::ReArrangeBits( uint8_t* pixelZone ) { uint32_t mask = 0xffffffff; mask = mask >> ( BitsAllocated - BitsStored ); - uint32_t* deb = (uint32_t*)pixelZone; + uint32_t* deb = (uint32_t*)Decompressed; for(int i = 0; i> (BitsStored - HighBitPosition - 1)) & mask; @@ -488,8 +483,8 @@ bool PixelConvert::ReArrangeBits( uint8_t* pixelZone ) } else { - dbg.Verbose(0, "PixelConvert::ReArrangeBits: weird image"); - throw FormatError( "File::ReArrangeBits()", + dbg.Verbose(0, "PixelConvert::ConvertReArrangeBits: weird image"); + throw FormatError( "PixelConvert::ConvertReArrangeBits()", "weird image !?" ); } } @@ -500,10 +495,11 @@ bool PixelConvert::ReArrangeBits( uint8_t* pixelZone ) * \brief Convert (Y plane, cB plane, cR plane) to RGB pixels * \warning Works on all the frames at a time */ -void PixelConvert::ConvertYcBcRPlanesToRGBPixels( uint8_t* destination ) +void PixelConvert::ConvertYcBcRPlanesToRGBPixels() { - uint8_t* oldPixelZone = new uint8_t[ DecompressedSize ]; - memmove( oldPixelZone, destination, DecompressedSize ); + uint8_t* localDecompressed = Decompressed; + uint8_t* copyDecompressed = new uint8_t[ DecompressedSize ]; + memmove( copyDecompressed, localDecompressed, DecompressedSize ); // to see the tricks about YBR_FULL, YBR_FULL_422, // YBR_PARTIAL_422, YBR_ICT, YBR_RCT have a look at : @@ -513,9 +509,9 @@ void PixelConvert::ConvertYcBcRPlanesToRGBPixels( uint8_t* destination ) int l = XSize * YSize; int nbFrames = ZSize; - uint8_t* a = oldPixelZone; - uint8_t* b = oldPixelZone + l; - uint8_t* c = oldPixelZone + l + l; + uint8_t* a = copyDecompressed; + uint8_t* b = copyDecompressed + l; + uint8_t* c = copyDecompressed + l + l; double R, G, B; /// \todo : Replace by the 'well known' integer computation @@ -538,43 +534,48 @@ void PixelConvert::ConvertYcBcRPlanesToRGBPixels( uint8_t* destination ) if (G > 255.0) G = 255.0; if (B > 255.0) B = 255.0; - *(destination++) = (uint8_t)R; - *(destination++) = (uint8_t)G; - *(destination++) = (uint8_t)B; + *(localDecompressed++) = (uint8_t)R; + *(localDecompressed++) = (uint8_t)G; + *(localDecompressed++) = (uint8_t)B; a++; b++; c++; } } - delete[] oldPixelZone; + delete[] copyDecompressed; } /** * \brief Convert (Red plane, Green plane, Blue plane) to RGB pixels * \warning Works on all the frames at a time */ -void PixelConvert::ConvertRGBPlanesToRGBPixels( uint8_t* destination ) +void PixelConvert::ConvertRGBPlanesToRGBPixels() { - uint8_t* oldPixelZone = new uint8_t[ DecompressedSize ]; - memmove( oldPixelZone, destination, DecompressedSize ); + uint8_t* localDecompressed = Decompressed; + uint8_t* copyDecompressed = new uint8_t[ DecompressedSize ]; + memmove( copyDecompressed, localDecompressed, DecompressedSize ); int l = XSize * YSize * ZSize; - uint8_t* a = oldPixelZone; - uint8_t* b = oldPixelZone + l; - uint8_t* c = oldPixelZone + l + l; + uint8_t* a = copyDecompressed; + uint8_t* b = copyDecompressed + l; + uint8_t* c = copyDecompressed + l + l; for (int j = 0; j < l; j++) { - *(destination++) = *(a++); - *(destination++) = *(b++); - *(destination++) = *(c++); + *(localDecompressed++) = *(a++); + *(localDecompressed++) = *(b++); + *(localDecompressed++) = *(c++); } - delete[] oldPixelZone; + delete[] copyDecompressed; } -bool PixelConvert::ReadAndDecompressPixelData( void* destination, FILE* fp ) +bool PixelConvert::ReadAndDecompressPixelData( FILE* fp ) { + ComputeDecompressedImageDataSize(); + if ( HasLUT ) + DecompressedSize *= 3; + AllocateDecompressed(); ////////////////////////////////////////////////// //// First stage: get our hands on the Pixel Data. if ( !fp ) @@ -584,7 +585,7 @@ bool PixelConvert::ReadAndDecompressPixelData( void* destination, FILE* fp ) return false; } - if ( fseek(fp, PixelOffset, SEEK_SET) == -1 ) + if ( fseek( fp, PixelOffset, SEEK_SET ) == -1 ) { dbg.Verbose( 0, "PixelConvert::ReadAndDecompressPixelData: " "unable to find PixelOffset in file." ); @@ -595,11 +596,11 @@ bool PixelConvert::ReadAndDecompressPixelData( void* destination, FILE* fp ) //// Second stage: read from disk dans uncompress. if ( BitsAllocated == 12 ) { - ReadAndDecompress12BitsTo16Bits( (uint8_t*)destination, fp); + ReadAndDecompress12BitsTo16Bits( fp); } else if ( IsUncompressed ) { - size_t ItemRead = fread( destination, PixelDataLength, 1, fp); + size_t ItemRead = fread( Decompressed, PixelDataLength, 1, fp ); if ( ItemRead != 1 ) { dbg.Verbose( 0, "PixelConvert::ReadAndDecompressPixelData: " @@ -609,7 +610,7 @@ bool PixelConvert::ReadAndDecompressPixelData( void* destination, FILE* fp ) } else if ( IsRLELossless ) { - if ( ! ReadAndDecompressRLEFile( destination, fp ) ) + if ( ! ReadAndDecompressRLEFile( fp ) ) { dbg.Verbose( 0, "PixelConvert::ReadAndDecompressPixelData: " "RLE decompressor failed." ); @@ -619,7 +620,7 @@ bool PixelConvert::ReadAndDecompressPixelData( void* destination, FILE* fp ) else { // Default case concerns JPEG family - if ( ! ReadAndDecompressJPEGFile( (uint8_t*)destination, fp ) ) + if ( ! ReadAndDecompressJPEGFile( fp ) ) { dbg.Verbose( 0, "PixelConvert::ReadAndDecompressPixelData: " "JPEG decompressor failed." ); @@ -629,13 +630,14 @@ bool PixelConvert::ReadAndDecompressPixelData( void* destination, FILE* fp ) //////////////////////////////////////////// //// Third stage: twigle the bytes and bits. - ReorderEndianity( (uint8_t*) destination ); - ReArrangeBits( (uint8_t*) destination ); + ConvertReorderEndianity(); + ConvertReArrangeBits(); + ConvertHandleColor(); return true; } -bool PixelConvert::HandleColor( uint8_t* destination ) +void PixelConvert::ConvertHandleColor() { ////////////////////////////////// // Deal with the color decoding i.e. handle: @@ -675,12 +677,10 @@ bool PixelConvert::HandleColor( uint8_t* destination ) // - [Planar 1] AND [Photo C] handled with ConvertYcBcRPlanesToRGBPixels() // - [Planar 2] OR [Photo D] requires LUT intervention. - if ( IsMonochrome - || ( PlanarConfiguration == 2 ) - || IsPaletteColor ) + if ( ! IsDecompressedRGB() ) { // [Planar 2] OR [Photo D]: LUT intervention done outside - return false; + return; } if ( PlanarConfiguration == 1 ) @@ -688,22 +688,36 @@ bool PixelConvert::HandleColor( uint8_t* destination ) if ( IsYBRFull ) { // [Planar 1] AND [Photo C] (remember YBR_FULL_422 acts as RGB) - ConvertYcBcRPlanesToRGBPixels( (uint8_t*)destination ); + ConvertYcBcRPlanesToRGBPixels(); } else { // [Planar 1] AND [Photo C] - ConvertRGBPlanesToRGBPixels( (uint8_t*)destination ); + ConvertRGBPlanesToRGBPixels(); } } // When planarConf is 0, pixels are allready in RGB +} + +/** + * \brief Predicate to know wether the image[s] (once decompressed) is RGB. + * \note See comments of \ref HandleColor + */ +bool PixelConvert::IsDecompressedRGB() +{ + if ( IsMonochrome + || ( PlanarConfiguration == 2 ) + || IsPaletteColor ) + { + return false; + } return true; } void PixelConvert::ComputeDecompressedImageDataSize() { - int bitsAllocated; + int bitsAllocated = BitsAllocated; // Number of "Bits Allocated" is fixed to 16 when it's 12, since // in this case we will expand the image to 16 bits (see // \ref ReadAndDecompress12BitsTo16Bits() ) diff --git a/src/gdcmPixelConvert.h b/src/gdcmPixelConvert.h index 9c67e06a..784c2e0e 100644 --- a/src/gdcmPixelConvert.h +++ b/src/gdcmPixelConvert.h @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmPixelConvert.h,v $ Language: C++ - Date: $Date: 2004/10/13 14:15:30 $ - Version: $Revision: 1.8 $ + Date: $Date: 2004/10/15 10:43:28 $ + Version: $Revision: 1.9 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -68,17 +68,13 @@ friend class File; bool IsMonochrome; bool IsPaletteColor; bool IsYBRFull; + bool HasLUT; -private: - bool ReadAndUncompressRLEFragment( - uint8_t* decodedZone, - long fragmentSize, - long uncompressedSegmentSize, - FILE* fp ); public: PixelConvert(); ~PixelConvert(); + //// Setter accessors: void SetXSize( int xSize ) { XSize = xSize; } void SetYSize( int ySize ) { YSize = ySize; } void SetZSize( int zSize ) { ZSize = zSize; } @@ -112,37 +108,48 @@ public: void SetIsPaletteColor( bool isPaletteColor ) { IsPaletteColor = isPaletteColor; } void SetIsYBRFull( bool isYBRFull ) { IsYBRFull = isYBRFull; } + void SetHasLUT ( bool hasLUT ) { HasLUT = hasLUT; } + + void SetRGBSize( size_t size ) { RGBSize = size; } + void SetDecompressedSize( size_t size ) { DecompressedSize = size; } + //// Getter accessors: uint8_t* GetRGB() { return RGB; } - void SetRGBSize( size_t size ) { RGBSize = size; } size_t GetRGBSize() { return RGBSize; } - void AllocateRGB(); - uint8_t* GetDecompressed() { return Decompressed; } - void SetDecompressedSize( size_t size ) { DecompressedSize = size; } size_t GetDecompressedSize() { return DecompressedSize; } - void AllocateDecompressed(); + + //// Predicates: + bool IsDecompressedRGB(); ////////////////////////////////////////////////////////// -// In progress private: - bool UncompressRLE16BitsFromRLE8Bits( - int NumberOfFrames, - uint8_t* fixMemUncompressed ); + // Use the fp: + bool ReadAndDecompressRLEFragment( + uint8_t* decodedZone, + long fragmentSize, + long uncompressedSegmentSize, + FILE* fp ); + void ReadAndDecompress12BitsTo16Bits( FILE* fp ) throw ( FormatError ); + bool ReadAndDecompressRLEFile( FILE* fp ); + bool ReadAndDecompressJPEGFile( FILE* fp ); + + // In place (within Decompressed and with no fp access) decompression + // or convertion: + bool DecompressRLE16BitsFromRLE8Bits( int NumberOfFrames ); + void ConvertSwapZone(); + void ConvertReorderEndianity(); + bool ConvertReArrangeBits() throw ( FormatError ); + void ConvertRGBPlanesToRGBPixels(); + void ConvertYcBcRPlanesToRGBPixels(); + void ConvertHandleColor(); + void ComputeDecompressedImageDataSize(); - void ReadAndDecompress12BitsTo16Bits( - uint8_t* pixelZone, - FILE* filePtr) throw ( FormatError ); - bool ReadAndDecompressRLEFile( void* image_buffer, FILE* fp ); - bool ReadAndDecompressJPEGFile( uint8_t* destination, FILE* fp ); - void SwapZone( uint8_t* im ); - void ReorderEndianity( uint8_t* pixelZone ); - bool ReArrangeBits( uint8_t* pixelZone ) throw ( FormatError ); - void ConvertRGBPlanesToRGBPixels( uint8_t* destination ); - void ConvertYcBcRPlanesToRGBPixels( uint8_t* destination ); + void AllocateRGB(); + void AllocateDecompressed(); public: - bool ReadAndDecompressPixelData( void* destination, FILE* fp ); - bool HandleColor( uint8_t* destination ); +// In progress + bool ReadAndDecompressPixelData( FILE* fp ); void Squeeze(); }; } // end namespace gdcm