+ if ( fp->fail() || fp->eof() )
+ {
+ throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
+ "Unfound first block" );
+ }
+
+ fp->read( (char*)&b1, 1 );
+ if ( fp->fail() || fp->eof())
+ {
+ throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
+ "Unfound second block" );
+ }
+
+ fp->read( (char*)&b2, 1 );
+ if ( fp->fail() || fp->eof())
+ {
+ throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
+ "Unfound second block" );
+ }
+
+ // Two steps are necessary to please VC++
+ //
+ // 2 pixels 12bit = [0xABCDEF]
+ // 2 pixels 16bit = [0x0ABD] + [0x0FCE]
+ // 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 ?
+ }
+}
+
+/**
+ * \brief Reads from disk the Pixel Data of JPEG Dicom encapsulated
+ * file and decompress it.
+ * @param fp File Pointer
+ * @return Boolean
+ */
+bool PixelReadConvert::ReadAndDecompressJPEGFile( std::ifstream *fp )
+{
+ if ( IsJPEG2000 )
+ {
+ // make sure this is the right JPEG compression
+ 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
+
+ if( ZSize == 1 )
+ {
+ unsigned long inputlength = 0;
+ JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment();
+ while( jpegfrag )
+ {
+ inputlength += jpegfrag->GetLength();
+ jpegfrag = JPEGInfo->GetNextFragment();
+ }
+ gdcmAssertMacro( inputlength != 0);
+ uint8_t *inputdata = new uint8_t[inputlength];
+ char *pinputdata = (char*)inputdata;
+ jpegfrag = JPEGInfo->GetFirstFragment();
+ while( jpegfrag )
+ {
+ fp->seekg( jpegfrag->GetOffset(), std::ios::beg);
+ fp->read(pinputdata, jpegfrag->GetLength());
+ pinputdata += jpegfrag->GetLength();
+ jpegfrag = JPEGInfo->GetNextFragment();
+ }
+ // Warning the inputdata buffer is deleted in the function
+ if ( gdcm_read_JPEG2000_file( Raw,
+ (char*)inputdata, inputlength ) )
+ {
+ return true;
+ }
+ // wow what happen, must be an error
+ gdcmWarningMacro( "gdcm_read_JPEG2000_file() failed ");
+ return false;
+ }
+ else
+ {
+ if( (unsigned int)ZSize != JPEGInfo->GetFragmentCount() )
+ {
+ gdcmErrorMacro( "Sorry GDCM does not handle this type of fragments" );
+ return false;
+ }
+ // Hopefully every dicom fragment is *exactly* the j2k stream
+ JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment();
+ char *praw = (char*)Raw;
+ while( jpegfrag )
+ {
+ unsigned long inputlength = jpegfrag->GetLength();
+ char *inputdata = new char[inputlength];
+ fp->seekg( jpegfrag->GetOffset(), std::ios::beg);
+ fp->read(inputdata, jpegfrag->GetLength());
+ // Warning the inputdata buffer is deleted in the function
+ gdcm_read_JPEG2000_file( praw,
+ inputdata, inputlength) ;
+ praw += XSize*YSize*SamplesPerPixel*(BitsAllocated/8);
+ jpegfrag = JPEGInfo->GetNextFragment();
+ }
+ return true;
+ }
+ }
+ else if ( IsJPEGLS )
+ {
+ // make sure this is the right JPEG compression
+ assert( !IsJPEGLossless || !IsJPEGLossy || !IsJPEG2000 );
+ // WARNING : JPEG-LS is NOT the 'classical' Jpeg Lossless :
+ // [JPEG-LS is the basis for new lossless/near-lossless compression
+ // standard for continuous-tone images intended for JPEG2000. The standard
+ // is based on the LOCO-I algorithm (LOw COmplexity LOssless COmpression
+ // for Images) developed at Hewlett-Packard Laboratories]
+ //
+ // see http://datacompression.info/JPEGLS.shtml
+ //
+#if 0
+ std::cerr << "count:" << JPEGInfo->GetFragmentCount() << std::endl;
+ unsigned long inputlength = 0;
+ JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment();
+ while( jpegfrag )
+ {
+ inputlength += jpegfrag->GetLength();
+ jpegfrag = JPEGInfo->GetNextFragment();
+ }
+ gdcmAssertMacro( inputlength != 0);
+ uint8_t *inputdata = new uint8_t[inputlength];
+ char *pinputdata = (char*)inputdata;
+ jpegfrag = JPEGInfo->GetFirstFragment();
+ while( jpegfrag )
+ {
+ fp->seekg( jpegfrag->GetOffset(), std::ios::beg);
+ fp->read(pinputdata, jpegfrag->GetLength());
+ pinputdata += jpegfrag->GetLength();
+ jpegfrag = JPEGInfo->GetNextFragment();
+ }
+
+ //fp->read((char*)Raw, PixelDataLength);
+
+ std::ofstream out("/tmp/jpegls.jpg");
+ out.write((char*)inputdata, inputlength);
+ out.close();
+ delete[] inputdata;
+#endif
+
+ gdcmWarningMacro( "Sorry, JPEG-LS not yet taken into account" );
+ fp->seekg( JPEGInfo->GetFirstFragment()->GetOffset(), std::ios::beg);
+// if ( ! gdcm_read_JPEGLS_file( fp,Raw ) )
+ return false;
+ }
+ else
+ {
+ // make sure this is the right JPEG compression
+ assert( !IsJPEGLS || !IsJPEG2000 );
+ // Precompute the offset localRaw will be shifted with
+ int length = XSize * YSize * ZSize * SamplesPerPixel;
+ int numberBytes = BitsAllocated / 8;
+
+ // to avoid major troubles when BitsStored == 8 && BitsAllocated==16 !
+ int dummy;
+ if (BitsStored == 8 && BitsAllocated==16)
+ dummy = 16;
+ else
+ dummy = BitsStored;
+ JPEGInfo->DecompressFromFile(fp, Raw, dummy, numberBytes, length );
+ return true;
+ }
+}
+
+/**
+ * \brief Build Red/Green/Blue/Alpha LUT from File when :
+ * - (0028,0004) : Photometric Interpretation == [PALETTE COLOR ]
+ * and
+ * - (0028,1101),(0028,1102),(0028,1102)
+ * xxx Palette Color Lookup Table Descriptor are found
+ * and
+ * - (0028,1201),(0028,1202),(0028,1202)
+ * xxx Palette Color Lookup Table Data - are found
+ * \warning does NOT deal with :
+ * - 0028 1100 Gray Lookup Table Descriptor (Retired)
+ * - 0028 1221 Segmented Red Palette Color Lookup Table Data
+ * - 0028 1222 Segmented Green Palette Color Lookup Table Data
+ * - 0028 1223 Segmented Blue Palette Color Lookup Table Data
+ * no known Dicom reader deals with them :-(
+ * @return a RGBA Lookup Table
+ */
+void PixelReadConvert::BuildLUTRGBA()
+{
+
+ // Note to code reviewers :
+ // The problem is *much more* complicated, since a lot of manufacturers
+ // Don't follow the norm :
+ // have a look at David Clunie's remark at the end of this .cxx file.
+ if ( LutRGBA )
+
+ {
+ return;
+ }
+ // Not so easy : see
+ // http://www.barre.nom.fr/medical/dicom2/limitations.html#Color%20Lookup%20Tables
+
+ if ( ! IsPaletteColor )
+ {
+ return;
+ }
+
+ if ( LutRedDescriptor == GDCM_UNFOUND
+ || LutGreenDescriptor == GDCM_UNFOUND
+ || LutBlueDescriptor == GDCM_UNFOUND )
+ {
+ gdcmWarningMacro( "(At least) a LUT Descriptor is missing" );
+ return;
+ }
+
+ ////////////////////////////////////////////
+ // Extract the info from the LUT descriptors
+ int lengthR; // Red LUT length in Bytes
+ int debR; // Subscript of the first Lut Value
+ int nbitsR; // Lut item size (in Bits)
+ int nbRead; // nb of items in LUT descriptor (must be = 3)
+
+ nbRead = sscanf( LutRedDescriptor.c_str(),
+ "%d\\%d\\%d",
+ &lengthR, &debR, &nbitsR );
+ if ( nbRead != 3 )
+ {
+ gdcmWarningMacro( "Wrong Red LUT descriptor" );
+ }
+ int lengthG; // Green LUT length in Bytes
+ int debG; // Subscript of the first Lut Value
+ int nbitsG; // Lut item size (in Bits)
+
+ nbRead = sscanf( LutGreenDescriptor.c_str(),
+ "%d\\%d\\%d",
+ &lengthG, &debG, &nbitsG );
+ if ( nbRead != 3 )
+ {
+ gdcmWarningMacro( "Wrong Green LUT descriptor" );
+ }
+
+ int lengthB; // Blue LUT length in Bytes
+ int debB; // Subscript of the first Lut Value
+ int nbitsB; // Lut item size (in Bits)
+ nbRead = sscanf( LutRedDescriptor.c_str(),
+ "%d\\%d\\%d",
+ &lengthB, &debB, &nbitsB );
+ if ( nbRead != 3 )
+ {
+ gdcmWarningMacro( "Wrong Blue LUT descriptor" );
+ }
+
+ gdcmDebugMacro(" lengthR " << lengthR << " debR "
+ << debR << " nbitsR " << nbitsR);
+ gdcmDebugMacro(" lengthG " << lengthG << " debG "
+ << debG << " nbitsG " << nbitsG);
+ gdcmDebugMacro(" lengthB " << lengthB << " debB "
+ << debB << " nbitsB " << nbitsB);
+
+ if ( !lengthR ) // if = 2^16, this shall be 0 see : CP-143
+ lengthR=65536;
+ if ( !lengthG ) // if = 2^16, this shall be 0
+ lengthG=65536;
+ if ( !lengthB ) // if = 2^16, this shall be 0
+ lengthB=65536;
+
+ ////////////////////////////////////////////////////////
+
+ if ( ( ! LutRedData ) || ( ! LutGreenData ) || ( ! LutBlueData ) )
+ {
+ gdcmWarningMacro( "(At least) a LUT is missing" );
+ return;
+ }
+
+ // -------------------------------------------------------------
+
+ 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;
+ if ( ( nbitsR == 16 ) && ( BitsAllocated == 8 ) )
+ {
+ // when LUT item size is different than pixel size
+ mult = 2; // high byte must be = low byte
+ }
+ else