1 /*=========================================================================
4 Module: $RCSfile: gdcmPixelReadConvert.cxx,v $
6 Date: $Date: 2005/10/23 17:51:43 $
7 Version: $Revision: 1.86 $
9 Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10 l'Image). All rights reserved. See Doc/License.txt or
11 http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
13 This software is distributed WITHOUT ANY WARRANTY; without even
14 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 PURPOSE. See the above copyright notices for more information.
17 =========================================================================*/
19 #include "gdcmPixelReadConvert.h"
20 #include "gdcmDebug.h"
22 #include "gdcmGlobal.h"
24 #include "gdcmDocEntry.h"
25 #include "gdcmRLEFramesInfo.h"
26 #include "gdcmJPEGFragmentsInfo.h"
29 #include <stdio.h> //for sscanf
34 //bool ReadMPEGFile (std::ifstream *fp, void *image_buffer, size_t lenght);
35 bool gdcm_read_JPEG2000_file (void* raw,
36 char *inputdata, size_t inputlength);
37 //-----------------------------------------------------------------------------
38 #define str2num(str, typeNum) *((typeNum *)(str))
40 //-----------------------------------------------------------------------------
41 // Constructor / Destructor
43 PixelReadConvert::PixelReadConvert()
59 /// Canonical Destructor
60 PixelReadConvert::~PixelReadConvert()
65 //-----------------------------------------------------------------------------
68 * \brief Predicate to know whether the image[s] (once Raw) is RGB.
69 * \note See comments of \ref ConvertHandleColor
71 bool PixelReadConvert::IsRawRGB()
74 || PlanarConfiguration == 2
82 * \brief Gets various usefull informations from the file header
83 * @param file gdcm::File pointer
85 void PixelReadConvert::GrabInformationsFromFile( File *file )
87 // Number of Bits Allocated for storing a Pixel is defaulted to 16
88 // when absent from the file.
89 BitsAllocated = file->GetBitsAllocated();
90 if ( BitsAllocated == 0 )
95 // Number of "Bits Stored", defaulted to number of "Bits Allocated"
96 // when absent from the file.
97 BitsStored = file->GetBitsStored();
98 if ( BitsStored == 0 )
100 BitsStored = BitsAllocated;
103 // High Bit Position, defaulted to "Bits Allocated" - 1
104 HighBitPosition = file->GetHighBitPosition();
105 if ( HighBitPosition == 0 )
107 HighBitPosition = BitsAllocated - 1;
110 XSize = file->GetXSize();
111 YSize = file->GetYSize();
112 ZSize = file->GetZSize();
113 SamplesPerPixel = file->GetSamplesPerPixel();
114 //PixelSize = file->GetPixelSize(); Useless
115 PixelSign = file->IsSignedPixelData();
116 SwapCode = file->GetSwapCode();
117 std::string ts = file->GetTransferSyntax();
119 ( ! file->IsDicomV3() )
120 || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRLittleEndian
121 || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRBigEndianPrivateGE
122 || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRLittleEndian
123 || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRBigEndian
124 || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::DeflatedExplicitVRLittleEndian;
126 IsPrivateGETransferSyntax =
127 ( Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRBigEndianPrivateGE );
129 IsMPEG = Global::GetTS()->IsMPEG(ts);
130 IsJPEG2000 = Global::GetTS()->IsJPEG2000(ts);
131 IsJPEGLS = Global::GetTS()->IsJPEGLS(ts);
132 IsJPEGLossy = Global::GetTS()->IsJPEGLossy(ts);
133 IsJPEGLossless = Global::GetTS()->IsJPEGLossless(ts);
134 IsRLELossless = Global::GetTS()->IsRLELossless(ts);
136 PixelOffset = file->GetPixelOffset();
137 PixelDataLength = file->GetPixelAreaLength();
138 RLEInfo = file->GetRLEInfo();
139 JPEGInfo = file->GetJPEGInfo();
141 IsMonochrome = file->IsMonochrome();
142 IsMonochrome1 = file->IsMonochrome1();
143 IsPaletteColor = file->IsPaletteColor();
144 IsYBRFull = file->IsYBRFull();
146 PlanarConfiguration = file->GetPlanarConfiguration();
148 /////////////////////////////////////////////////////////////////
150 HasLUT = file->HasLUT();
153 // Just in case some access to a File element requires disk access.
154 LutRedDescriptor = file->GetEntryString( 0x0028, 0x1101 );
155 LutGreenDescriptor = file->GetEntryString( 0x0028, 0x1102 );
156 LutBlueDescriptor = file->GetEntryString( 0x0028, 0x1103 );
158 // The following comment is probabely meaningless, since LUT are *always*
159 // loaded at parsing time, whatever their length is.
161 // Depending on the value of Document::MAX_SIZE_LOAD_ELEMENT_VALUE
162 // [ refer to invocation of Document::SetMaxSizeLoadEntry() in
163 // Document::Document() ], the loading of the value (content) of a
164 // [Bin|Val]Entry occurence migth have been hindered (read simply NOT
165 // loaded). Hence, we first try to obtain the LUTs data from the file
166 // and when this fails we read the LUTs data directly from disk.
167 // \TODO Reading a [Bin|Val]Entry directly from disk is a kludge.
168 // We should NOT bypass the [Bin|Val]Entry class. Instead
169 // an access to an UNLOADED content of a [Bin|Val]Entry occurence
170 // (e.g. DataEntry::GetBinArea()) should force disk access from
171 // within the [Bin|Val]Entry class itself. The only problem
172 // is that the [Bin|Val]Entry is unaware of the FILE* is was
173 // parsed from. Fix that. FIXME.
176 file->LoadEntryBinArea(0x0028, 0x1201);
177 LutRedData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1201 );
180 gdcmWarningMacro("Unable to read Red Palette Color Lookup Table data");
184 file->LoadEntryBinArea(0x0028, 0x1202);
185 LutGreenData = (uint8_t*)file->GetEntryBinArea(0x0028, 0x1202 );
188 gdcmWarningMacro("Unable to read Green Palette Color Lookup Table data");
192 file->LoadEntryBinArea(0x0028, 0x1203);
193 LutBlueData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1203 );
196 gdcmWarningMacro("Unable to read Blue Palette Color Lookup Table data");
201 ComputeRawAndRGBSizes();
204 /// \brief Reads from disk and decompresses Pixels
205 bool PixelReadConvert::ReadAndDecompressPixelData( std::ifstream *fp )
207 // ComputeRawAndRGBSizes is already made by
208 // ::GrabInformationsFromfile. So, the structure sizes are
212 //////////////////////////////////////////////////
213 //// First stage: get our hands on the Pixel Data.
216 gdcmWarningMacro( "Unavailable file pointer." );
220 fp->seekg( PixelOffset, std::ios::beg );
221 if ( fp->fail() || fp->eof() )
223 gdcmWarningMacro( "Unable to find PixelOffset in file." );
229 //////////////////////////////////////////////////
230 //// Second stage: read from disk and decompress.
231 if ( BitsAllocated == 12 )
233 ReadAndDecompress12BitsTo16Bits( fp);
237 // This problem can be found when some obvious informations are found
238 // after the field containing the image data. In this case, these
239 // bad data are added to the size of the image (in the PixelDataLength
240 // variable). But RawSize is the right size of the image !
241 if ( PixelDataLength != RawSize )
243 gdcmWarningMacro( "Mismatch between PixelReadConvert : "
244 << PixelDataLength << " and RawSize : " << RawSize );
246 if ( PixelDataLength > RawSize )
248 fp->read( (char*)Raw, RawSize);
252 fp->read( (char*)Raw, PixelDataLength);
255 if ( fp->fail() || fp->eof())
257 gdcmWarningMacro( "Reading of Raw pixel data failed." );
261 else if ( IsRLELossless )
263 if ( ! RLEInfo->DecompressRLEFile
264 ( fp, Raw, XSize, YSize, ZSize, BitsAllocated ) )
266 gdcmWarningMacro( "RLE decompressor failed." );
272 //gdcmWarningMacro( "Sorry, MPEG not yet taken into account" );
274 // fp has already been seek to start of mpeg
275 //ReadMPEGFile(fp, Raw, PixelDataLength);
280 // Default case concerns JPEG family
281 if ( ! ReadAndDecompressJPEGFile( fp ) )
283 gdcmWarningMacro( "JPEG decompressor failed." );
288 ////////////////////////////////////////////
289 //// Third stage: twigle the bytes and bits.
290 ConvertReorderEndianity();
291 ConvertReArrangeBits();
292 ConvertFixGreyLevels();
293 if (UserFunction) // user is allowed to Mirror, TopDown, Rotate,...the image
294 UserFunction( Raw, FileInternal);
295 ConvertHandleColor();
300 /// Deletes Pixels Area
301 void PixelReadConvert::Squeeze()
317 * \brief Build the RGB image from the Raw image and the LUTs.
319 bool PixelReadConvert::BuildRGBImage()
323 // The job is already done.
329 // The job can't be done
336 // The job can't be done
340 gdcmWarningMacro( "--> BuildRGBImage" );
346 if ( BitsAllocated <= 8 )
348 uint8_t *localRGB = RGB;
349 for (size_t i = 0; i < RawSize; ++i )
352 *localRGB++ = LutRGBA[j];
353 *localRGB++ = LutRGBA[j+1];
354 *localRGB++ = LutRGBA[j+2];
358 else // deal with 16 bits pixels and 16 bits Palette color
360 uint16_t *localRGB = (uint16_t *)RGB;
361 for (size_t i = 0; i < RawSize/2; ++i )
363 j = ((uint16_t *)Raw)[i] * 4;
364 *localRGB++ = ((uint16_t *)LutRGBA)[j];
365 *localRGB++ = ((uint16_t *)LutRGBA)[j+1];
366 *localRGB++ = ((uint16_t *)LutRGBA)[j+2];
373 //-----------------------------------------------------------------------------
376 //-----------------------------------------------------------------------------
379 * \brief Read from file a 12 bits per pixel image and decompress it
380 * into a 16 bits per pixel image.
382 void PixelReadConvert::ReadAndDecompress12BitsTo16Bits( std::ifstream *fp )
383 throw ( FormatError )
385 int nbPixels = XSize * YSize;
386 uint16_t *localDecompres = (uint16_t*)Raw;
388 for( int p = 0; p < nbPixels; p += 2 )
392 fp->read( (char*)&b0, 1);
393 if ( fp->fail() || fp->eof() )
395 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
396 "Unfound first block" );
399 fp->read( (char*)&b1, 1 );
400 if ( fp->fail() || fp->eof())
402 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
403 "Unfound second block" );
406 fp->read( (char*)&b2, 1 );
407 if ( fp->fail() || fp->eof())
409 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
410 "Unfound second block" );
413 // Two steps are necessary to please VC++
415 // 2 pixels 12bit = [0xABCDEF]
416 // 2 pixels 16bit = [0x0ABD] + [0x0FCE]
418 *localDecompres++ = ((b0 >> 4) << 8) + ((b0 & 0x0f) << 4) + (b1 & 0x0f);
420 *localDecompres++ = ((b2 & 0x0f) << 8) + ((b1 >> 4) << 4) + (b2 >> 4);
422 /// \todo JPR Troubles expected on Big-Endian processors ?
427 * \brief Reads from disk the Pixel Data of JPEG Dicom encapsulated
428 * file and decompress it.
429 * @param fp File Pointer
432 bool PixelReadConvert::ReadAndDecompressJPEGFile( std::ifstream *fp )
436 // make sure this is the right JPEG compression
437 assert( !IsJPEGLossless || !IsJPEGLossy || !IsJPEGLS );
438 // FIXME this is really ugly but it seems I have to load the complete
439 // jpeg2000 stream to use jasper:
440 // I don't think we'll ever be able to deal with multiple fragments properly
442 unsigned long inputlength = 0;
443 JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment();
446 inputlength += jpegfrag->GetLength();
447 jpegfrag = JPEGInfo->GetNextFragment();
449 gdcmAssertMacro( inputlength != 0);
450 uint8_t *inputdata = new uint8_t[inputlength];
451 char *pinputdata = (char*)inputdata;
452 jpegfrag = JPEGInfo->GetFirstFragment();
455 fp->seekg( jpegfrag->GetOffset(), std::ios::beg);
456 fp->read(pinputdata, jpegfrag->GetLength());
457 pinputdata += jpegfrag->GetLength();
458 jpegfrag = JPEGInfo->GetNextFragment();
460 // Warning the inputdata buffer is delete in the function
461 if ( ! gdcm_read_JPEG2000_file( Raw,
462 (char*)inputdata, inputlength ) )
466 // wow what happen, must be an error
471 // make sure this is the right JPEG compression
472 assert( !IsJPEGLossless || !IsJPEGLossy || !IsJPEG2000 );
473 // WARNING : JPEG-LS is NOT the 'classical' Jpeg Lossless :
474 // [JPEG-LS is the basis for new lossless/near-lossless compression
475 // standard for continuous-tone images intended for JPEG2000. The standard
476 // is based on the LOCO-I algorithm (LOw COmplexity LOssless COmpression
477 // for Images) developed at Hewlett-Packard Laboratories]
479 // see http://datacompression.info/JPEGLS.shtml
482 std::cerr << "count:" << JPEGInfo->GetFragmentCount() << std::endl;
483 unsigned long inputlength = 0;
484 JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment();
487 inputlength += jpegfrag->GetLength();
488 jpegfrag = JPEGInfo->GetNextFragment();
490 gdcmAssertMacro( inputlength != 0);
491 uint8_t *inputdata = new uint8_t[inputlength];
492 char *pinputdata = (char*)inputdata;
493 jpegfrag = JPEGInfo->GetFirstFragment();
496 fp->seekg( jpegfrag->GetOffset(), std::ios::beg);
497 fp->read(pinputdata, jpegfrag->GetLength());
498 pinputdata += jpegfrag->GetLength();
499 jpegfrag = JPEGInfo->GetNextFragment();
502 //fp->read((char*)Raw, PixelDataLength);
504 std::ofstream out("/tmp/jpegls.jpg");
505 out.write((char*)inputdata, inputlength);
510 gdcmWarningMacro( "Sorry, JPEG-LS not yet taken into account" );
511 fp->seekg( JPEGInfo->GetFirstFragment()->GetOffset(), std::ios::beg);
512 // if ( ! gdcm_read_JPEGLS_file( fp,Raw ) )
517 // make sure this is the right JPEG compression
518 assert( !IsJPEGLS || !IsJPEG2000 );
519 // Precompute the offset localRaw will be shifted with
520 int length = XSize * YSize * SamplesPerPixel;
521 int numberBytes = BitsAllocated / 8;
523 JPEGInfo->DecompressFromFile(fp, Raw, BitsStored, numberBytes, length );
529 * \brief Build Red/Green/Blue/Alpha LUT from File when :
530 * - (0028,0004) : Photometric Interpretation == [PALETTE COLOR ]
532 * - (0028,1101),(0028,1102),(0028,1102)
533 * xxx Palette Color Lookup Table Descriptor are found
535 * - (0028,1201),(0028,1202),(0028,1202)
536 * xxx Palette Color Lookup Table Data - are found
537 * \warning does NOT deal with :
538 * - 0028 1100 Gray Lookup Table Descriptor (Retired)
539 * - 0028 1221 Segmented Red Palette Color Lookup Table Data
540 * - 0028 1222 Segmented Green Palette Color Lookup Table Data
541 * - 0028 1223 Segmented Blue Palette Color Lookup Table Data
542 * no known Dicom reader deals with them :-(
543 * @return a RGBA Lookup Table
545 void PixelReadConvert::BuildLUTRGBA()
548 // Note to code reviewers :
549 // The problem is *much more* complicated, since a lot of manufacturers
550 // Don't follow the norm :
551 // have a look at David Clunie's remark at the end of this .cxx file.
558 // http://www.barre.nom.fr/medical/dicom2/limitations.html#Color%20Lookup%20Tables
560 if ( ! IsPaletteColor )
565 if ( LutRedDescriptor == GDCM_UNFOUND
566 || LutGreenDescriptor == GDCM_UNFOUND
567 || LutBlueDescriptor == GDCM_UNFOUND )
569 gdcmWarningMacro( "(At least) a LUT Descriptor is missing" );
573 ////////////////////////////////////////////
574 // Extract the info from the LUT descriptors
575 int lengthR; // Red LUT length in Bytes
576 int debR; // Subscript of the first Lut Value
577 int nbitsR; // Lut item size (in Bits)
578 int nbRead; // nb of items in LUT descriptor (must be = 3)
580 nbRead = sscanf( LutRedDescriptor.c_str(),
582 &lengthR, &debR, &nbitsR );
585 gdcmWarningMacro( "Wrong Red LUT descriptor" );
587 int lengthG; // Green LUT length in Bytes
588 int debG; // Subscript of the first Lut Value
589 int nbitsG; // Lut item size (in Bits)
591 nbRead = sscanf( LutGreenDescriptor.c_str(),
593 &lengthG, &debG, &nbitsG );
596 gdcmWarningMacro( "Wrong Green LUT descriptor" );
599 int lengthB; // Blue LUT length in Bytes
600 int debB; // Subscript of the first Lut Value
601 int nbitsB; // Lut item size (in Bits)
602 nbRead = sscanf( LutRedDescriptor.c_str(),
604 &lengthB, &debB, &nbitsB );
607 gdcmWarningMacro( "Wrong Blue LUT descriptor" );
610 gdcmWarningMacro(" lengthR " << lengthR << " debR "
611 << debR << " nbitsR " << nbitsR);
612 gdcmWarningMacro(" lengthG " << lengthG << " debG "
613 << debG << " nbitsG " << nbitsG);
614 gdcmWarningMacro(" lengthB " << lengthB << " debB "
615 << debB << " nbitsB " << nbitsB);
617 if ( !lengthR ) // if = 2^16, this shall be 0 see : CP-143
619 if ( !lengthG ) // if = 2^16, this shall be 0
621 if ( !lengthB ) // if = 2^16, this shall be 0
624 ////////////////////////////////////////////////////////
626 if ( ( ! LutRedData ) || ( ! LutGreenData ) || ( ! LutBlueData ) )
628 gdcmWarningMacro( "(At least) a LUT is missing" );
632 // -------------------------------------------------------------
634 if ( BitsAllocated <= 8 )
636 // forge the 4 * 8 Bits Red/Green/Blue/Alpha LUT
637 LutRGBA = new uint8_t[ 1024 ]; // 256 * 4 (R, G, B, Alpha)
642 memset( LutRGBA, 0, 1024 );
645 if ( ( nbitsR == 16 ) && ( BitsAllocated == 8 ) )
647 // when LUT item size is different than pixel size
648 mult = 2; // high byte must be = low byte
652 // See PS 3.3-2003 C.11.1.1.2 p 619
656 // if we get a black image, let's just remove the '+1'
657 // from 'i*mult+1' and check again
658 // if it works, we shall have to check the 3 Palettes
659 // to see which byte is ==0 (first one, or second one)
661 // We give up the checking to avoid some (useless ?) overhead
662 // (optimistic asumption)
666 //take "Subscript of the first Lut Value" (debR,debG,debB) into account!
668 //FIXME : +1 : to get 'low value' byte
669 // Trouble expected on Big Endian Processors ?
670 // 16 BIts Per Pixel Palette Color to be swapped?
672 a = LutRGBA + 0 + debR;
673 for( i=0; i < lengthR; ++i )
675 *a = LutRedData[i*mult+1];
679 a = LutRGBA + 1 + debG;
680 for( i=0; i < lengthG; ++i)
682 *a = LutGreenData[i*mult+1];
686 a = LutRGBA + 2 + debB;
687 for(i=0; i < lengthB; ++i)
689 *a = LutBlueData[i*mult+1];
694 for(i=0; i < 256; ++i)
696 *a = 1; // Alpha component
702 // Probabely the same stuff is to be done for 16 Bits Pixels
703 // with 65536 entries LUT ?!?
704 // Still looking for accurate info on the web :-(
706 gdcmWarningMacro( "Sorry Palette Color Lookup Tables not yet dealt with"
707 << " for 16 Bits Per Pixel images" );
709 // forge the 4 * 16 Bits Red/Green/Blue/Alpha LUT
711 LutRGBA = (uint8_t *)new uint16_t[ 65536*4 ]; // 2^16 * 4 (R, G, B, Alpha)
714 memset( LutRGBA, 0, 65536*4*2 ); // 16 bits = 2 bytes ;-)
716 LutItemNumber = 65536;
722 //take "Subscript of the first Lut Value" (debR,debG,debB) into account!
724 a16 = (uint16_t*)LutRGBA + 0 + debR;
725 for( i=0; i < lengthR; ++i )
727 *a16 = ((uint16_t*)LutRedData)[i];
731 a16 = (uint16_t*)LutRGBA + 1 + debG;
732 for( i=0; i < lengthG; ++i)
734 *a16 = ((uint16_t*)LutGreenData)[i];
738 a16 = (uint16_t*)LutRGBA + 2 + debB;
739 for(i=0; i < lengthB; ++i)
741 *a16 = ((uint16_t*)LutBlueData)[i];
745 a16 = (uint16_t*)LutRGBA + 3 ;
746 for(i=0; i < 65536; ++i)
748 *a16 = 1; // Alpha component
751 /* Just to 'see' the LUT, at debug time
752 // Don't remove this commented out code.
754 a16=(uint16_t*)LutRGBA;
755 for (int j=0;j<65536;j++)
757 std::cout << *a16 << " " << *(a16+1) << " "
758 << *(a16+2) << " " << *(a16+3) << std::endl;
766 * \brief Swap the bytes, according to \ref SwapCode.
768 void PixelReadConvert::ConvertSwapZone()
771 uint16_t localSwapCode = SwapCode;
773 // If this file is 'ImplicitVR BigEndian PrivateGE Transfer Syntax',
774 // then the header is in little endian format and the pixel data is in
775 // big endian format. When reading the header, GDCM has already established
776 // a byte swapping code suitable for this machine to read the
777 // header. In TS::ImplicitVRBigEndianPrivateGE, this code will need
778 // to be switched in order to read the pixel data. This must be
779 // done REGARDLESS of the processor endianess!
781 // Example: Assume we are on a little endian machine. When
782 // GDCM reads the header, the header will match the machine
783 // endianess and the swap code will be established as a no-op.
784 // When GDCM reaches the pixel data, it will need to switch the
785 // swap code to do big endian to little endian conversion.
787 // Now, assume we are on a big endian machine. When GDCM reads the
788 // header, the header will be recognized as a different endianess
789 // than the machine endianess, and a swap code will be established
790 // to convert from little endian to big endian. When GDCM readers
791 // the pixel data, the pixel data endianess will now match the
792 // machine endianess. But we currently have a swap code that
793 // converts from little endian to big endian. In this case, we
794 // need to switch the swap code to a no-op.
796 // Therefore, in either case, if the file is in
797 // 'ImplicitVR BigEndian PrivateGE Transfer Syntax', then GDCM needs to switch
798 // the byte swapping code when entering the pixel data.
800 /* //Let me check something.
801 //I wait for the Dashboard !
802 if ( IsPrivateGETransferSyntax )
804 // PrivateGETransferSyntax only exists for 'true' Dicom images
805 // we assume there is no 'exotic' 32 bits endianess!
806 switch (localSwapCode)
809 localSwapCode = 4321;
812 localSwapCode = 1234;
817 if ( BitsAllocated == 16 )
819 uint16_t *im16 = (uint16_t*)Raw;
820 switch( localSwapCode )
827 for( i = 0; i < RawSize / 2; i++ )
829 im16[i]= (im16[i] >> 8) | (im16[i] << 8 );
833 gdcmWarningMacro("SwapCode value (16 bits) not allowed.");
836 else if ( BitsAllocated == 32 )
841 uint32_t *im32 = (uint32_t*)Raw;
842 switch ( localSwapCode )
847 for( i = 0; i < RawSize / 4; i++ )
849 low = im32[i] & 0x0000ffff; // 4321
850 high = im32[i] >> 16;
851 high = ( high >> 8 ) | ( high << 8 );
852 low = ( low >> 8 ) | ( low << 8 );
854 im32[i] = ( s32 << 16 ) | high;
858 for( i = 0; i < RawSize / 4; i++ )
860 low = im32[i] & 0x0000ffff; // 2143
861 high = im32[i] >> 16;
862 high = ( high >> 8 ) | ( high << 8 );
863 low = ( low >> 8 ) | ( low << 8 );
865 im32[i] = ( s32 << 16 ) | low;
869 for( i = 0; i < RawSize / 4; i++ )
871 low = im32[i] & 0x0000ffff; // 3412
872 high = im32[i] >> 16;
874 im32[i] = ( s32 << 16 ) | high;
878 gdcmWarningMacro("SwapCode value (32 bits) not allowed." );
884 * \brief Deal with endianness i.e. re-arange bytes inside the integer
886 void PixelReadConvert::ConvertReorderEndianity()
888 if ( BitsAllocated != 8 )
893 // Special kludge in order to deal with xmedcon broken images:
894 if ( BitsAllocated == 16
895 && BitsStored < BitsAllocated
898 int l = (int)( RawSize / ( BitsAllocated / 8 ) );
899 uint16_t *deb = (uint16_t *)Raw;
900 for(int i = 0; i<l; i++)
902 if ( *deb == 0xffff )
912 * \brief Deal with Grey levels i.e. re-arange them
913 * to have low values = dark, high values = bright
915 void PixelReadConvert::ConvertFixGreyLevels()
920 uint32_t i; // to please M$VC6
925 if ( BitsAllocated == 8 )
927 uint8_t *deb = (uint8_t *)Raw;
928 for (i=0; i<RawSize; i++)
936 if ( BitsAllocated == 16 )
939 for (j=0; j<BitsStored-1; j++)
941 mask = (mask << 1) +1; // will be fff when BitsStored=12
944 uint16_t *deb = (uint16_t *)Raw;
945 for (i=0; i<RawSize/2; i++)
955 if ( BitsAllocated == 8 )
957 uint8_t smask8 = 255;
958 uint8_t *deb = (uint8_t *)Raw;
959 for (i=0; i<RawSize; i++)
961 *deb = smask8 - *deb;
966 if ( BitsAllocated == 16 )
968 uint16_t smask16 = 65535;
969 uint16_t *deb = (uint16_t *)Raw;
970 for (i=0; i<RawSize/2; i++)
972 *deb = smask16 - *deb;
981 * \brief Re-arrange the bits within the bytes.
982 * @return Boolean always true
984 bool PixelReadConvert::ConvertReArrangeBits() throw ( FormatError )
987 if ( BitsStored != BitsAllocated )
989 int l = (int)( RawSize / ( BitsAllocated / 8 ) );
990 if ( BitsAllocated == 16 )
992 // pmask : to mask the 'unused bits' (may contain overlays)
993 uint16_t pmask = 0xffff;
994 pmask = pmask >> ( BitsAllocated - BitsStored );
996 uint16_t *deb = (uint16_t*)Raw;
998 if ( !PixelSign ) // Pixels are unsigned
1000 for(int i = 0; i<l; i++)
1002 *deb = (*deb >> (BitsStored - HighBitPosition - 1)) & pmask;
1006 else // Pixels are signed
1008 // smask : to check the 'sign' when BitsStored != BitsAllocated
1009 uint16_t smask = 0x0001;
1010 smask = smask << ( 16 - (BitsAllocated - BitsStored + 1) );
1011 // nmask : to propagate sign bit on negative values
1012 int16_t nmask = (int16_t)0x8000;
1013 nmask = nmask >> ( BitsAllocated - BitsStored - 1 );
1015 for(int i = 0; i<l; i++)
1017 *deb = *deb >> (BitsStored - HighBitPosition - 1);
1020 *deb = *deb | nmask;
1024 *deb = *deb & pmask;
1030 else if ( BitsAllocated == 32 )
1032 // pmask : to mask the 'unused bits' (may contain overlays)
1033 uint32_t pmask = 0xffffffff;
1034 pmask = pmask >> ( BitsAllocated - BitsStored );
1036 uint32_t *deb = (uint32_t*)Raw;
1040 for(int i = 0; i<l; i++)
1042 *deb = (*deb >> (BitsStored - HighBitPosition - 1)) & pmask;
1048 // smask : to check the 'sign' when BitsStored != BitsAllocated
1049 uint32_t smask = 0x00000001;
1050 smask = smask >> ( 32 - (BitsAllocated - BitsStored +1 ));
1051 // nmask : to propagate sign bit on negative values
1052 int32_t nmask = 0x80000000;
1053 nmask = nmask >> ( BitsAllocated - BitsStored -1 );
1055 for(int i = 0; i<l; i++)
1057 *deb = *deb >> (BitsStored - HighBitPosition - 1);
1059 *deb = *deb | nmask;
1061 *deb = *deb & pmask;
1068 gdcmWarningMacro("Weird image (BitsAllocated !=8, 12, 16, 32)");
1069 throw FormatError( "Weird image !?" );
1076 * \brief Convert (Red plane, Green plane, Blue plane) to RGB pixels
1077 * \warning Works on all the frames at a time
1079 void PixelReadConvert::ConvertRGBPlanesToRGBPixels()
1081 gdcmWarningMacro("--> ConvertRGBPlanesToRGBPixels");
1083 uint8_t *localRaw = Raw;
1084 uint8_t *copyRaw = new uint8_t[ RawSize ];
1085 memmove( copyRaw, localRaw, RawSize );
1087 int l = XSize * YSize * ZSize;
1089 uint8_t *a = copyRaw;
1090 uint8_t *b = copyRaw + l;
1091 uint8_t *c = copyRaw + l + l;
1093 for (int j = 0; j < l; j++)
1095 *(localRaw++) = *(a++);
1096 *(localRaw++) = *(b++);
1097 *(localRaw++) = *(c++);
1103 * \brief Convert (cY plane, cB plane, cR plane) to RGB pixels
1104 * \warning Works on all the frames at a time
1106 void PixelReadConvert::ConvertYcBcRPlanesToRGBPixels()
1108 // Remarks for YBR newbees :
1109 // YBR_FULL works very much like RGB, i.e. three samples per pixel,
1110 // just the color space is YCbCr instead of RGB. This is particularly useful
1111 // for doppler ultrasound where most of the image is grayscale
1112 // (i.e. only populates the Y components) and Cb and Cr are mostly zero,
1113 // except for the few patches of color on the image.
1114 // On such images, RLE achieves a compression ratio that is much better
1115 // than the compression ratio on an equivalent RGB image.
1117 gdcmWarningMacro("--> ConvertYcBcRPlanesToRGBPixels");
1119 uint8_t *localRaw = Raw;
1120 uint8_t *copyRaw = new uint8_t[ RawSize ];
1121 memmove( copyRaw, localRaw, RawSize );
1123 // to see the tricks about YBR_FULL, YBR_FULL_422,
1124 // YBR_PARTIAL_422, YBR_ICT, YBR_RCT have a look at :
1125 // ftp://medical.nema.org/medical/dicom/final/sup61_ft.pdf
1126 // and be *very* affraid
1128 int l = XSize * YSize;
1129 int nbFrames = ZSize;
1131 uint8_t *a = copyRaw + 0;
1132 uint8_t *b = copyRaw + l;
1133 uint8_t *c = copyRaw + l+ l;
1136 /// We replaced easy to understand but time consuming floating point
1137 /// computations by the 'well known' integer computation counterpart
1139 /// http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf
1140 /// for code optimisation.
1142 for ( int i = 0; i < nbFrames; i++ )
1144 for ( int j = 0; j < l; j++ )
1146 R = 38142 *(*a-16) + 52298 *(*c -128);
1147 G = 38142 *(*a-16) - 26640 *(*c -128) - 12845 *(*b -128);
1148 B = 38142 *(*a-16) + 66093 *(*b -128);
1157 if (R > 255) R = 255;
1158 if (G > 255) G = 255;
1159 if (B > 255) B = 255;
1161 *(localRaw++) = (uint8_t)R;
1162 *(localRaw++) = (uint8_t)G;
1163 *(localRaw++) = (uint8_t)B;
1172 /// \brief Deals with the color decoding i.e. handle:
1173 /// - R, G, B planes (as opposed to RGB pixels)
1174 /// - YBR (various) encodings.
1175 /// - LUT[s] (or "PALETTE COLOR").
1177 void PixelReadConvert::ConvertHandleColor()
1179 //////////////////////////////////
1180 // Deal with the color decoding i.e. handle:
1181 // - R, G, B planes (as opposed to RGB pixels)
1182 // - YBR (various) encodings.
1183 // - LUT[s] (or "PALETTE COLOR").
1185 // The classification in the color decoding schema is based on the blending
1186 // of two Dicom tags values:
1187 // * "Photometric Interpretation" for which we have the cases:
1188 // - [Photo A] MONOCHROME[1|2] pictures,
1189 // - [Photo B] RGB or YBR_FULL_422 (which acts as RGB),
1190 // - [Photo C] YBR_* (with the above exception of YBR_FULL_422)
1191 // - [Photo D] "PALETTE COLOR" which indicates the presence of LUT[s].
1192 // * "Planar Configuration" for which we have the cases:
1193 // - [Planar 0] 0 then Pixels are already RGB
1194 // - [Planar 1] 1 then we have 3 planes : R, G, B,
1195 // - [Planar 2] 2 then we have 1 gray Plane and 3 LUTs
1197 // Now in theory, one could expect some coherence when blending the above
1198 // cases. For example we should not encounter files belonging at the
1199 // time to case [Planar 0] and case [Photo D].
1200 // Alas, this was only theory ! Because in practice some odd (read ill
1201 // formated Dicom) files (e.g. gdcmData/US-PAL-8-10x-echo.dcm) we encounter:
1202 // - "Planar Configuration" = 0,
1203 // - "Photometric Interpretation" = "PALETTE COLOR".
1204 // Hence gdcm will use the folowing "heuristic" in order to be tolerant
1205 // towards Dicom-non-conformant files:
1206 // << whatever the "Planar Configuration" value might be, a
1207 // "Photometric Interpretation" set to "PALETTE COLOR" forces
1208 // a LUT intervention >>
1210 // Now we are left with the following handling of the cases:
1211 // - [Planar 0] OR [Photo A] no color decoding (since respectively
1212 // Pixels are already RGB and monochrome pictures have no color :),
1213 // - [Planar 1] AND [Photo B] handled with ConvertRGBPlanesToRGBPixels()
1214 // - [Planar 1] AND [Photo C] handled with ConvertYcBcRPlanesToRGBPixels()
1215 // - [Planar 2] OR [Photo D] requires LUT intervention.
1217 gdcmWarningMacro("--> ConvertHandleColor"
1218 << "Planar Configuration " << PlanarConfiguration );
1222 // [Planar 2] OR [Photo D]: LUT intervention done outside
1223 gdcmWarningMacro("--> RawRGB : LUT intervention done outside");
1227 if ( PlanarConfiguration == 1 )
1231 // [Planar 1] AND [Photo C] (remember YBR_FULL_422 acts as RGB)
1232 gdcmWarningMacro("--> YBRFull");
1233 ConvertYcBcRPlanesToRGBPixels();
1237 // [Planar 1] AND [Photo C]
1238 gdcmWarningMacro("--> YBRFull");
1239 ConvertRGBPlanesToRGBPixels();
1244 // When planarConf is 0, and RLELossless (forbidden by Dicom norm)
1245 // pixels need to be RGB-fyied anyway
1249 gdcmWarningMacro("--> RLE Lossless");
1250 ConvertRGBPlanesToRGBPixels();
1253 // In *normal *case, when planarConf is 0, pixels are already in RGB
1256 /// Computes the Pixels Size
1257 void PixelReadConvert::ComputeRawAndRGBSizes()
1259 int bitsAllocated = BitsAllocated;
1260 // Number of "Bits Allocated" is fixed to 16 when it's 12, since
1261 // in this case we will expand the image to 16 bits (see
1262 // \ref ReadAndDecompress12BitsTo16Bits() )
1263 if ( BitsAllocated == 12 )
1268 RawSize = XSize * YSize * ZSize
1269 * ( bitsAllocated / 8 )
1273 RGBSize = 3 * RawSize; // works for 8 and 16 bits per Pixel
1281 /// Allocates room for RGB Pixels
1282 void PixelReadConvert::AllocateRGB()
1286 RGB = new uint8_t[RGBSize];
1289 /// Allocates room for RAW Pixels
1290 void PixelReadConvert::AllocateRaw()
1294 Raw = new uint8_t[RawSize];
1297 //-----------------------------------------------------------------------------
1300 * \brief Print self.
1301 * @param indent Indentation string to be prepended during printing.
1302 * @param os Stream to print to.
1304 void PixelReadConvert::Print( std::ostream &os, std::string const &indent )
1307 << "--- Pixel information -------------------------"
1310 << "Pixel Data: offset " << PixelOffset
1311 << " x(" << std::hex << PixelOffset << std::dec
1312 << ") length " << PixelDataLength
1313 << " x(" << std::hex << PixelDataLength << std::dec
1314 << ")" << std::endl;
1316 if ( IsRLELossless )
1320 RLEInfo->Print( os, indent );
1324 gdcmWarningMacro("Set as RLE file but NO RLEinfo present.");
1328 if ( IsJPEG2000 || IsJPEGLossless || IsJPEGLossy || IsJPEGLS )
1332 JPEGInfo->Print( os, indent );
1336 gdcmWarningMacro("Set as JPEG file but NO JPEGinfo present.");
1341 //-----------------------------------------------------------------------------
1342 } // end namespace gdcm
1344 // Note to developpers :
1345 // Here is a very detailled post from David Clunie, on the troubles caused
1346 // 'non standard' LUT and LUT description
1347 // We shall have to take it into accound in our code.
1352 Subject: Problem with VOI LUTs in Agfa and Fuji CR and GE DX images, was Re: VOI LUT issues
1353 Date: Sun, 06 Feb 2005 17:13:40 GMT
1354 From: David Clunie <dclunie@dclunie.com>
1355 Reply-To: dclunie@dclunie.com
1356 Newsgroups: comp.protocols.dicom
1357 References: <1107553502.040221.189550@o13g2000cwo.googlegroups.com>
1359 > THE LUT that comes with [my] image claims to be 16-bit, but none of the
1360 > values goes higher than 4095. That being said, though, none of my
1361 > original pixel values goes higher than that, either. I have read
1362 > elsewhere on this group that when that happens you are supposed to
1363 > adjust the LUT. Can someone be more specific? There was a thread from
1364 > 2002 where Marco and David were mentioning doing precisely that.
1371 You have encountered the well known "we know what the standard says but
1372 we are going to ignore it and do what we have been doing for almost
1373 a decade regardless" CR vendor bug. Agfa started this, but they are not
1374 the only vendor doing this now; GE and Fuji may have joined the club.
1376 Sadly, one needs to look at the LUT Data, figure out what the maximum
1377 value actually encoded is, and find the next highest power of 2 (e.g.
1378 212 in this case), to figure out what the range of the data is
1379 supposed to be. I have assumed that if the maximum value in the LUT
1380 data is less than a power of 2 minus 1 (e.g. 0xebc) then the intent
1381 of the vendor was not to use the maximum available grayscale range
1382 of the display (e.g. the maximum is 0xfff in this case). An alternative
1383 would be to scale to the actual maximum rather than a power of two.
1385 Very irritating, and in theory not totally reliable if one really
1386 intended the full 16 bits and only used, say 15, but that is extremely
1387 unlikely since everything would be too dark, and this heuristic
1390 There has never been anything in the standard that describes having
1391 to go through these convolutions. Since the only value in the
1392 standard that describes the bit depth of the LUT values is LUT
1393 Descriptor value 3 and that is (usually) always required to be
1394 either 8 or 16, it mystifies me how the creators' of these images
1395 imagine that the receiver is going to divine the range that is intended. Further, the standard is quite explicit that this 3rd
1396 value defines the range of LUT values, but as far as I am aware, all
1397 the vendors are ignoring the standard and indeed sending a third value
1400 This problem is not confined to CR, and is also seen with DX products.
1402 Typically I have seen:
1404 - Agfa CR, which usually (always ?) sends LUTs, values up to 0x0fff
1405 - Fuji CR, which occasionally send LUTs, values up to 0x03ff
1406 - GE DX, for presentation, which always have LUTs, up to 0x3fff
1408 Swissray, Siemens, Philips, Canon and Kodak never seem to send VOI LUTs
1409 at this point (which is a whole other problem). Note that the presence
1410 or absence of a VOI LUT as opposed to window values may be configurable
1411 on the modality in some cases, and I have just looked at what I happen
1412 to have received from a myriad of sites over whose configuration I have
1413 no control. This may be why the majority of Fuji images have no VOI LUTs,
1414 but a few do (or it may be the Siemens system that these Fuji images went
1415 through that perhaps added it). I do have some test Hologic DX images that
1416 are not from a clinical site that do actually get this right (a value
1417 of 12 for the third value and a max of 0xfff).
1419 Since almost every vendor that I have encountered that encodes LUTs
1420 makes this mistake, perhaps it is time to amend the standard to warn
1421 implementor's of receivers and/or sanction this bad behavior. We have
1422 talked about this in the past in WG 6 but so far everyone has been
1423 reluctant to write into the standard such a comment. Maybe it is time
1424 to try again, since if one is not aware of this problem, one cannot
1425 effectively implement display using VOI LUTs, and there is a vast
1426 installed base to contend with.
1428 I did not check presentation states, in which VOI LUTs could also be
1429 encountered, for the prevalence of this mistake, nor did I look at the
1430 encoding of Modality LUT's, which are unusual. Nor did I check digital
1431 mammography images. I would be interested to hear from anyone who has.
1435 PS. The following older thread in this newsgroup discusses this:
1437 "http://groups-beta.google.com/group/comp.protocols.dicom/browse_frm/t hread/6a033444802a35fc/0f0a9a1e35c1468e?q=voi+lut&_done=%2Fgroup%2Fcom p.protocols.dicom%2Fsearch%3Fgroup%3Dcomp.protocols.dicom%26q%3Dvoi+lu t%26qt_g%3D1%26searchnow%3DSearch+this+group%26&_doneTitle=Back+to+Sea rch&&d#0f0a9a1e35c1468e"
1439 PPS. From a historical perspective, the following may be of interest.
1441 In the original standard in 1993, all that was said about this was a
1442 reference to the corresponding such where Modality LUTs are described
1445 "The third value specifies the number of bits for each entry in the
1446 LUT Data. It shall take the value 8 or 16. The LUT Data shall be stored
1447 in a format equivalent to 8 or 16 bits allocated and high bit equal
1450 Since the high bit hint was not apparently explicit enough, a very
1451 early CP, CP 15 (submitted by Agfa as it happens), replaced this with:
1453 "The third value conveys the range of LUT entry values. It shall take
1454 the value 8 or 16, corresponding with the LUT entry value range of
1457 Note: The third value is not required for describing the
1458 LUT data and is only included for informational usage
1459 and for maintaining compatibility with ACRNEMA 2.0.
1461 The LUT Data contains the LUT entry values."
1463 That is how it read in the 1996, 1998 and 1999 editions.
1465 By the 2000 edition, Supplement 33 that introduced presentation states
1466 extensively reworked this entire section and tried to explain this in
1469 "The output range is from 0 to 2^n-1 where n is the third value of LUT
1470 Descriptor. This range is always unsigned."
1472 and also added a note to spell out what the output range meant in the
1475 "9. The output of the Window Center/Width or VOI LUT transformation
1476 is either implicitly scaled to the full range of the display device
1477 if there is no succeeding transformation defined, or implicitly scaled
1478 to the full input range of the succeeding transformation step (such as
1479 the Presentation LUT), if present. See C.11.6.1."
1481 It still reads this way in the 2004 edition.
1483 Note that LUTs in other applications than the general VOI LUT allow for
1484 values other than 8 or 16 in the third value of LUT descriptor to permit
1485 ranges other than 0 to 255 or 65535.
1487 In addition, the DX Image Module specializes the VOI LUT
1488 attributes as follows, in PS 3.3 section C.8.11.3.1.5 (added in Sup 32):
1490 "The third value specifies the number of bits for each entry in the LUT
1491 Data (analogous to ìbits storedî). It shall be between 10-16. The LUT
1492 Data shall be stored in a format equivalent to 16 ìbits allocatedî and
1493 ìhigh bitî equal to ìbits storedî - 1. The third value conveys the range
1494 of LUT entry values. These unsigned LUT entry values shall range between
1495 0 and 2^n-1, where n is the third value of the LUT Descriptor."
1497 So in the case of the GE DX for presentation images, the third value of
1498 LUT descriptor is allowed to be and probably should be 14 rather than 16.