X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmPixelConvert.cxx;h=cf3c240aa84d1134816a5367a65cac50fe475bd8;hb=3afc179392ebebe610f7685bc8895b690c2a66aa;hp=2afdb86c089c44217172bbf3344103314c46f655;hpb=80f7a0ffbc39a8a7c47c2a8c6c9a272515d55d6f;p=gdcm.git diff --git a/src/gdcmPixelConvert.cxx b/src/gdcmPixelConvert.cxx index 2afdb86c..cf3c240a 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/22 13:56:46 $ - Version: $Revision: 1.20 $ + Date: $Date: 2004/11/10 18:27:23 $ + Version: $Revision: 1.29 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -25,10 +25,10 @@ #include "gdcmDebug.h" #include "gdcmPixelConvert.h" #include +#include namespace gdcm { - #define str2num(str, typeNum) *((typeNum *)(str)) // For JPEG 2000, body in file gdcmJpeg2000.cxx @@ -106,7 +106,7 @@ void PixelConvert::ReadAndDecompress12BitsTo16Bits( std::ifstream* fp ) { int nbPixels = XSize * YSize; uint16_t* localDecompres = (uint16_t*)Decompressed; - + for( int p = 0; p < nbPixels; p += 2 ) { uint8_t b0, b1, b2; @@ -131,7 +131,7 @@ void PixelConvert::ReadAndDecompress12BitsTo16Bits( std::ifstream* fp ) throw FormatError( "PixelConvert::ReadAndDecompress12BitsTo16Bits()", "Unfound second block" ); } - + // Two steps are necessary to please VC++ // // 2 pixels 12bit = [0xABCDEF] @@ -140,7 +140,7 @@ void PixelConvert::ReadAndDecompress12BitsTo16Bits( std::ifstream* fp ) *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 ? } } @@ -174,8 +174,8 @@ bool PixelConvert::DecompressRLE16BitsFromRLE8Bits( int NumberOfFrames ) { for ( unsigned int j = 0; j < PixelNumber; j++ ) { - *(x++) = *(a++); *(x++) = *(b++); + *(x++) = *(a++); } } @@ -204,7 +204,7 @@ bool PixelConvert::ReadAndDecompressRLEFragment( uint8_t* subDecompressed, int8_t count; long numberOfOutputBytes = 0; long numberOfReadBytes = 0; - + while( numberOfOutputBytes < decompressedSegmentSize ) { fp->read( (char*)&count, 1 ); @@ -268,7 +268,6 @@ bool PixelConvert::ReadAndDecompressRLEFile( std::ifstream* fp ) // Loop on the fragments for( unsigned int k = 1; k <= (*it)->NumberFragments; k++ ) { - //fseek( fp, (*it)->Offset[k] ,SEEK_SET ); fp->seekg( (*it)->Offset[k] , std::ios_base::beg ); (void)ReadAndDecompressRLEFragment( subDecompressed, (*it)->Length[k], @@ -277,13 +276,13 @@ bool PixelConvert::ReadAndDecompressRLEFile( std::ifstream* fp ) subDecompressed += decompressedSegmentSize; } } - + if ( BitsAllocated == 16 ) { // Try to deal with RLE 16 Bits (void)DecompressRLE16BitsFromRLE8Bits( ZSize ); } - + return true; } @@ -293,7 +292,7 @@ bool PixelConvert::ReadAndDecompressRLEFile( std::ifstream* fp ) void PixelConvert::ConvertSwapZone() { unsigned int i; - + if( BitsAllocated == 16 ) { uint16_t* im16 = (uint16_t*)Decompressed; @@ -409,7 +408,6 @@ bool PixelConvert::ReadAndDecompressJPEGFile( std::ifstream* fp ) it != JPEGInfo->Fragments.end(); ++it ) { - //fseek( fp, (*it)->Offset, SEEK_SET ); fp->seekg( (*it)->Offset, std::ios_base::beg); if ( IsJPEG2000 ) @@ -427,7 +425,7 @@ bool PixelConvert::ReadAndDecompressJPEGFile( std::ifstream* fp ) return false; } } - else if ( BitsStored == 12) + else if ( BitsStored <= 12) { // Reading Fragment pixels if ( ! gdcm_read_JPEG_file12 ( fp, localDecompressed ) ) @@ -435,7 +433,7 @@ bool PixelConvert::ReadAndDecompressJPEGFile( std::ifstream* fp ) return false; } } - else if ( BitsStored == 16) + else if ( BitsStored <= 16) { // Reading Fragment pixels if ( ! gdcm_read_JPEG_file16 ( fp, localDecompressed ) ) @@ -451,12 +449,12 @@ bool PixelConvert::ReadAndDecompressJPEGFile( std::ifstream* fp ) "jpeg lossy compression "); return false; } - + // Advance to next free location in Decompressed // for next fragment decompression (if any) int length = XSize * YSize * SamplesPerPixel; int numberBytes = BitsAllocated / 8; - + localDecompressed += length * numberBytes; } return true; @@ -512,7 +510,7 @@ void PixelConvert::ConvertYcBcRPlanesToRGBPixels() 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 : // ftp://medical.nema.org/medical/dicom/final/sup61_ft.pdf @@ -520,17 +518,17 @@ void PixelConvert::ConvertYcBcRPlanesToRGBPixels() // int l = XSize * YSize; int nbFrames = ZSize; - + 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 /// counterpart. Refer to /// http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf /// for code optimisation. - + for ( int i = 0; i < nbFrames; i++ ) { for ( int j = 0; j < l; j++ ) @@ -538,14 +536,14 @@ void PixelConvert::ConvertYcBcRPlanesToRGBPixels() R = 1.164 *(*a-16) + 1.596 *(*c -128) + 0.5; G = 1.164 *(*a-16) - 0.813 *(*c -128) - 0.392 *(*b -128) + 0.5; B = 1.164 *(*a-16) + 2.017 *(*b -128) + 0.5; - + if (R < 0.0) R = 0.0; if (G < 0.0) G = 0.0; if (B < 0.0) B = 0.0; if (R > 255.0) R = 255.0; if (G > 255.0) G = 255.0; if (B > 255.0) B = 255.0; - + *(localDecompressed++) = (uint8_t)R; *(localDecompressed++) = (uint8_t)G; *(localDecompressed++) = (uint8_t)B; @@ -566,13 +564,13 @@ void PixelConvert::ConvertRGBPlanesToRGBPixels() uint8_t* localDecompressed = Decompressed; uint8_t* copyDecompressed = new uint8_t[ DecompressedSize ]; memmove( copyDecompressed, localDecompressed, DecompressedSize ); - + int l = XSize * YSize * ZSize; - + uint8_t* a = copyDecompressed; uint8_t* b = copyDecompressed + l; uint8_t* c = copyDecompressed + l + l; - + for (int j = 0; j < l; j++) { *(localDecompressed++) = *(a++); @@ -590,20 +588,19 @@ bool PixelConvert::ReadAndDecompressPixelData( std::ifstream* fp ) //// First stage: get our hands on the Pixel Data. if ( !fp ) { - dbg.Verbose( 0, "PixelConvert::ReadAndDecompressPixelData: " - "unavailable file pointer." ); + dbg.Verbose( 0, "PixelConvert::ReadAndDecompressPixelData: " + "unavailable file pointer." ); return false; } - - //if ( fseek( fp, PixelOffset, SEEK_SET ) == -1 ) + fp->seekg( PixelOffset, std::ios_base::beg ); if( fp->fail() || fp->eof()) //Fp->gcount() == 1 { - dbg.Verbose( 0, "PixelConvert::ReadAndDecompressPixelData: " - "unable to find PixelOffset in file." ); + dbg.Verbose( 0, "PixelConvert::ReadAndDecompressPixelData: " + "unable to find PixelOffset in file." ); return false; } - + ////////////////////////////////////////////////// //// Second stage: read from disk dans decompress. if ( BitsAllocated == 12 ) @@ -612,7 +609,24 @@ bool PixelConvert::ReadAndDecompressPixelData( std::ifstream* fp ) } else if ( IsDecompressed ) { - fp->read( (char*)Decompressed, PixelDataLength); + // This problem can be found when some obvious informations are found + // after the field containing the image datas. In this case, these + // bad datas are added to the size of the image (in the PixelDataLength + // variable). But DecompressedSize is the right size of the image ! + if( PixelDataLength != DecompressedSize) + { + dbg.Verbose( 0, "PixelConvert::ReadAndDecompressPixelData: " + "Mismatch between PixelConvert and DecompressedSize." ); + } + if( PixelDataLength > DecompressedSize) + { + fp->read( (char*)Decompressed, DecompressedSize); + } + else + { + fp->read( (char*)Decompressed, PixelDataLength); + } + if ( fp->fail() || fp->eof())//Fp->gcount() == 1 { dbg.Verbose( 0, "PixelConvert::ReadAndDecompressPixelData: " @@ -707,9 +721,16 @@ void PixelConvert::ConvertHandleColor() // [Planar 1] AND [Photo C] ConvertRGBPlanesToRGBPixels(); } + return; } - // When planarConf is 0, pixels are allready in RGB + // When planarConf is 0, and RLELossless (forbidden by Dicom norm) + // pixels need to be RGB-fied anyway + if (IsRLELossless) + { + ConvertRGBPlanesToRGBPixels(); + } + // In *normal *case, when planarConf is 0, pixels are already in RGB } /** @@ -719,7 +740,7 @@ void PixelConvert::ConvertHandleColor() bool PixelConvert::IsDecompressedRGB() { if ( IsMonochrome - || ( PlanarConfiguration == 2 ) + || PlanarConfiguration == 2 || IsPaletteColor ) { return false; @@ -752,7 +773,7 @@ void PixelConvert::GrabInformationsFromHeader( Header* header ) { // Just in case some access to a Header element requires disk access. // Note: gdcmDocument::Fp is leaved open after OpenFile. - std::ifstream* fp = header->OpenFile(); + std::ifstream* fp = header->OpenFile(); // Number of Bits Allocated for storing a Pixel is defaulted to 16 // when absent from the header. BitsAllocated = header->GetBitsAllocated(); @@ -834,11 +855,9 @@ void PixelConvert::GrabInformationsFromHeader( Header* header ) DocEntry* lutRedDataEntry = header->GetDocEntryByNumber( 0x0028, 0x1201 ); LutRedData = new uint8_t[ lutRedDataEntry->GetLength() ]; - //fseek( fp, lutRedDataEntry->GetOffset() ,SEEK_SET ); fp->seekg( lutRedDataEntry->GetOffset() ,std::ios_base::beg ); - fp->read( (char*)LutRedData, (size_t)lutRedDataEntry->GetLength()); - //if ( numberItem != 1 ) - if ( fp->fail() || fp->eof())//Fp->gcount() == 1 + fp->read( (char*)LutRedData, (size_t)lutRedDataEntry->GetLength()); + if ( fp->fail() || fp->eof())//Fp->gcount() == 1 { dbg.Verbose(0, "PixelConvert::GrabInformationsFromHeader: " "unable to read red LUT data" ); @@ -854,11 +873,9 @@ void PixelConvert::GrabInformationsFromHeader( Header* header ) DocEntry* lutGreenDataEntry = header->GetDocEntryByNumber( 0x0028, 0x1202 ); LutGreenData = new uint8_t[ lutGreenDataEntry->GetLength() ]; - //fseek( fp, lutGreenDataEntry->GetOffset() ,SEEK_SET ); fp->seekg( lutGreenDataEntry->GetOffset() , std::ios_base::beg ); - fp->read( (char*)LutGreenData, (size_t)lutGreenDataEntry->GetLength() ); - //if ( numberItem != 1 ) - if ( fp->fail() || fp->eof())//Fp->gcount() == 1 + fp->read( (char*)LutGreenData, (size_t)lutGreenDataEntry->GetLength() ); + if ( fp->fail() || fp->eof())//Fp->gcount() == 1 { dbg.Verbose(0, "PixelConvert::GrabInformationsFromHeader: " "unable to read green LUT data" ); @@ -874,11 +891,9 @@ void PixelConvert::GrabInformationsFromHeader( Header* header ) DocEntry* lutBlueDataEntry = header->GetDocEntryByNumber( 0x0028, 0x1203 ); LutBlueData = new uint8_t[ lutBlueDataEntry->GetLength() ]; - //fseek( fp, lutBlueDataEntry->GetOffset() ,SEEK_SET ); fp->seekg( lutBlueDataEntry->GetOffset() , std::ios_base::beg ); fp->read( (char*)LutBlueData, (size_t)lutBlueDataEntry->GetLength() ); - //if ( numberItem != 1 ) - if ( fp->fail() || fp->eof())//Fp->gcount() == 1 + if ( fp->fail() || fp->eof())//Fp->gcount() == 1 { dbg.Verbose(0, "PixelConvert::GrabInformationsFromHeader: " "unable to read blue LUT data" ); @@ -887,7 +902,7 @@ void PixelConvert::GrabInformationsFromHeader( Header* header ) } } - header->CloseFile(); + if(fp) header->CloseFile(); } /** @@ -919,9 +934,9 @@ void PixelConvert::BuildLUTRGBA() return; } - if ( ( LutRedDescriptor == GDCM_UNFOUND ) - || ( LutGreenDescriptor == GDCM_UNFOUND ) - || ( LutBlueDescriptor == GDCM_UNFOUND ) ) + if ( LutRedDescriptor == GDCM_UNFOUND + || LutGreenDescriptor == GDCM_UNFOUND + || LutBlueDescriptor == GDCM_UNFOUND ) { return; } @@ -1032,7 +1047,7 @@ bool PixelConvert::BuildRGBImage() { if ( RGB ) { - // The job is allready done. + // The job is already done. return true; }