1 /*=========================================================================
4 Module: $RCSfile: gdcmPixelReadConvert.cxx,v $
6 Date: $Date: 2005/10/26 14:54:51 $
7 Version: $Revision: 1.92 $
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();
118 if (! file->IsDicomV3() ) // Should be ACR-NEMA file
121 // Don't loose time checking unexistant Transfer Syntax !
122 IsPrivateGETransferSyntax = IsMPEG
123 = IsJPEG2000 = IsJPEGLS = IsJPEGLossy
124 = IsJPEGLossless = IsRLELossless
129 std::string ts = file->GetTransferSyntax();
132 Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRLittleEndian
133 || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRBigEndianPrivateGE
134 || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRLittleEndian
135 || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRBigEndian
136 || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::DeflatedExplicitVRLittleEndian;
138 IsPrivateGETransferSyntax =
139 ( Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRBigEndianPrivateGE );
141 IsMPEG = Global::GetTS()->IsMPEG(ts);
142 IsJPEG2000 = Global::GetTS()->IsJPEG2000(ts);
143 IsJPEGLS = Global::GetTS()->IsJPEGLS(ts);
144 IsJPEGLossy = Global::GetTS()->IsJPEGLossy(ts);
145 IsJPEGLossless = Global::GetTS()->IsJPEGLossless(ts);
146 IsRLELossless = Global::GetTS()->IsRLELossless(ts);
149 PixelOffset = file->GetPixelOffset();
150 PixelDataLength = file->GetPixelAreaLength();
151 RLEInfo = file->GetRLEInfo();
152 JPEGInfo = file->GetJPEGInfo();
154 IsMonochrome = file->IsMonochrome();
155 IsMonochrome1 = file->IsMonochrome1();
156 IsPaletteColor = file->IsPaletteColor();
157 IsYBRFull = file->IsYBRFull();
159 PlanarConfiguration = file->GetPlanarConfiguration();
161 /////////////////////////////////////////////////////////////////
163 HasLUT = file->HasLUT();
166 // Just in case some access to a File element requires disk access.
167 LutRedDescriptor = file->GetEntryString( 0x0028, 0x1101 );
168 LutGreenDescriptor = file->GetEntryString( 0x0028, 0x1102 );
169 LutBlueDescriptor = file->GetEntryString( 0x0028, 0x1103 );
171 // The following comment is probabely meaningless, since LUT are *always*
172 // loaded at parsing time, whatever their length is.
174 // Depending on the value of Document::MAX_SIZE_LOAD_ELEMENT_VALUE
175 // [ refer to invocation of Document::SetMaxSizeLoadEntry() in
176 // Document::Document() ], the loading of the value (content) of a
177 // [Bin|Val]Entry occurence migth have been hindered (read simply NOT
178 // loaded). Hence, we first try to obtain the LUTs data from the file
179 // and when this fails we read the LUTs data directly from disk.
180 // \TODO Reading a [Bin|Val]Entry directly from disk is a kludge.
181 // We should NOT bypass the [Bin|Val]Entry class. Instead
182 // an access to an UNLOADED content of a [Bin|Val]Entry occurence
183 // (e.g. DataEntry::GetBinArea()) should force disk access from
184 // within the [Bin|Val]Entry class itself. The only problem
185 // is that the [Bin|Val]Entry is unaware of the FILE* is was
186 // parsed from. Fix that. FIXME.
189 file->LoadEntryBinArea(0x0028, 0x1201);
190 LutRedData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1201 );
193 gdcmWarningMacro("Unable to read Red Palette Color Lookup Table data");
197 file->LoadEntryBinArea(0x0028, 0x1202);
198 LutGreenData = (uint8_t*)file->GetEntryBinArea(0x0028, 0x1202 );
201 gdcmWarningMacro("Unable to read Green Palette Color Lookup Table data");
205 file->LoadEntryBinArea(0x0028, 0x1203);
206 LutBlueData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1203 );
209 gdcmWarningMacro("Unable to read Blue Palette Color Lookup Table data");
214 ComputeRawAndRGBSizes();
217 /// \brief Reads from disk and decompresses Pixels
218 bool PixelReadConvert::ReadAndDecompressPixelData( std::ifstream *fp )
220 // ComputeRawAndRGBSizes is already made by
221 // ::GrabInformationsFromfile. So, the structure sizes are
225 //////////////////////////////////////////////////
226 //// First stage: get our hands on the Pixel Data.
229 gdcmWarningMacro( "Unavailable file pointer." );
233 fp->seekg( PixelOffset, std::ios::beg );
234 if ( fp->fail() || fp->eof() )
236 gdcmWarningMacro( "Unable to find PixelOffset in file." );
242 //////////////////////////////////////////////////
243 //// Second stage: read from disk and decompress.
244 if ( BitsAllocated == 12 )
246 ReadAndDecompress12BitsTo16Bits( fp);
250 // This problem can be found when some obvious informations are found
251 // after the field containing the image data. In this case, these
252 // bad data are added to the size of the image (in the PixelDataLength
253 // variable). But RawSize is the right size of the image !
254 if ( PixelDataLength != RawSize )
256 gdcmWarningMacro( "Mismatch between PixelReadConvert : "
257 << PixelDataLength << " and RawSize : " << RawSize );
259 if ( PixelDataLength > RawSize )
261 fp->read( (char*)Raw, RawSize);
265 fp->read( (char*)Raw, PixelDataLength);
268 if ( fp->fail() || fp->eof())
270 gdcmWarningMacro( "Reading of Raw pixel data failed." );
274 else if ( IsRLELossless )
276 if ( ! RLEInfo->DecompressRLEFile
277 ( fp, Raw, XSize, YSize, ZSize, BitsAllocated ) )
279 gdcmWarningMacro( "RLE decompressor failed." );
285 //gdcmWarningMacro( "Sorry, MPEG not yet taken into account" );
287 // fp has already been seek to start of mpeg
288 //ReadMPEGFile(fp, Raw, PixelDataLength);
293 // Default case concerns JPEG family
294 if ( ! ReadAndDecompressJPEGFile( fp ) )
296 gdcmWarningMacro( "JPEG decompressor failed." );
301 ////////////////////////////////////////////
302 //// Third stage: twigle the bytes and bits.
303 ConvertReorderEndianity();
304 ConvertReArrangeBits();
305 ConvertFixGreyLevels();
306 if (UserFunction) // user is allowed to Mirror, TopDown, Rotate,...the image
307 UserFunction( Raw, FileInternal);
308 ConvertHandleColor();
313 /// Deletes Pixels Area
314 void PixelReadConvert::Squeeze()
330 * \brief Build the RGB image from the Raw image and the LUTs.
332 bool PixelReadConvert::BuildRGBImage()
336 // The job is already done.
342 // The job can't be done
349 // The job can't be done
353 gdcmWarningMacro( "--> BuildRGBImage" );
359 if ( BitsAllocated <= 8 )
361 uint8_t *localRGB = RGB;
362 for (size_t i = 0; i < RawSize; ++i )
365 *localRGB++ = LutRGBA[j];
366 *localRGB++ = LutRGBA[j+1];
367 *localRGB++ = LutRGBA[j+2];
371 else // deal with 16 bits pixels and 16 bits Palette color
373 uint16_t *localRGB = (uint16_t *)RGB;
374 for (size_t i = 0; i < RawSize/2; ++i )
376 j = ((uint16_t *)Raw)[i] * 4;
377 *localRGB++ = ((uint16_t *)LutRGBA)[j];
378 *localRGB++ = ((uint16_t *)LutRGBA)[j+1];
379 *localRGB++ = ((uint16_t *)LutRGBA)[j+2];
386 //-----------------------------------------------------------------------------
389 //-----------------------------------------------------------------------------
392 * \brief Read from file a 12 bits per pixel image and decompress it
393 * into a 16 bits per pixel image.
395 void PixelReadConvert::ReadAndDecompress12BitsTo16Bits( std::ifstream *fp )
396 throw ( FormatError )
398 int nbPixels = XSize * YSize;
399 uint16_t *localDecompres = (uint16_t*)Raw;
401 for( int p = 0; p < nbPixels; p += 2 )
405 fp->read( (char*)&b0, 1);
406 if ( fp->fail() || fp->eof() )
408 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
409 "Unfound first block" );
412 fp->read( (char*)&b1, 1 );
413 if ( fp->fail() || fp->eof())
415 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
416 "Unfound second block" );
419 fp->read( (char*)&b2, 1 );
420 if ( fp->fail() || fp->eof())
422 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
423 "Unfound second block" );
426 // Two steps are necessary to please VC++
428 // 2 pixels 12bit = [0xABCDEF]
429 // 2 pixels 16bit = [0x0ABD] + [0x0FCE]
431 *localDecompres++ = ((b0 >> 4) << 8) + ((b0 & 0x0f) << 4) + (b1 & 0x0f);
433 *localDecompres++ = ((b2 & 0x0f) << 8) + ((b1 >> 4) << 4) + (b2 >> 4);
435 /// \todo JPR Troubles expected on Big-Endian processors ?
440 * \brief Reads from disk the Pixel Data of JPEG Dicom encapsulated
441 * file and decompress it.
442 * @param fp File Pointer
445 bool PixelReadConvert::ReadAndDecompressJPEGFile( std::ifstream *fp )
449 // make sure this is the right JPEG compression
450 assert( !IsJPEGLossless || !IsJPEGLossy || !IsJPEGLS );
451 // FIXME this is really ugly but it seems I have to load the complete
452 // jpeg2000 stream to use jasper:
453 // I don't think we'll ever be able to deal with multiple fragments properly
455 unsigned long inputlength = 0;
456 JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment();
459 inputlength += jpegfrag->GetLength();
460 jpegfrag = JPEGInfo->GetNextFragment();
462 gdcmAssertMacro( inputlength != 0);
463 uint8_t *inputdata = new uint8_t[inputlength];
464 char *pinputdata = (char*)inputdata;
465 jpegfrag = JPEGInfo->GetFirstFragment();
468 fp->seekg( jpegfrag->GetOffset(), std::ios::beg);
469 fp->read(pinputdata, jpegfrag->GetLength());
470 pinputdata += jpegfrag->GetLength();
471 jpegfrag = JPEGInfo->GetNextFragment();
473 // Warning the inputdata buffer is delete in the function
474 if ( ! gdcm_read_JPEG2000_file( Raw,
475 (char*)inputdata, inputlength ) )
479 // wow what happen, must be an error
484 // make sure this is the right JPEG compression
485 assert( !IsJPEGLossless || !IsJPEGLossy || !IsJPEG2000 );
486 // WARNING : JPEG-LS is NOT the 'classical' Jpeg Lossless :
487 // [JPEG-LS is the basis for new lossless/near-lossless compression
488 // standard for continuous-tone images intended for JPEG2000. The standard
489 // is based on the LOCO-I algorithm (LOw COmplexity LOssless COmpression
490 // for Images) developed at Hewlett-Packard Laboratories]
492 // see http://datacompression.info/JPEGLS.shtml
495 std::cerr << "count:" << JPEGInfo->GetFragmentCount() << std::endl;
496 unsigned long inputlength = 0;
497 JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment();
500 inputlength += jpegfrag->GetLength();
501 jpegfrag = JPEGInfo->GetNextFragment();
503 gdcmAssertMacro( inputlength != 0);
504 uint8_t *inputdata = new uint8_t[inputlength];
505 char *pinputdata = (char*)inputdata;
506 jpegfrag = JPEGInfo->GetFirstFragment();
509 fp->seekg( jpegfrag->GetOffset(), std::ios::beg);
510 fp->read(pinputdata, jpegfrag->GetLength());
511 pinputdata += jpegfrag->GetLength();
512 jpegfrag = JPEGInfo->GetNextFragment();
515 //fp->read((char*)Raw, PixelDataLength);
517 std::ofstream out("/tmp/jpegls.jpg");
518 out.write((char*)inputdata, inputlength);
523 gdcmWarningMacro( "Sorry, JPEG-LS not yet taken into account" );
524 fp->seekg( JPEGInfo->GetFirstFragment()->GetOffset(), std::ios::beg);
525 // if ( ! gdcm_read_JPEGLS_file( fp,Raw ) )
530 // make sure this is the right JPEG compression
531 assert( !IsJPEGLS || !IsJPEG2000 );
532 // Precompute the offset localRaw will be shifted with
533 int length = XSize * YSize * SamplesPerPixel;
534 int numberBytes = BitsAllocated / 8;
536 JPEGInfo->DecompressFromFile(fp, Raw, BitsStored, numberBytes, length );
542 * \brief Build Red/Green/Blue/Alpha LUT from File when :
543 * - (0028,0004) : Photometric Interpretation == [PALETTE COLOR ]
545 * - (0028,1101),(0028,1102),(0028,1102)
546 * xxx Palette Color Lookup Table Descriptor are found
548 * - (0028,1201),(0028,1202),(0028,1202)
549 * xxx Palette Color Lookup Table Data - are found
550 * \warning does NOT deal with :
551 * - 0028 1100 Gray Lookup Table Descriptor (Retired)
552 * - 0028 1221 Segmented Red Palette Color Lookup Table Data
553 * - 0028 1222 Segmented Green Palette Color Lookup Table Data
554 * - 0028 1223 Segmented Blue Palette Color Lookup Table Data
555 * no known Dicom reader deals with them :-(
556 * @return a RGBA Lookup Table
558 void PixelReadConvert::BuildLUTRGBA()
561 // Note to code reviewers :
562 // The problem is *much more* complicated, since a lot of manufacturers
563 // Don't follow the norm :
564 // have a look at David Clunie's remark at the end of this .cxx file.
571 // http://www.barre.nom.fr/medical/dicom2/limitations.html#Color%20Lookup%20Tables
573 if ( ! IsPaletteColor )
578 if ( LutRedDescriptor == GDCM_UNFOUND
579 || LutGreenDescriptor == GDCM_UNFOUND
580 || LutBlueDescriptor == GDCM_UNFOUND )
582 gdcmWarningMacro( "(At least) a LUT Descriptor is missing" );
586 ////////////////////////////////////////////
587 // Extract the info from the LUT descriptors
588 int lengthR; // Red LUT length in Bytes
589 int debR; // Subscript of the first Lut Value
590 int nbitsR; // Lut item size (in Bits)
591 int nbRead; // nb of items in LUT descriptor (must be = 3)
593 nbRead = sscanf( LutRedDescriptor.c_str(),
595 &lengthR, &debR, &nbitsR );
598 gdcmWarningMacro( "Wrong Red LUT descriptor" );
600 int lengthG; // Green LUT length in Bytes
601 int debG; // Subscript of the first Lut Value
602 int nbitsG; // Lut item size (in Bits)
604 nbRead = sscanf( LutGreenDescriptor.c_str(),
606 &lengthG, &debG, &nbitsG );
609 gdcmWarningMacro( "Wrong Green LUT descriptor" );
612 int lengthB; // Blue LUT length in Bytes
613 int debB; // Subscript of the first Lut Value
614 int nbitsB; // Lut item size (in Bits)
615 nbRead = sscanf( LutRedDescriptor.c_str(),
617 &lengthB, &debB, &nbitsB );
620 gdcmWarningMacro( "Wrong Blue LUT descriptor" );
623 gdcmWarningMacro(" lengthR " << lengthR << " debR "
624 << debR << " nbitsR " << nbitsR);
625 gdcmWarningMacro(" lengthG " << lengthG << " debG "
626 << debG << " nbitsG " << nbitsG);
627 gdcmWarningMacro(" lengthB " << lengthB << " debB "
628 << debB << " nbitsB " << nbitsB);
630 if ( !lengthR ) // if = 2^16, this shall be 0 see : CP-143
632 if ( !lengthG ) // if = 2^16, this shall be 0
634 if ( !lengthB ) // if = 2^16, this shall be 0
637 ////////////////////////////////////////////////////////
639 if ( ( ! LutRedData ) || ( ! LutGreenData ) || ( ! LutBlueData ) )
641 gdcmWarningMacro( "(At least) a LUT is missing" );
645 // -------------------------------------------------------------
647 if ( BitsAllocated <= 8 )
649 // forge the 4 * 8 Bits Red/Green/Blue/Alpha LUT
650 LutRGBA = new uint8_t[ 1024 ]; // 256 * 4 (R, G, B, Alpha)
655 memset( LutRGBA, 0, 1024 );
658 if ( ( nbitsR == 16 ) && ( BitsAllocated == 8 ) )
660 // when LUT item size is different than pixel size
661 mult = 2; // high byte must be = low byte
665 // See PS 3.3-2003 C.11.1.1.2 p 619
669 // if we get a black image, let's just remove the '+1'
670 // from 'i*mult+1' and check again
671 // if it works, we shall have to check the 3 Palettes
672 // to see which byte is ==0 (first one, or second one)
674 // We give up the checking to avoid some (useless ?) overhead
675 // (optimistic asumption)
679 //take "Subscript of the first Lut Value" (debR,debG,debB) into account!
681 //FIXME : +1 : to get 'low value' byte
682 // Trouble expected on Big Endian Processors ?
683 // 16 BIts Per Pixel Palette Color to be swapped?
685 a = LutRGBA + 0 + debR;
686 for( i=0; i < lengthR; ++i )
688 *a = LutRedData[i*mult+1];
692 a = LutRGBA + 1 + debG;
693 for( i=0; i < lengthG; ++i)
695 *a = LutGreenData[i*mult+1];
699 a = LutRGBA + 2 + debB;
700 for(i=0; i < lengthB; ++i)
702 *a = LutBlueData[i*mult+1];
707 for(i=0; i < 256; ++i)
709 *a = 1; // Alpha component
715 // Probabely the same stuff is to be done for 16 Bits Pixels
716 // with 65536 entries LUT ?!?
717 // Still looking for accurate info on the web :-(
719 gdcmWarningMacro( "Sorry Palette Color Lookup Tables not yet dealt with"
720 << " for 16 Bits Per Pixel images" );
722 // forge the 4 * 16 Bits Red/Green/Blue/Alpha LUT
724 LutRGBA = (uint8_t *)new uint16_t[ 65536*4 ]; // 2^16 * 4 (R, G, B, Alpha)
727 memset( LutRGBA, 0, 65536*4*2 ); // 16 bits = 2 bytes ;-)
729 LutItemNumber = 65536;
735 //take "Subscript of the first Lut Value" (debR,debG,debB) into account!
737 a16 = (uint16_t*)LutRGBA + 0 + debR;
738 for( i=0; i < lengthR; ++i )
740 *a16 = ((uint16_t*)LutRedData)[i];
744 a16 = (uint16_t*)LutRGBA + 1 + debG;
745 for( i=0; i < lengthG; ++i)
747 *a16 = ((uint16_t*)LutGreenData)[i];
751 a16 = (uint16_t*)LutRGBA + 2 + debB;
752 for(i=0; i < lengthB; ++i)
754 *a16 = ((uint16_t*)LutBlueData)[i];
758 a16 = (uint16_t*)LutRGBA + 3 ;
759 for(i=0; i < 65536; ++i)
761 *a16 = 1; // Alpha component
764 /* Just to 'see' the LUT, at debug time
765 // Don't remove this commented out code.
767 a16=(uint16_t*)LutRGBA;
768 for (int j=0;j<65536;j++)
770 std::cout << *a16 << " " << *(a16+1) << " "
771 << *(a16+2) << " " << *(a16+3) << std::endl;
779 * \brief Swap the bytes, according to \ref SwapCode.
781 void PixelReadConvert::ConvertSwapZone()
784 uint16_t localSwapCode = SwapCode;
786 // If this file is 'ImplicitVR BigEndian PrivateGE Transfer Syntax',
787 // then the header is in little endian format and the pixel data is in
788 // big endian format. When reading the header, GDCM has already established
789 // a byte swapping code suitable for this machine to read the
790 // header. In TS::ImplicitVRBigEndianPrivateGE, this code will need
791 // to be switched in order to read the pixel data. This must be
792 // done REGARDLESS of the processor endianess!
794 // Example: Assume we are on a little endian machine. When
795 // GDCM reads the header, the header will match the machine
796 // endianess and the swap code will be established as a no-op.
797 // When GDCM reaches the pixel data, it will need to switch the
798 // swap code to do big endian to little endian conversion.
800 // Now, assume we are on a big endian machine. When GDCM reads the
801 // header, the header will be recognized as a different endianess
802 // than the machine endianess, and a swap code will be established
803 // to convert from little endian to big endian. When GDCM readers
804 // the pixel data, the pixel data endianess will now match the
805 // machine endianess. But we currently have a swap code that
806 // converts from little endian to big endian. In this case, we
807 // need to switch the swap code to a no-op.
809 // Therefore, in either case, if the file is in
810 // 'ImplicitVR BigEndian PrivateGE Transfer Syntax', then GDCM needs to switch
811 // the byte swapping code when entering the pixel data.
813 /* //Let me check something.
814 //I wait for the Dashboard !
815 if ( IsPrivateGETransferSyntax )
817 // PrivateGETransferSyntax only exists for 'true' Dicom images
818 // we assume there is no 'exotic' 32 bits endianess!
819 switch (localSwapCode)
822 localSwapCode = 4321;
825 localSwapCode = 1234;
830 if ( BitsAllocated == 16 )
832 uint16_t *im16 = (uint16_t*)Raw;
833 switch( localSwapCode )
840 for( i = 0; i < RawSize / 2; i++ )
842 im16[i]= (im16[i] >> 8) | (im16[i] << 8 );
846 gdcmWarningMacro("SwapCode value (16 bits) not allowed.");
849 else if ( BitsAllocated == 32 )
854 uint32_t *im32 = (uint32_t*)Raw;
855 switch ( localSwapCode )
860 for( i = 0; i < RawSize / 4; i++ )
862 low = im32[i] & 0x0000ffff; // 4321
863 high = im32[i] >> 16;
864 high = ( high >> 8 ) | ( high << 8 );
865 low = ( low >> 8 ) | ( low << 8 );
867 im32[i] = ( s32 << 16 ) | high;
871 for( i = 0; i < RawSize / 4; i++ )
873 low = im32[i] & 0x0000ffff; // 2143
874 high = im32[i] >> 16;
875 high = ( high >> 8 ) | ( high << 8 );
876 low = ( low >> 8 ) | ( low << 8 );
878 im32[i] = ( s32 << 16 ) | low;
882 for( i = 0; i < RawSize / 4; i++ )
884 low = im32[i] & 0x0000ffff; // 3412
885 high = im32[i] >> 16;
887 im32[i] = ( s32 << 16 ) | high;
891 gdcmWarningMacro("SwapCode value (32 bits) not allowed." );
897 * \brief Deal with endianness i.e. re-arange bytes inside the integer
899 void PixelReadConvert::ConvertReorderEndianity()
901 if ( BitsAllocated != 8 )
906 // Special kludge in order to deal with xmedcon broken images:
907 if ( BitsAllocated == 16
908 && BitsStored < BitsAllocated
911 int l = (int)( RawSize / ( BitsAllocated / 8 ) );
912 uint16_t *deb = (uint16_t *)Raw;
913 for(int i = 0; i<l; i++)
915 if ( *deb == 0xffff )
925 * \brief Deal with Grey levels i.e. re-arange them
926 * to have low values = dark, high values = bright
928 void PixelReadConvert::ConvertFixGreyLevels()
933 uint32_t i; // to please M$VC6
938 if ( BitsAllocated == 8 )
940 uint8_t *deb = (uint8_t *)Raw;
941 for (i=0; i<RawSize; i++)
949 if ( BitsAllocated == 16 )
952 for (j=0; j<BitsStored-1; j++)
954 mask = (mask << 1) +1; // will be fff when BitsStored=12
957 uint16_t *deb = (uint16_t *)Raw;
958 for (i=0; i<RawSize/2; i++)
968 if ( BitsAllocated == 8 )
970 uint8_t smask8 = 255;
971 uint8_t *deb = (uint8_t *)Raw;
972 for (i=0; i<RawSize; i++)
974 *deb = smask8 - *deb;
979 if ( BitsAllocated == 16 )
981 uint16_t smask16 = 65535;
982 uint16_t *deb = (uint16_t *)Raw;
983 for (i=0; i<RawSize/2; i++)
985 *deb = smask16 - *deb;
994 * \brief Re-arrange the bits within the bytes.
995 * @return Boolean always true
997 bool PixelReadConvert::ConvertReArrangeBits() throw ( FormatError )
1000 if ( BitsStored != BitsAllocated )
1002 int l = (int)( RawSize / ( BitsAllocated / 8 ) );
1003 if ( BitsAllocated == 16 )
1005 // pmask : to mask the 'unused bits' (may contain overlays)
1006 uint16_t pmask = 0xffff;
1007 pmask = pmask >> ( BitsAllocated - BitsStored );
1009 uint16_t *deb = (uint16_t*)Raw;
1011 if ( !PixelSign ) // Pixels are unsigned
1013 for(int i = 0; i<l; i++)
1015 *deb = (*deb >> (BitsStored - HighBitPosition - 1)) & pmask;
1019 else // Pixels are signed
1021 // smask : to check the 'sign' when BitsStored != BitsAllocated
1022 uint16_t smask = 0x0001;
1023 smask = smask << ( 16 - (BitsAllocated - BitsStored + 1) );
1024 // nmask : to propagate sign bit on negative values
1025 int16_t nmask = (int16_t)0x8000;
1026 nmask = nmask >> ( BitsAllocated - BitsStored - 1 );
1028 for(int i = 0; i<l; i++)
1030 *deb = *deb >> (BitsStored - HighBitPosition - 1);
1033 *deb = *deb | nmask;
1037 *deb = *deb & pmask;
1043 else if ( BitsAllocated == 32 )
1045 // pmask : to mask the 'unused bits' (may contain overlays)
1046 uint32_t pmask = 0xffffffff;
1047 pmask = pmask >> ( BitsAllocated - BitsStored );
1049 uint32_t *deb = (uint32_t*)Raw;
1053 for(int i = 0; i<l; i++)
1055 *deb = (*deb >> (BitsStored - HighBitPosition - 1)) & pmask;
1061 // smask : to check the 'sign' when BitsStored != BitsAllocated
1062 uint32_t smask = 0x00000001;
1063 smask = smask >> ( 32 - (BitsAllocated - BitsStored +1 ));
1064 // nmask : to propagate sign bit on negative values
1065 int32_t nmask = 0x80000000;
1066 nmask = nmask >> ( BitsAllocated - BitsStored -1 );
1068 for(int i = 0; i<l; i++)
1070 *deb = *deb >> (BitsStored - HighBitPosition - 1);
1072 *deb = *deb | nmask;
1074 *deb = *deb & pmask;
1081 gdcmWarningMacro("Weird image (BitsAllocated !=8, 12, 16, 32)");
1082 throw FormatError( "Weird image !?" );
1089 * \brief Convert (Red plane, Green plane, Blue plane) to RGB pixels
1090 * \warning Works on all the frames at a time
1092 void PixelReadConvert::ConvertRGBPlanesToRGBPixels()
1094 gdcmWarningMacro("--> ConvertRGBPlanesToRGBPixels");
1096 uint8_t *localRaw = Raw;
1097 uint8_t *copyRaw = new uint8_t[ RawSize ];
1098 memmove( copyRaw, localRaw, RawSize );
1100 int l = XSize * YSize * ZSize;
1102 uint8_t *a = copyRaw;
1103 uint8_t *b = copyRaw + l;
1104 uint8_t *c = copyRaw + l + l;
1106 for (int j = 0; j < l; j++)
1108 *(localRaw++) = *(a++);
1109 *(localRaw++) = *(b++);
1110 *(localRaw++) = *(c++);
1116 * \brief Convert (cY plane, cB plane, cR plane) to RGB pixels
1117 * \warning Works on all the frames at a time
1119 void PixelReadConvert::ConvertYcBcRPlanesToRGBPixels()
1121 // Remarks for YBR newbees :
1122 // YBR_FULL works very much like RGB, i.e. three samples per pixel,
1123 // just the color space is YCbCr instead of RGB. This is particularly useful
1124 // for doppler ultrasound where most of the image is grayscale
1125 // (i.e. only populates the Y components) and Cb and Cr are mostly zero,
1126 // except for the few patches of color on the image.
1127 // On such images, RLE achieves a compression ratio that is much better
1128 // than the compression ratio on an equivalent RGB image.
1130 gdcmWarningMacro("--> ConvertYcBcRPlanesToRGBPixels");
1132 uint8_t *localRaw = Raw;
1133 uint8_t *copyRaw = new uint8_t[ RawSize ];
1134 memmove( copyRaw, localRaw, RawSize );
1136 // to see the tricks about YBR_FULL, YBR_FULL_422,
1137 // YBR_PARTIAL_422, YBR_ICT, YBR_RCT have a look at :
1138 // ftp://medical.nema.org/medical/dicom/final/sup61_ft.pdf
1139 // and be *very* affraid
1141 int l = XSize * YSize;
1142 int nbFrames = ZSize;
1144 uint8_t *a = copyRaw + 0;
1145 uint8_t *b = copyRaw + l;
1146 uint8_t *c = copyRaw + l+ l;
1149 /// We replaced easy to understand but time consuming floating point
1150 /// computations by the 'well known' integer computation counterpart
1152 /// http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf
1153 /// for code optimisation.
1155 for ( int i = 0; i < nbFrames; i++ )
1157 for ( int j = 0; j < l; j++ )
1159 R = 38142 *(*a-16) + 52298 *(*c -128);
1160 G = 38142 *(*a-16) - 26640 *(*c -128) - 12845 *(*b -128);
1161 B = 38142 *(*a-16) + 66093 *(*b -128);
1170 if (R > 255) R = 255;
1171 if (G > 255) G = 255;
1172 if (B > 255) B = 255;
1174 *(localRaw++) = (uint8_t)R;
1175 *(localRaw++) = (uint8_t)G;
1176 *(localRaw++) = (uint8_t)B;
1185 /// \brief Deals with the color decoding i.e. handle:
1186 /// - R, G, B planes (as opposed to RGB pixels)
1187 /// - YBR (various) encodings.
1188 /// - LUT[s] (or "PALETTE COLOR").
1190 void PixelReadConvert::ConvertHandleColor()
1192 //////////////////////////////////
1193 // Deal with the color decoding i.e. handle:
1194 // - R, G, B planes (as opposed to RGB pixels)
1195 // - YBR (various) encodings.
1196 // - LUT[s] (or "PALETTE COLOR").
1198 // The classification in the color decoding schema is based on the blending
1199 // of two Dicom tags values:
1200 // * "Photometric Interpretation" for which we have the cases:
1201 // - [Photo A] MONOCHROME[1|2] pictures,
1202 // - [Photo B] RGB or YBR_FULL_422 (which acts as RGB),
1203 // - [Photo C] YBR_* (with the above exception of YBR_FULL_422)
1204 // - [Photo D] "PALETTE COLOR" which indicates the presence of LUT[s].
1205 // * "Planar Configuration" for which we have the cases:
1206 // - [Planar 0] 0 then Pixels are already RGB
1207 // - [Planar 1] 1 then we have 3 planes : R, G, B,
1208 // - [Planar 2] 2 then we have 1 gray Plane and 3 LUTs
1210 // Now in theory, one could expect some coherence when blending the above
1211 // cases. For example we should not encounter files belonging at the
1212 // time to case [Planar 0] and case [Photo D].
1213 // Alas, this was only theory ! Because in practice some odd (read ill
1214 // formated Dicom) files (e.g. gdcmData/US-PAL-8-10x-echo.dcm) we encounter:
1215 // - "Planar Configuration" = 0,
1216 // - "Photometric Interpretation" = "PALETTE COLOR".
1217 // Hence gdcm will use the folowing "heuristic" in order to be tolerant
1218 // towards Dicom-non-conformant files:
1219 // << whatever the "Planar Configuration" value might be, a
1220 // "Photometric Interpretation" set to "PALETTE COLOR" forces
1221 // a LUT intervention >>
1223 // Now we are left with the following handling of the cases:
1224 // - [Planar 0] OR [Photo A] no color decoding (since respectively
1225 // Pixels are already RGB and monochrome pictures have no color :),
1226 // - [Planar 1] AND [Photo B] handled with ConvertRGBPlanesToRGBPixels()
1227 // - [Planar 1] AND [Photo C] handled with ConvertYcBcRPlanesToRGBPixels()
1228 // - [Planar 2] OR [Photo D] requires LUT intervention.
1230 gdcmWarningMacro("--> ConvertHandleColor"
1231 << "Planar Configuration " << PlanarConfiguration );
1235 // [Planar 2] OR [Photo D]: LUT intervention done outside
1236 gdcmWarningMacro("--> RawRGB : LUT intervention done outside");
1240 if ( PlanarConfiguration == 1 )
1244 // [Planar 1] AND [Photo C] (remember YBR_FULL_422 acts as RGB)
1245 gdcmWarningMacro("--> YBRFull");
1246 ConvertYcBcRPlanesToRGBPixels();
1250 // [Planar 1] AND [Photo C]
1251 gdcmWarningMacro("--> YBRFull");
1252 ConvertRGBPlanesToRGBPixels();
1257 // When planarConf is 0, and RLELossless (forbidden by Dicom norm)
1258 // pixels need to be RGB-fyied anyway
1262 gdcmWarningMacro("--> RLE Lossless");
1263 ConvertRGBPlanesToRGBPixels();
1266 // In *normal *case, when planarConf is 0, pixels are already in RGB
1269 /// Computes the Pixels Size
1270 void PixelReadConvert::ComputeRawAndRGBSizes()
1272 int bitsAllocated = BitsAllocated;
1273 // Number of "Bits Allocated" is fixed to 16 when it's 12, since
1274 // in this case we will expand the image to 16 bits (see
1275 // \ref ReadAndDecompress12BitsTo16Bits() )
1276 if ( BitsAllocated == 12 )
1281 RawSize = XSize * YSize * ZSize
1282 * ( bitsAllocated / 8 )
1286 RGBSize = 3 * RawSize; // works for 8 and 16 bits per Pixel
1294 /// Allocates room for RGB Pixels
1295 void PixelReadConvert::AllocateRGB()
1299 RGB = new uint8_t[RGBSize];
1302 /// Allocates room for RAW Pixels
1303 void PixelReadConvert::AllocateRaw()
1307 Raw = new uint8_t[RawSize];
1310 //-----------------------------------------------------------------------------
1313 * \brief Print self.
1314 * @param indent Indentation string to be prepended during printing.
1315 * @param os Stream to print to.
1317 void PixelReadConvert::Print( std::ostream &os, std::string const &indent )
1320 << "--- Pixel information -------------------------"
1323 << "Pixel Data: offset " << PixelOffset
1324 << " x(" << std::hex << PixelOffset << std::dec
1325 << ") length " << PixelDataLength
1326 << " x(" << std::hex << PixelDataLength << std::dec
1327 << ")" << std::endl;
1329 if ( IsRLELossless )
1333 RLEInfo->Print( os, indent );
1337 gdcmWarningMacro("Set as RLE file but NO RLEinfo present.");
1341 if ( IsJPEG2000 || IsJPEGLossless || IsJPEGLossy || IsJPEGLS )
1345 JPEGInfo->Print( os, indent );
1349 gdcmWarningMacro("Set as JPEG file but NO JPEGinfo present.");
1354 //-----------------------------------------------------------------------------
1355 } // end namespace gdcm
1357 // Note to developpers :
1358 // Here is a very detailled post from David Clunie, on the troubles caused
1359 // 'non standard' LUT and LUT description
1360 // We shall have to take it into accound in our code.
1365 Subject: Problem with VOI LUTs in Agfa and Fuji CR and GE DX images, was Re: VOI LUT issues
1366 Date: Sun, 06 Feb 2005 17:13:40 GMT
1367 From: David Clunie <dclunie@dclunie.com>
1368 Reply-To: dclunie@dclunie.com
1369 Newsgroups: comp.protocols.dicom
1370 References: <1107553502.040221.189550@o13g2000cwo.googlegroups.com>
1372 > THE LUT that comes with [my] image claims to be 16-bit, but none of the
1373 > values goes higher than 4095. That being said, though, none of my
1374 > original pixel values goes higher than that, either. I have read
1375 > elsewhere on this group that when that happens you are supposed to
1376 > adjust the LUT. Can someone be more specific? There was a thread from
1377 > 2002 where Marco and David were mentioning doing precisely that.
1384 You have encountered the well known "we know what the standard says but
1385 we are going to ignore it and do what we have been doing for almost
1386 a decade regardless" CR vendor bug. Agfa started this, but they are not
1387 the only vendor doing this now; GE and Fuji may have joined the club.
1389 Sadly, one needs to look at the LUT Data, figure out what the maximum
1390 value actually encoded is, and find the next highest power of 2 (e.g.
1391 212 in this case), to figure out what the range of the data is
1392 supposed to be. I have assumed that if the maximum value in the LUT
1393 data is less than a power of 2 minus 1 (e.g. 0xebc) then the intent
1394 of the vendor was not to use the maximum available grayscale range
1395 of the display (e.g. the maximum is 0xfff in this case). An alternative
1396 would be to scale to the actual maximum rather than a power of two.
1398 Very irritating, and in theory not totally reliable if one really
1399 intended the full 16 bits and only used, say 15, but that is extremely
1400 unlikely since everything would be too dark, and this heuristic
1403 There has never been anything in the standard that describes having
1404 to go through these convolutions. Since the only value in the
1405 standard that describes the bit depth of the LUT values is LUT
1406 Descriptor value 3 and that is (usually) always required to be
1407 either 8 or 16, it mystifies me how the creators' of these images
1408 imagine that the receiver is going to divine the range that is intended. Further, the standard is quite explicit that this 3rd
1409 value defines the range of LUT values, but as far as I am aware, all
1410 the vendors are ignoring the standard and indeed sending a third value
1413 This problem is not confined to CR, and is also seen with DX products.
1415 Typically I have seen:
1417 - Agfa CR, which usually (always ?) sends LUTs, values up to 0x0fff
1418 - Fuji CR, which occasionally send LUTs, values up to 0x03ff
1419 - GE DX, for presentation, which always have LUTs, up to 0x3fff
1421 Swissray, Siemens, Philips, Canon and Kodak never seem to send VOI LUTs
1422 at this point (which is a whole other problem). Note that the presence
1423 or absence of a VOI LUT as opposed to window values may be configurable
1424 on the modality in some cases, and I have just looked at what I happen
1425 to have received from a myriad of sites over whose configuration I have
1426 no control. This may be why the majority of Fuji images have no VOI LUTs,
1427 but a few do (or it may be the Siemens system that these Fuji images went
1428 through that perhaps added it). I do have some test Hologic DX images that
1429 are not from a clinical site that do actually get this right (a value
1430 of 12 for the third value and a max of 0xfff).
1432 Since almost every vendor that I have encountered that encodes LUTs
1433 makes this mistake, perhaps it is time to amend the standard to warn
1434 implementor's of receivers and/or sanction this bad behavior. We have
1435 talked about this in the past in WG 6 but so far everyone has been
1436 reluctant to write into the standard such a comment. Maybe it is time
1437 to try again, since if one is not aware of this problem, one cannot
1438 effectively implement display using VOI LUTs, and there is a vast
1439 installed base to contend with.
1441 I did not check presentation states, in which VOI LUTs could also be
1442 encountered, for the prevalence of this mistake, nor did I look at the
1443 encoding of Modality LUT's, which are unusual. Nor did I check digital
1444 mammography images. I would be interested to hear from anyone who has.
1448 PS. The following older thread in this newsgroup discusses this:
1450 "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"
1452 PPS. From a historical perspective, the following may be of interest.
1454 In the original standard in 1993, all that was said about this was a
1455 reference to the corresponding such where Modality LUTs are described
1458 "The third value specifies the number of bits for each entry in the
1459 LUT Data. It shall take the value 8 or 16. The LUT Data shall be stored
1460 in a format equivalent to 8 or 16 bits allocated and high bit equal
1463 Since the high bit hint was not apparently explicit enough, a very
1464 early CP, CP 15 (submitted by Agfa as it happens), replaced this with:
1466 "The third value conveys the range of LUT entry values. It shall take
1467 the value 8 or 16, corresponding with the LUT entry value range of
1470 Note: The third value is not required for describing the
1471 LUT data and is only included for informational usage
1472 and for maintaining compatibility with ACRNEMA 2.0.
1474 The LUT Data contains the LUT entry values."
1476 That is how it read in the 1996, 1998 and 1999 editions.
1478 By the 2000 edition, Supplement 33 that introduced presentation states
1479 extensively reworked this entire section and tried to explain this in
1482 "The output range is from 0 to 2^n-1 where n is the third value of LUT
1483 Descriptor. This range is always unsigned."
1485 and also added a note to spell out what the output range meant in the
1488 "9. The output of the Window Center/Width or VOI LUT transformation
1489 is either implicitly scaled to the full range of the display device
1490 if there is no succeeding transformation defined, or implicitly scaled
1491 to the full input range of the succeeding transformation step (such as
1492 the Presentation LUT), if present. See C.11.6.1."
1494 It still reads this way in the 2004 edition.
1496 Note that LUTs in other applications than the general VOI LUT allow for
1497 values other than 8 or 16 in the third value of LUT descriptor to permit
1498 ranges other than 0 to 255 or 65535.
1500 In addition, the DX Image Module specializes the VOI LUT
1501 attributes as follows, in PS 3.3 section C.8.11.3.1.5 (added in Sup 32):
1503 "The third value specifies the number of bits for each entry in the LUT
1504 Data (analogous to ìbits storedî). It shall be between 10-16. The LUT
1505 Data shall be stored in a format equivalent to 16 ìbits allocatedî and
1506 ìhigh bitî equal to ìbits storedî - 1. The third value conveys the range
1507 of LUT entry values. These unsigned LUT entry values shall range between
1508 0 and 2^n-1, where n is the third value of the LUT Descriptor."
1510 So in the case of the GE DX for presentation images, the third value of
1511 LUT descriptor is allowed to be and probably should be 14 rather than 16.