X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmPixelReadConvert.cxx;h=3e4a1e346c8b0db4cc26618b18ec9bc0e4759363;hb=fb3bc19d96ec0bf38de3a466208a891a799f4797;hp=1b4c6f3c17275f147fac7b1c90653149f0ea03bb;hpb=7d8c2400914483dd3a89e6581044c64c977445ff;p=gdcm.git diff --git a/src/gdcmPixelReadConvert.cxx b/src/gdcmPixelReadConvert.cxx index 1b4c6f3c..3e4a1e34 100644 --- a/src/gdcmPixelReadConvert.cxx +++ b/src/gdcmPixelReadConvert.cxx @@ -1,10 +1,10 @@ /*========================================================================= - + Program: gdcm Module: $RCSfile: gdcmPixelReadConvert.cxx,v $ Language: C++ - Date: $Date: 2005/06/15 19:59:39 $ - Version: $Revision: 1.66 $ + Date: $Date: 2005/09/07 14:12:23 $ + Version: $Revision: 1.77 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -50,6 +50,10 @@ PixelReadConvert::PixelReadConvert() LutRedData = 0; LutGreenData = 0; LutBlueData = 0; + RLEInfo = 0; + JPEGInfo = 0; + UserFunction = 0; + FileInternal = 0; } /// Canonical Destructor @@ -107,7 +111,7 @@ void PixelReadConvert::GrabInformationsFromFile( File *file ) YSize = file->GetYSize(); ZSize = file->GetZSize(); SamplesPerPixel = file->GetSamplesPerPixel(); - PixelSize = file->GetPixelSize(); + //PixelSize = file->GetPixelSize(); Useless PixelSign = file->IsSignedPixelData(); SwapCode = file->GetSwapCode(); std::string ts = file->GetTransferSyntax(); @@ -167,7 +171,7 @@ void PixelReadConvert::GrabInformationsFromFile( File *file ) LutRedData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1201 ); if ( ! LutRedData ) { - gdcmWarningMacro( "Unable to read Red LUT data" ); + gdcmWarningMacro( "Unable to read Red Palette Color Lookup Table data" ); } // //// Green round: @@ -175,7 +179,7 @@ void PixelReadConvert::GrabInformationsFromFile( File *file ) LutGreenData = (uint8_t*)file->GetEntryBinArea(0x0028, 0x1202 ); if ( ! LutGreenData) { - gdcmWarningMacro( "Unable to read Green LUT data" ); + gdcmWarningMacro( "Unable to read Green Palette Color Lookup Table data" ); } // //// Blue round: @@ -183,9 +187,10 @@ void PixelReadConvert::GrabInformationsFromFile( File *file ) LutBlueData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1203 ); if ( ! LutBlueData ) { - gdcmWarningMacro( "Unable to read Blue LUT data" ); + gdcmWarningMacro( "Unable to read Blue Palette Color Lookup Table data" ); } } + FileInternal = file; ComputeRawAndRGBSizes(); } @@ -207,7 +212,7 @@ bool PixelReadConvert::ReadAndDecompressPixelData( std::ifstream *fp ) } fp->seekg( PixelOffset, std::ios::beg ); - if( fp->fail() || fp->eof()) + if ( fp->fail() || fp->eof() ) { gdcmWarningMacro( "Unable to find PixelOffset in file." ); return false; @@ -216,7 +221,7 @@ bool PixelReadConvert::ReadAndDecompressPixelData( std::ifstream *fp ) AllocateRaw(); ////////////////////////////////////////////////// - //// Second stage: read from disk dans decompress. + //// Second stage: read from disk and decompress. if ( BitsAllocated == 12 ) { ReadAndDecompress12BitsTo16Bits( fp); @@ -227,12 +232,12 @@ bool PixelReadConvert::ReadAndDecompressPixelData( std::ifstream *fp ) // after the field containing the image data. In this case, these // bad data are added to the size of the image (in the PixelDataLength // variable). But RawSize is the right size of the image ! - if( PixelDataLength != RawSize) + if ( PixelDataLength != RawSize ) { gdcmWarningMacro( "Mismatch between PixelReadConvert : " << PixelDataLength << " and RawSize : " << RawSize ); } - if( PixelDataLength > RawSize) + if ( PixelDataLength > RawSize ) { fp->read( (char*)Raw, RawSize); } @@ -259,7 +264,8 @@ bool PixelReadConvert::ReadAndDecompressPixelData( std::ifstream *fp ) { //gdcmWarningMacro( "Sorry, MPEG not yet taken into account" ); //return false; - //ReadMPEGFile(fp, Raw, PixelDataLength); // fp has already been seek to start of mpeg + // fp has already been seek to start of mpeg + //ReadMPEGFile(fp, Raw, PixelDataLength); return true; } else @@ -277,6 +283,8 @@ bool PixelReadConvert::ReadAndDecompressPixelData( std::ifstream *fp ) ConvertReorderEndianity(); ConvertReArrangeBits(); ConvertFixGreyLevels(); + if (UserFunction) // user is allowed to Mirror, TopDown, Rotate,...the image + UserFunction( Raw, FileInternal); ConvertHandleColor(); return true; @@ -321,12 +329,14 @@ bool PixelReadConvert::BuildRGBImage() // The job can't be done return false; } + + gdcmWarningMacro( "--> BuildRGBImage" ); // Build RGB Pixels AllocateRGB(); int j; - if( BitsAllocated <= 8) + if ( BitsAllocated <= 8 ) { uint8_t *localRGB = RGB; for (size_t i = 0; i < RawSize; ++i ) @@ -420,7 +430,7 @@ bool PixelReadConvert::ReadAndDecompressJPEGFile( std::ifstream *fp ) assert( !IsJPEGLossless || !IsJPEGLossy || !IsJPEGLS ); // FIXME this is really ugly but it seems I have to load the complete // jpeg2000 stream to use jasper: - // I don't think we'll ever be able to deal with multiple fragments properly + // I don't think we'll ever be able to deal with multiple fragments properly unsigned long inputlength = 0; JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment(); @@ -555,7 +565,7 @@ void PixelReadConvert::BuildLUTRGBA() nbRead = sscanf( LutRedDescriptor.c_str(), "%d\\%d\\%d", &lengthR, &debR, &nbitsR ); - if( nbRead != 3 ) + if ( nbRead != 3 ) { gdcmWarningMacro( "Wrong Red LUT descriptor" ); } @@ -566,7 +576,7 @@ void PixelReadConvert::BuildLUTRGBA() nbRead = sscanf( LutGreenDescriptor.c_str(), "%d\\%d\\%d", &lengthG, &debG, &nbitsG ); - if( nbRead != 3 ) + if ( nbRead != 3 ) { gdcmWarningMacro( "Wrong Green LUT descriptor" ); } @@ -577,7 +587,7 @@ void PixelReadConvert::BuildLUTRGBA() nbRead = sscanf( LutRedDescriptor.c_str(), "%d\\%d\\%d", &lengthB, &debB, &nbitsB ); - if( nbRead != 3 ) + if ( nbRead != 3 ) { gdcmWarningMacro( "Wrong Blue LUT descriptor" ); } @@ -591,7 +601,7 @@ void PixelReadConvert::BuildLUTRGBA() if ( !lengthR ) // if = 2^16, this shall be 0 see : CP-143 lengthR=65536; - if( !lengthG ) // if = 2^16, this shall be 0 + if ( !lengthG ) // if = 2^16, this shall be 0 lengthG=65536; if ( !lengthB ) // if = 2^16, this shall be 0 lengthB=65536; @@ -606,13 +616,14 @@ void PixelReadConvert::BuildLUTRGBA() // ------------------------------------------------------------- - if ( BitsAllocated <= 8) + if ( BitsAllocated <= 8 ) { // forge the 4 * 8 Bits Red/Green/Blue/Alpha LUT LutRGBA = new uint8_t[ 1024 ]; // 256 * 4 (R, G, B, Alpha) if ( !LutRGBA ) return; - + LutItemNumber = 256; + LutItemSize = 8; memset( LutRGBA, 0, 1024 ); int mult; @@ -639,10 +650,14 @@ void PixelReadConvert::BuildLUTRGBA() //take "Subscript of the first Lut Value" (debR,debG,debB) into account! + //FIXME : +1 : to get 'low value' byte + // Trouble expected on Big Endian Processors ? + // 16 BIts Per Pixel Palette Color to be swapped? + a = LutRGBA + 0 + debR; for( i=0; i < lengthR; ++i ) { - *a = LutRedData[i*mult+1]; + *a = LutRedData[i*mult+1]; a += 4; } @@ -659,7 +674,7 @@ void PixelReadConvert::BuildLUTRGBA() *a = LutBlueData[i*mult+1]; a += 4; } - + a = LutRGBA + 3 ; for(i=0; i < 256; ++i) { @@ -683,6 +698,9 @@ void PixelReadConvert::BuildLUTRGBA() return; memset( LutRGBA, 0, 65536*4*2 ); // 16 bits = 2 bytes ;-) + LutItemNumber = 65536; + LutItemSize = 16; + int i; uint16_t *a16; @@ -691,21 +709,21 @@ void PixelReadConvert::BuildLUTRGBA() a16 = (uint16_t*)LutRGBA + 0 + debR; for( i=0; i < lengthR; ++i ) { - *a16 = ((uint16_t*)LutRedData)[i+1]; + *a16 = ((uint16_t*)LutRedData)[i]; a16 += 4; } a16 = (uint16_t*)LutRGBA + 1 + debG; for( i=0; i < lengthG; ++i) { - *a16 = ((uint16_t*)LutGreenData)[i+1]; + *a16 = ((uint16_t*)LutGreenData)[i]; a16 += 4; } a16 = (uint16_t*)LutRGBA + 2 + debB; for(i=0; i < lengthB; ++i) { - *a16 = ((uint16_t*)LutBlueData)[i+1]; + *a16 = ((uint16_t*)LutBlueData)[i]; a16 += 4; } @@ -715,7 +733,8 @@ void PixelReadConvert::BuildLUTRGBA() *a16 = 1; // Alpha component a16 += 4; } -/* +/* Just to 'see' the LUT, at debug time + a16=(uint16_t*)LutRGBA; for (int j=0;j<65536;j++) { @@ -734,7 +753,7 @@ void PixelReadConvert::ConvertSwapZone() { unsigned int i; - if( BitsAllocated == 16 ) + if ( BitsAllocated == 16 ) { uint16_t *im16 = (uint16_t*)Raw; switch( SwapCode ) @@ -753,7 +772,7 @@ void PixelReadConvert::ConvertSwapZone() gdcmWarningMacro("SwapCode value (16 bits) not allowed."); } } - else if( BitsAllocated == 32 ) + else if ( BitsAllocated == 32 ) { uint32_t s32; uint16_t high; @@ -819,7 +838,7 @@ void PixelReadConvert::ConvertReorderEndianity() uint16_t *deb = (uint16_t *)Raw; for(int i = 0; i> ( BitsAllocated - BitsStored ); + // pmask : to mask the 'unused bits' (may contain overlays) + uint16_t pmask = 0xffff; + pmask = pmask >> ( BitsAllocated - BitsStored ); + uint16_t *deb = (uint16_t*)Raw; - for(int i = 0; i> (BitsStored - HighBitPosition - 1)) & mask; - deb++; + for(int i = 0; i> (BitsStored - HighBitPosition - 1)) & pmask; + deb++; + } + } + else // Pixels are signed + { + // smask : to check the 'sign' when BitsStored != BitsAllocated + uint16_t smask = 0x0001; + smask = smask << ( 16 - (BitsAllocated - BitsStored + 1) ); + // nmask : to propagate sign bit on negative values + int16_t nmask = (int16_t)0x8000; + nmask = nmask >> ( BitsAllocated - BitsStored - 1 ); + + for(int i = 0; i> (BitsStored - HighBitPosition - 1); + if ( *deb & smask ) + { + *deb = *deb | nmask; + } + else + { + *deb = *deb & pmask; + } + deb++; + } } } else if ( BitsAllocated == 32 ) { - uint32_t mask = 0xffffffff; - mask = mask >> ( BitsAllocated - BitsStored ); + // pmask : to mask the 'unused bits' (may contain overlays) + uint32_t pmask = 0xffffffff; + pmask = pmask >> ( BitsAllocated - BitsStored ); + uint32_t *deb = (uint32_t*)Raw; - for(int i = 0; i> (BitsStored - HighBitPosition - 1)) & mask; - deb++; + for(int i = 0; i> (BitsStored - HighBitPosition - 1)) & pmask; + deb++; + } + } + else + { + // smask : to check the 'sign' when BitsStored != BitsAllocated + uint32_t smask = 0x00000001; + smask = smask >> ( 32 - (BitsAllocated - BitsStored +1 )); + // nmask : to propagate sign bit on negative values + int32_t nmask = 0x80000000; + nmask = nmask >> ( BitsAllocated - BitsStored -1 ); + + for(int i = 0; i> (BitsStored - HighBitPosition - 1); + if ( *deb & smask ) + *deb = *deb | nmask; + else + *deb = *deb & pmask; + deb++; + } } } else { - gdcmWarningMacro("Weird image"); + gdcmWarningMacro("Weird image (BitsAllocated !=8, 12, 16, 32)"); throw FormatError( "Weird image !?" ); } } @@ -943,6 +1017,8 @@ bool PixelReadConvert::ConvertReArrangeBits() throw ( FormatError ) */ void PixelReadConvert::ConvertRGBPlanesToRGBPixels() { + gdcmWarningMacro("--> ConvertRGBPlanesToRGBPixels"); + uint8_t *localRaw = Raw; uint8_t *copyRaw = new uint8_t[ RawSize ]; memmove( copyRaw, localRaw, RawSize ); @@ -968,6 +1044,17 @@ void PixelReadConvert::ConvertRGBPlanesToRGBPixels() */ void PixelReadConvert::ConvertYcBcRPlanesToRGBPixels() { + // Remarks for YBR newbees : + // YBR_FULL works very much like RGB, i.e. three samples per pixel, + // just the color space is YCbCr instead of RGB. This is particularly useful + // for doppler ultrasound where most of the image is grayscale + // (i.e. only populates the Y components) and Cb and Cr are mostly zero, + // except for the few patches of color on the image. + // On such images, RLE achieves a compression ratio that is much better + // than the compression ratio on an equivalent RGB image. + + gdcmWarningMacro("--> ConvertYcBcRPlanesToRGBPixels"); + uint8_t *localRaw = Raw; uint8_t *copyRaw = new uint8_t[ RawSize ]; memmove( copyRaw, localRaw, RawSize ); @@ -1066,9 +1153,13 @@ void PixelReadConvert::ConvertHandleColor() // - [Planar 1] AND [Photo C] handled with ConvertYcBcRPlanesToRGBPixels() // - [Planar 2] OR [Photo D] requires LUT intervention. + gdcmWarningMacro("--> ConvertHandleColor" + << "Planar Configuration " << PlanarConfiguration ); + if ( ! IsRawRGB() ) { // [Planar 2] OR [Photo D]: LUT intervention done outside + gdcmWarningMacro("--> RawRGB : LUT intervention done outside"); return; } @@ -1077,22 +1168,27 @@ void PixelReadConvert::ConvertHandleColor() if ( IsYBRFull ) { // [Planar 1] AND [Photo C] (remember YBR_FULL_422 acts as RGB) + gdcmWarningMacro("--> YBRFull"); ConvertYcBcRPlanesToRGBPixels(); } else { // [Planar 1] AND [Photo C] + gdcmWarningMacro("--> YBRFull"); ConvertRGBPlanesToRGBPixels(); } return; } // When planarConf is 0, and RLELossless (forbidden by Dicom norm) - // pixels need to be RGB-fied anyway + // pixels need to be RGB-fyied anyway + if (IsRLELossless) - { + { + gdcmWarningMacro("--> RLE Lossless"); ConvertRGBPlanesToRGBPixels(); } + // In *normal *case, when planarConf is 0, pixels are already in RGB } @@ -1183,14 +1279,3 @@ void PixelReadConvert::Print( std::ostream &os, std::string const &indent ) //----------------------------------------------------------------------------- } // end namespace gdcm - -// NOTES on File internal calls -// User -// ---> GetImageData -// ---> GetImageDataIntoVector -// |---> GetImageDataIntoVectorRaw -// | lut intervention -// User -// ---> GetImageDataRaw -// ---> GetImageDataIntoVectorRaw -