1 /*=========================================================================
4 Module: $RCSfile: gdcmPixelReadConvert.cxx,v $
6 Date: $Date: 2005/11/28 10:32:05 $
7 Version: $Revision: 1.102 $
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, char *inputdata, 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 IsPrivateGETransferSyntax = IsMPEG
119 = IsJPEG2000 = IsJPEGLS = IsJPEGLossy
120 = IsJPEGLossless = IsRLELossless
123 if (! file->IsDicomV3() ) // Should be ACR-NEMA file
129 std::string ts = file->GetTransferSyntax();
132 while (true) // short to write than if elseif elseif elseif ...
134 // mind the order : check the most usual first.
135 if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRLittleEndian) break;
136 if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRLittleEndian ) break;
137 if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRBigEndian) break;
138 if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRBigEndianPrivateGE) break;
139 if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::DeflatedExplicitVRLittleEndian) break;
142 // cache whether this is a strange GE transfer syntax (which uses
143 // a little endian transfer syntax for the header and a big endian
144 // transfer syntax for the pixel data).
145 IsPrivateGETransferSyntax =
146 ( Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRBigEndianPrivateGE );
148 IsMPEG = IsJPEG2000 = IsJPEGLS = IsJPEGLossy = IsJPEGLossless = IsRLELossless = false;
153 // mind the order : check the most usual first.
154 if( IsJPEGLossy = Global::GetTS()->IsJPEGLossy(ts) ) break;
155 if( IsJPEGLossless = Global::GetTS()->IsJPEGLossless(ts) ) break;
156 if( IsRLELossless = Global::GetTS()->IsRLELossless(ts) ) break;
157 if( IsJPEG2000 = Global::GetTS()->IsJPEG2000(ts) ) break;
158 if( IsMPEG = Global::GetTS()->IsMPEG(ts) ) break;
159 if( IsJPEGLS = Global::GetTS()->IsJPEGLS(ts) ) break;
160 gdcmWarningMacro("Unexpected Transfer Syntax :[" << ts << "]");
166 PixelOffset = file->GetPixelOffset();
167 PixelDataLength = file->GetPixelAreaLength();
168 RLEInfo = file->GetRLEInfo();
169 JPEGInfo = file->GetJPEGInfo();
171 IsMonochrome = file->IsMonochrome();
172 IsMonochrome1 = file->IsMonochrome1();
173 IsPaletteColor = file->IsPaletteColor();
174 IsYBRFull = file->IsYBRFull();
176 PlanarConfiguration = file->GetPlanarConfiguration();
178 /////////////////////////////////////////////////////////////////
180 HasLUT = file->HasLUT();
183 // Just in case some access to a File element requires disk access.
184 LutRedDescriptor = file->GetEntryString( 0x0028, 0x1101 );
185 LutGreenDescriptor = file->GetEntryString( 0x0028, 0x1102 );
186 LutBlueDescriptor = file->GetEntryString( 0x0028, 0x1103 );
188 // FIXME : The following comment is probabely meaningless, since LUT are *always*
189 // loaded at parsing time, whatever their length is.
191 // Depending on the value of Document::MAX_SIZE_LOAD_ELEMENT_VALUE
192 // [ refer to invocation of Document::SetMaxSizeLoadEntry() in
193 // Document::Document() ], the loading of the value (content) of a
194 // [Bin|Val]Entry occurence migth have been hindered (read simply NOT
195 // loaded). Hence, we first try to obtain the LUTs data from the file
196 // and when this fails we read the LUTs data directly from disk.
197 // \TODO Reading a [Bin|Val]Entry directly from disk is a kludge.
198 // We should NOT bypass the [Bin|Val]Entry class. Instead
199 // an access to an UNLOADED content of a [Bin|Val]Entry occurence
200 // (e.g. DataEntry::GetBinArea()) should force disk access from
201 // within the [Bin|Val]Entry class itself. The only problem
202 // is that the [Bin|Val]Entry is unaware of the FILE* is was
203 // parsed from. Fix that. FIXME.
206 file->LoadEntryBinArea(0x0028, 0x1201);
207 LutRedData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1201 );
210 gdcmWarningMacro("Unable to read Red Palette Color Lookup Table data");
214 file->LoadEntryBinArea(0x0028, 0x1202);
215 LutGreenData = (uint8_t*)file->GetEntryBinArea(0x0028, 0x1202 );
218 gdcmWarningMacro("Unable to read Green Palette Color Lookup Table data");
222 file->LoadEntryBinArea(0x0028, 0x1203);
223 LutBlueData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1203 );
226 gdcmWarningMacro("Unable to read Blue Palette Color Lookup Table data");
231 ComputeRawAndRGBSizes();
234 /// \brief Reads from disk and decompresses Pixels
235 bool PixelReadConvert::ReadAndDecompressPixelData( std::ifstream *fp )
237 // ComputeRawAndRGBSizes is already made by
238 // ::GrabInformationsFromfile. So, the structure sizes are
242 //////////////////////////////////////////////////
243 //// First stage: get our hands on the Pixel Data.
246 gdcmWarningMacro( "Unavailable file pointer." );
250 fp->seekg( PixelOffset, std::ios::beg );
251 if ( fp->fail() || fp->eof() )
253 gdcmWarningMacro( "Unable to find PixelOffset in file." );
259 //////////////////////////////////////////////////
260 //// Second stage: read from disk and decompress.
261 if ( BitsAllocated == 12 )
263 ReadAndDecompress12BitsTo16Bits( fp);
267 // This problem can be found when some obvious informations are found
268 // after the field containing the image data. In this case, these
269 // bad data are added to the size of the image (in the PixelDataLength
270 // variable). But RawSize is the right size of the image !
271 if ( PixelDataLength != RawSize )
273 gdcmWarningMacro( "Mismatch between PixelReadConvert : "
274 << PixelDataLength << " and RawSize : " << RawSize );
276 if ( PixelDataLength > RawSize )
278 fp->read( (char*)Raw, RawSize);
282 fp->read( (char*)Raw, PixelDataLength);
285 if ( fp->fail() || fp->eof())
287 gdcmWarningMacro( "Reading of Raw pixel data failed." );
291 else if ( IsRLELossless )
293 if ( ! RLEInfo->DecompressRLEFile
294 ( fp, Raw, XSize, YSize, ZSize, BitsAllocated ) )
296 gdcmWarningMacro( "RLE decompressor failed." );
302 //gdcmWarningMacro( "Sorry, MPEG not yet taken into account" );
304 // fp has already been seek to start of mpeg
305 //ReadMPEGFile(fp, (char*)Raw, PixelDataLength);
310 // Default case concerns JPEG family
311 if ( ! ReadAndDecompressJPEGFile( fp ) )
313 gdcmWarningMacro( "JPEG decompressor ( ReadAndDecompressJPEGFile()"
314 << " method ) failed." );
319 ////////////////////////////////////////////
320 //// Third stage: twigle the bytes and bits.
321 ConvertReorderEndianity();
322 ConvertReArrangeBits();
323 ConvertFixGreyLevels();
324 if (UserFunction) // user is allowed to Mirror, TopDown, Rotate,...the image
325 UserFunction( Raw, FileInternal);
326 ConvertHandleColor();
331 /// Deletes Pixels Area
332 void PixelReadConvert::Squeeze()
348 * \brief Build the RGB image from the Raw image and the LUTs.
350 bool PixelReadConvert::BuildRGBImage()
354 // The job is already done.
360 // The job can't be done
367 // The job can't be done
371 gdcmDebugMacro( "--> BuildRGBImage" );
377 if ( BitsAllocated <= 8 )
379 uint8_t *localRGB = RGB;
380 for (size_t i = 0; i < RawSize; ++i )
383 *localRGB++ = LutRGBA[j];
384 *localRGB++ = LutRGBA[j+1];
385 *localRGB++ = LutRGBA[j+2];
389 else // deal with 16 bits pixels and 16 bits Palette color
391 uint16_t *localRGB = (uint16_t *)RGB;
392 for (size_t i = 0; i < RawSize/2; ++i )
394 j = ((uint16_t *)Raw)[i] * 4;
395 *localRGB++ = ((uint16_t *)LutRGBA)[j];
396 *localRGB++ = ((uint16_t *)LutRGBA)[j+1];
397 *localRGB++ = ((uint16_t *)LutRGBA)[j+2];
404 //-----------------------------------------------------------------------------
407 //-----------------------------------------------------------------------------
410 * \brief Read from file a 12 bits per pixel image and decompress it
411 * into a 16 bits per pixel image.
413 void PixelReadConvert::ReadAndDecompress12BitsTo16Bits( std::ifstream *fp )
414 throw ( FormatError )
416 int nbPixels = XSize * YSize;
417 uint16_t *localDecompres = (uint16_t*)Raw;
419 for( int p = 0; p < nbPixels; p += 2 )
423 fp->read( (char*)&b0, 1);
424 if ( fp->fail() || fp->eof() )
426 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
427 "Unfound first block" );
430 fp->read( (char*)&b1, 1 );
431 if ( fp->fail() || fp->eof())
433 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
434 "Unfound second block" );
437 fp->read( (char*)&b2, 1 );
438 if ( fp->fail() || fp->eof())
440 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
441 "Unfound second block" );
444 // Two steps are necessary to please VC++
446 // 2 pixels 12bit = [0xABCDEF]
447 // 2 pixels 16bit = [0x0ABD] + [0x0FCE]
449 *localDecompres++ = ((b0 >> 4) << 8) + ((b0 & 0x0f) << 4) + (b1 & 0x0f);
451 *localDecompres++ = ((b2 & 0x0f) << 8) + ((b1 >> 4) << 4) + (b2 >> 4);
453 /// \todo JPR Troubles expected on Big-Endian processors ?
458 * \brief Reads from disk the Pixel Data of JPEG Dicom encapsulated
459 * file and decompress it.
460 * @param fp File Pointer
463 bool PixelReadConvert::ReadAndDecompressJPEGFile( std::ifstream *fp )
467 // make sure this is the right JPEG compression
468 assert( !IsJPEGLossless || !IsJPEGLossy || !IsJPEGLS );
469 // FIXME this is really ugly but it seems I have to load the complete
470 // jpeg2000 stream to use jasper:
471 // I don't think we'll ever be able to deal with multiple fragments properly
473 unsigned long inputlength = 0;
474 JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment();
477 inputlength += jpegfrag->GetLength();
478 jpegfrag = JPEGInfo->GetNextFragment();
480 gdcmAssertMacro( inputlength != 0);
481 uint8_t *inputdata = new uint8_t[inputlength];
482 char *pinputdata = (char*)inputdata;
483 jpegfrag = JPEGInfo->GetFirstFragment();
486 fp->seekg( jpegfrag->GetOffset(), std::ios::beg);
487 fp->read(pinputdata, jpegfrag->GetLength());
488 pinputdata += jpegfrag->GetLength();
489 jpegfrag = JPEGInfo->GetNextFragment();
491 // Warning the inputdata buffer is delete in the function
492 if ( ! gdcm_read_JPEG2000_file( Raw,
493 (char*)inputdata, inputlength ) )
497 // wow what happen, must be an error
498 gdcmWarningMacro( "gdcm_read_JPEG2000_file() failed ");
503 // make sure this is the right JPEG compression
504 assert( !IsJPEGLossless || !IsJPEGLossy || !IsJPEG2000 );
505 // WARNING : JPEG-LS is NOT the 'classical' Jpeg Lossless :
506 // [JPEG-LS is the basis for new lossless/near-lossless compression
507 // standard for continuous-tone images intended for JPEG2000. The standard
508 // is based on the LOCO-I algorithm (LOw COmplexity LOssless COmpression
509 // for Images) developed at Hewlett-Packard Laboratories]
511 // see http://datacompression.info/JPEGLS.shtml
514 std::cerr << "count:" << JPEGInfo->GetFragmentCount() << std::endl;
515 unsigned long inputlength = 0;
516 JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment();
519 inputlength += jpegfrag->GetLength();
520 jpegfrag = JPEGInfo->GetNextFragment();
522 gdcmAssertMacro( inputlength != 0);
523 uint8_t *inputdata = new uint8_t[inputlength];
524 char *pinputdata = (char*)inputdata;
525 jpegfrag = JPEGInfo->GetFirstFragment();
528 fp->seekg( jpegfrag->GetOffset(), std::ios::beg);
529 fp->read(pinputdata, jpegfrag->GetLength());
530 pinputdata += jpegfrag->GetLength();
531 jpegfrag = JPEGInfo->GetNextFragment();
534 //fp->read((char*)Raw, PixelDataLength);
536 std::ofstream out("/tmp/jpegls.jpg");
537 out.write((char*)inputdata, inputlength);
542 gdcmWarningMacro( "Sorry, JPEG-LS not yet taken into account" );
543 fp->seekg( JPEGInfo->GetFirstFragment()->GetOffset(), std::ios::beg);
544 // if ( ! gdcm_read_JPEGLS_file( fp,Raw ) )
549 // make sure this is the right JPEG compression
550 assert( !IsJPEGLS || !IsJPEG2000 );
551 // Precompute the offset localRaw will be shifted with
552 int length = XSize * YSize * SamplesPerPixel;
553 int numberBytes = BitsAllocated / 8;
555 JPEGInfo->DecompressFromFile(fp, Raw, BitsStored, numberBytes, length );
561 * \brief Build Red/Green/Blue/Alpha LUT from File when :
562 * - (0028,0004) : Photometric Interpretation == [PALETTE COLOR ]
564 * - (0028,1101),(0028,1102),(0028,1102)
565 * xxx Palette Color Lookup Table Descriptor are found
567 * - (0028,1201),(0028,1202),(0028,1202)
568 * xxx Palette Color Lookup Table Data - are found
569 * \warning does NOT deal with :
570 * - 0028 1100 Gray Lookup Table Descriptor (Retired)
571 * - 0028 1221 Segmented Red Palette Color Lookup Table Data
572 * - 0028 1222 Segmented Green Palette Color Lookup Table Data
573 * - 0028 1223 Segmented Blue Palette Color Lookup Table Data
574 * no known Dicom reader deals with them :-(
575 * @return a RGBA Lookup Table
577 void PixelReadConvert::BuildLUTRGBA()
580 // Note to code reviewers :
581 // The problem is *much more* complicated, since a lot of manufacturers
582 // Don't follow the norm :
583 // have a look at David Clunie's remark at the end of this .cxx file.
590 // http://www.barre.nom.fr/medical/dicom2/limitations.html#Color%20Lookup%20Tables
592 if ( ! IsPaletteColor )
597 if ( LutRedDescriptor == GDCM_UNFOUND
598 || LutGreenDescriptor == GDCM_UNFOUND
599 || LutBlueDescriptor == GDCM_UNFOUND )
601 gdcmWarningMacro( "(At least) a LUT Descriptor is missing" );
605 ////////////////////////////////////////////
606 // Extract the info from the LUT descriptors
607 int lengthR; // Red LUT length in Bytes
608 int debR; // Subscript of the first Lut Value
609 int nbitsR; // Lut item size (in Bits)
610 int nbRead; // nb of items in LUT descriptor (must be = 3)
612 nbRead = sscanf( LutRedDescriptor.c_str(),
614 &lengthR, &debR, &nbitsR );
617 gdcmWarningMacro( "Wrong Red LUT descriptor" );
619 int lengthG; // Green LUT length in Bytes
620 int debG; // Subscript of the first Lut Value
621 int nbitsG; // Lut item size (in Bits)
623 nbRead = sscanf( LutGreenDescriptor.c_str(),
625 &lengthG, &debG, &nbitsG );
628 gdcmWarningMacro( "Wrong Green LUT descriptor" );
631 int lengthB; // Blue LUT length in Bytes
632 int debB; // Subscript of the first Lut Value
633 int nbitsB; // Lut item size (in Bits)
634 nbRead = sscanf( LutRedDescriptor.c_str(),
636 &lengthB, &debB, &nbitsB );
639 gdcmWarningMacro( "Wrong Blue LUT descriptor" );
642 gdcmDebugMacro(" lengthR " << lengthR << " debR "
643 << debR << " nbitsR " << nbitsR);
644 gdcmDebugMacro(" lengthG " << lengthG << " debG "
645 << debG << " nbitsG " << nbitsG);
646 gdcmDebugMacro(" lengthB " << lengthB << " debB "
647 << debB << " nbitsB " << nbitsB);
649 if ( !lengthR ) // if = 2^16, this shall be 0 see : CP-143
651 if ( !lengthG ) // if = 2^16, this shall be 0
653 if ( !lengthB ) // if = 2^16, this shall be 0
656 ////////////////////////////////////////////////////////
658 if ( ( ! LutRedData ) || ( ! LutGreenData ) || ( ! LutBlueData ) )
660 gdcmWarningMacro( "(At least) a LUT is missing" );
664 // -------------------------------------------------------------
666 if ( BitsAllocated <= 8 )
668 // forge the 4 * 8 Bits Red/Green/Blue/Alpha LUT
669 LutRGBA = new uint8_t[ 1024 ]; // 256 * 4 (R, G, B, Alpha)
674 memset( LutRGBA, 0, 1024 );
677 if ( ( nbitsR == 16 ) && ( BitsAllocated == 8 ) )
679 // when LUT item size is different than pixel size
680 mult = 2; // high byte must be = low byte
684 // See PS 3.3-2003 C.11.1.1.2 p 619
688 // if we get a black image, let's just remove the '+1'
689 // from 'i*mult+1' and check again
690 // if it works, we shall have to check the 3 Palettes
691 // to see which byte is ==0 (first one, or second one)
693 // We give up the checking to avoid some (useless ?) overhead
694 // (optimistic asumption)
698 //take "Subscript of the first Lut Value" (debR,debG,debB) into account!
700 //FIXME : +1 : to get 'low value' byte
701 // Trouble expected on Big Endian Processors ?
702 // 16 BIts Per Pixel Palette Color to be swapped?
704 a = LutRGBA + 0 + debR;
705 for( i=0; i < lengthR; ++i )
707 *a = LutRedData[i*mult+1];
711 a = LutRGBA + 1 + debG;
712 for( i=0; i < lengthG; ++i)
714 *a = LutGreenData[i*mult+1];
718 a = LutRGBA + 2 + debB;
719 for(i=0; i < lengthB; ++i)
721 *a = LutBlueData[i*mult+1];
726 for(i=0; i < 256; ++i)
728 *a = 1; // Alpha component
734 // Probabely the same stuff is to be done for 16 Bits Pixels
735 // with 65536 entries LUT ?!?
736 // Still looking for accurate info on the web :-(
738 gdcmWarningMacro( "Sorry Palette Color Lookup Tables not yet dealt with"
739 << " for 16 Bits Per Pixel images" );
741 // forge the 4 * 16 Bits Red/Green/Blue/Alpha LUT
743 LutRGBA = (uint8_t *)new uint16_t[ 65536*4 ]; // 2^16 * 4 (R, G, B, Alpha)
746 memset( LutRGBA, 0, 65536*4*2 ); // 16 bits = 2 bytes ;-)
748 LutItemNumber = 65536;
754 //take "Subscript of the first Lut Value" (debR,debG,debB) into account!
756 a16 = (uint16_t*)LutRGBA + 0 + debR;
757 for( i=0; i < lengthR; ++i )
759 *a16 = ((uint16_t*)LutRedData)[i];
763 a16 = (uint16_t*)LutRGBA + 1 + debG;
764 for( i=0; i < lengthG; ++i)
766 *a16 = ((uint16_t*)LutGreenData)[i];
770 a16 = (uint16_t*)LutRGBA + 2 + debB;
771 for(i=0; i < lengthB; ++i)
773 *a16 = ((uint16_t*)LutBlueData)[i];
777 a16 = (uint16_t*)LutRGBA + 3 ;
778 for(i=0; i < 65536; ++i)
780 *a16 = 1; // Alpha component
783 /* Just to 'see' the LUT, at debug time
784 // Don't remove this commented out code.
786 a16=(uint16_t*)LutRGBA;
787 for (int j=0;j<65536;j++)
789 std::cout << *a16 << " " << *(a16+1) << " "
790 << *(a16+2) << " " << *(a16+3) << std::endl;
798 * \brief Swap the bytes, according to \ref SwapCode.
800 void PixelReadConvert::ConvertSwapZone()
804 // If this file is 'ImplicitVR BigEndian PrivateGE Transfer Syntax',
805 // then the header is in little endian format and the pixel data is in
806 // big endian format. When reading the header, GDCM has already established
807 // a byte swapping code suitable for this machine to read the
808 // header. In TS::ImplicitVRBigEndianPrivateGE, this code will need
809 // to be switched in order to read the pixel data. This must be
810 // done REGARDLESS of the processor endianess!
812 // Example: Assume we are on a little endian machine. When
813 // GDCM reads the header, the header will match the machine
814 // endianess and the swap code will be established as a no-op.
815 // When GDCM reaches the pixel data, it will need to switch the
816 // swap code to do big endian to little endian conversion.
818 // Now, assume we are on a big endian machine. When GDCM reads the
819 // header, the header will be recognized as a different endianess
820 // than the machine endianess, and a swap code will be established
821 // to convert from little endian to big endian. When GDCM readers
822 // the pixel data, the pixel data endianess will now match the
823 // machine endianess. But we currently have a swap code that
824 // converts from little endian to big endian. In this case, we
825 // need to switch the swap code to a no-op.
827 // Therefore, in either case, if the file is in
828 // 'ImplicitVR BigEndian PrivateGE Transfer Syntax', then GDCM needs to switch
829 // the byte swapping code when entering the pixel data.
831 int tempSwapCode = SwapCode;
832 if ( IsPrivateGETransferSyntax )
834 gdcmWarningMacro(" IsPrivateGETransferSyntax found; turn the SwapCode");
835 // PrivateGETransferSyntax only exists for 'true' Dicom images
836 // we assume there is no 'exotic' 32 bits endianess!
837 if (SwapCode == 1234)
841 else if (SwapCode == 4321)
847 if ( BitsAllocated == 16 )
849 uint16_t *im16 = (uint16_t*)Raw;
850 switch( tempSwapCode )
857 for( i = 0; i < RawSize / 2; i++ )
859 im16[i]= (im16[i] >> 8) | (im16[i] << 8 );
863 gdcmWarningMacro("SwapCode value (16 bits) not allowed."
867 else if ( BitsAllocated == 32 )
872 uint32_t *im32 = (uint32_t*)Raw;
873 switch ( tempSwapCode )
878 for( i = 0; i < RawSize / 4; i++ )
880 low = im32[i] & 0x0000ffff; // 4321
881 high = im32[i] >> 16;
882 high = ( high >> 8 ) | ( high << 8 );
883 low = ( low >> 8 ) | ( low << 8 );
885 im32[i] = ( s32 << 16 ) | high;
889 for( i = 0; i < RawSize / 4; i++ )
891 low = im32[i] & 0x0000ffff; // 2143
892 high = im32[i] >> 16;
893 high = ( high >> 8 ) | ( high << 8 );
894 low = ( low >> 8 ) | ( low << 8 );
896 im32[i] = ( s32 << 16 ) | low;
900 for( i = 0; i < RawSize / 4; i++ )
902 low = im32[i] & 0x0000ffff; // 3412
903 high = im32[i] >> 16;
905 im32[i] = ( s32 << 16 ) | high;
909 gdcmWarningMacro("SwapCode value (32 bits) not allowed." << tempSwapCode );
915 * \brief Deal with endianness i.e. re-arange bytes inside the integer
917 void PixelReadConvert::ConvertReorderEndianity()
919 if ( BitsAllocated != 8 )
924 // Special kludge in order to deal with xmedcon broken images:
925 if ( BitsAllocated == 16
926 && BitsStored < BitsAllocated
929 int l = (int)( RawSize / ( BitsAllocated / 8 ) );
930 uint16_t *deb = (uint16_t *)Raw;
931 for(int i = 0; i<l; i++)
933 if ( *deb == 0xffff )
943 * \brief Deal with Grey levels i.e. re-arange them
944 * to have low values = dark, high values = bright
946 void PixelReadConvert::ConvertFixGreyLevels()
951 uint32_t i; // to please M$VC6
956 if ( BitsAllocated == 8 )
958 uint8_t *deb = (uint8_t *)Raw;
959 for (i=0; i<RawSize; i++)
967 if ( BitsAllocated == 16 )
970 for (j=0; j<BitsStored-1; j++)
972 mask = (mask << 1) +1; // will be fff when BitsStored=12
975 uint16_t *deb = (uint16_t *)Raw;
976 for (i=0; i<RawSize/2; i++)
986 if ( BitsAllocated == 8 )
988 uint8_t smask8 = 255;
989 uint8_t *deb = (uint8_t *)Raw;
990 for (i=0; i<RawSize; i++)
992 *deb = smask8 - *deb;
997 if ( BitsAllocated == 16 )
999 uint16_t smask16 = 65535;
1000 uint16_t *deb = (uint16_t *)Raw;
1001 for (i=0; i<RawSize/2; i++)
1003 *deb = smask16 - *deb;
1012 * \brief Re-arrange the bits within the bytes.
1013 * @return Boolean always true
1015 bool PixelReadConvert::ConvertReArrangeBits() throw ( FormatError )
1018 if ( BitsStored != BitsAllocated )
1020 int l = (int)( RawSize / ( BitsAllocated / 8 ) );
1021 if ( BitsAllocated == 16 )
1023 // pmask : to mask the 'unused bits' (may contain overlays)
1024 uint16_t pmask = 0xffff;
1025 pmask = pmask >> ( BitsAllocated - BitsStored );
1027 uint16_t *deb = (uint16_t*)Raw;
1029 if ( !PixelSign ) // Pixels are unsigned
1031 for(int i = 0; i<l; i++)
1033 *deb = (*deb >> (BitsStored - HighBitPosition - 1)) & pmask;
1037 else // Pixels are signed
1039 // smask : to check the 'sign' when BitsStored != BitsAllocated
1040 uint16_t smask = 0x0001;
1041 smask = smask << ( 16 - (BitsAllocated - BitsStored + 1) );
1042 // nmask : to propagate sign bit on negative values
1043 int16_t nmask = (int16_t)0x8000;
1044 nmask = nmask >> ( BitsAllocated - BitsStored - 1 );
1046 for(int i = 0; i<l; i++)
1048 *deb = *deb >> (BitsStored - HighBitPosition - 1);
1051 *deb = *deb | nmask;
1055 *deb = *deb & pmask;
1061 else if ( BitsAllocated == 32 )
1063 // pmask : to mask the 'unused bits' (may contain overlays)
1064 uint32_t pmask = 0xffffffff;
1065 pmask = pmask >> ( BitsAllocated - BitsStored );
1067 uint32_t *deb = (uint32_t*)Raw;
1071 for(int i = 0; i<l; i++)
1073 *deb = (*deb >> (BitsStored - HighBitPosition - 1)) & pmask;
1079 // smask : to check the 'sign' when BitsStored != BitsAllocated
1080 uint32_t smask = 0x00000001;
1081 smask = smask >> ( 32 - (BitsAllocated - BitsStored +1 ));
1082 // nmask : to propagate sign bit on negative values
1083 int32_t nmask = 0x80000000;
1084 nmask = nmask >> ( BitsAllocated - BitsStored -1 );
1086 for(int i = 0; i<l; i++)
1088 *deb = *deb >> (BitsStored - HighBitPosition - 1);
1090 *deb = *deb | nmask;
1092 *deb = *deb & pmask;
1099 gdcmWarningMacro("Weird image (BitsAllocated !=8, 12, 16, 32)");
1100 throw FormatError( "Weird image !?" );
1107 * \brief Convert (Red plane, Green plane, Blue plane) to RGB pixels
1108 * \warning Works on all the frames at a time
1110 void PixelReadConvert::ConvertRGBPlanesToRGBPixels()
1112 gdcmWarningMacro("--> ConvertRGBPlanesToRGBPixels");
1114 uint8_t *localRaw = Raw;
1115 uint8_t *copyRaw = new uint8_t[ RawSize ];
1116 memmove( copyRaw, localRaw, RawSize );
1118 int l = XSize * YSize * ZSize;
1120 uint8_t *a = copyRaw;
1121 uint8_t *b = copyRaw + l;
1122 uint8_t *c = copyRaw + l + l;
1124 for (int j = 0; j < l; j++)
1126 *(localRaw++) = *(a++);
1127 *(localRaw++) = *(b++);
1128 *(localRaw++) = *(c++);
1134 * \brief Convert (cY plane, cB plane, cR plane) to RGB pixels
1135 * \warning Works on all the frames at a time
1137 void PixelReadConvert::ConvertYcBcRPlanesToRGBPixels()
1139 // Remarks for YBR newbees :
1140 // YBR_FULL works very much like RGB, i.e. three samples per pixel,
1141 // just the color space is YCbCr instead of RGB. This is particularly useful
1142 // for doppler ultrasound where most of the image is grayscale
1143 // (i.e. only populates the Y components) and Cb and Cr are mostly zero,
1144 // except for the few patches of color on the image.
1145 // On such images, RLE achieves a compression ratio that is much better
1146 // than the compression ratio on an equivalent RGB image.
1148 gdcmWarningMacro("--> ConvertYcBcRPlanesToRGBPixels");
1150 uint8_t *localRaw = Raw;
1151 uint8_t *copyRaw = new uint8_t[ RawSize ];
1152 memmove( copyRaw, localRaw, RawSize );
1154 // to see the tricks about YBR_FULL, YBR_FULL_422,
1155 // YBR_PARTIAL_422, YBR_ICT, YBR_RCT have a look at :
1156 // ftp://medical.nema.org/medical/dicom/final/sup61_ft.pdf
1157 // and be *very* affraid
1159 int l = XSize * YSize;
1160 int nbFrames = ZSize;
1162 uint8_t *a = copyRaw + 0;
1163 uint8_t *b = copyRaw + l;
1164 uint8_t *c = copyRaw + l+ l;
1167 /// We replaced easy to understand but time consuming floating point
1168 /// computations by the 'well known' integer computation counterpart
1170 /// http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf
1171 /// for code optimisation.
1173 for ( int i = 0; i < nbFrames; i++ )
1175 for ( int j = 0; j < l; j++ )
1177 R = 38142 *(*a-16) + 52298 *(*c -128);
1178 G = 38142 *(*a-16) - 26640 *(*c -128) - 12845 *(*b -128);
1179 B = 38142 *(*a-16) + 66093 *(*b -128);
1188 if (R > 255) R = 255;
1189 if (G > 255) G = 255;
1190 if (B > 255) B = 255;
1192 *(localRaw++) = (uint8_t)R;
1193 *(localRaw++) = (uint8_t)G;
1194 *(localRaw++) = (uint8_t)B;
1203 /// \brief Deals with the color decoding i.e. handle:
1204 /// - R, G, B planes (as opposed to RGB pixels)
1205 /// - YBR (various) encodings.
1206 /// - LUT[s] (or "PALETTE COLOR").
1208 void PixelReadConvert::ConvertHandleColor()
1210 //////////////////////////////////
1211 // Deal with the color decoding i.e. handle:
1212 // - R, G, B planes (as opposed to RGB pixels)
1213 // - YBR (various) encodings.
1214 // - LUT[s] (or "PALETTE COLOR").
1216 // The classification in the color decoding schema is based on the blending
1217 // of two Dicom tags values:
1218 // * "Photometric Interpretation" for which we have the cases:
1219 // - [Photo A] MONOCHROME[1|2] pictures,
1220 // - [Photo B] RGB or YBR_FULL_422 (which acts as RGB),
1221 // - [Photo C] YBR_* (with the above exception of YBR_FULL_422)
1222 // - [Photo D] "PALETTE COLOR" which indicates the presence of LUT[s].
1223 // * "Planar Configuration" for which we have the cases:
1224 // - [Planar 0] 0 then Pixels are already RGB
1225 // - [Planar 1] 1 then we have 3 planes : R, G, B,
1226 // - [Planar 2] 2 then we have 1 gray Plane and 3 LUTs
1228 // Now in theory, one could expect some coherence when blending the above
1229 // cases. For example we should not encounter files belonging at the
1230 // time to case [Planar 0] and case [Photo D].
1231 // Alas, this was only theory ! Because in practice some odd (read ill
1232 // formated Dicom) files (e.g. gdcmData/US-PAL-8-10x-echo.dcm) we encounter:
1233 // - "Planar Configuration" = 0,
1234 // - "Photometric Interpretation" = "PALETTE COLOR".
1235 // Hence gdcm will use the folowing "heuristic" in order to be tolerant
1236 // towards Dicom-non-conformant files:
1237 // << whatever the "Planar Configuration" value might be, a
1238 // "Photometric Interpretation" set to "PALETTE COLOR" forces
1239 // a LUT intervention >>
1241 // Now we are left with the following handling of the cases:
1242 // - [Planar 0] OR [Photo A] no color decoding (since respectively
1243 // Pixels are already RGB and monochrome pictures have no color :),
1244 // - [Planar 1] AND [Photo B] handled with ConvertRGBPlanesToRGBPixels()
1245 // - [Planar 1] AND [Photo C] handled with ConvertYcBcRPlanesToRGBPixels()
1246 // - [Planar 2] OR [Photo D] requires LUT intervention.
1248 gdcmDebugMacro("--> ConvertHandleColor "
1249 << "Planar Configuration " << PlanarConfiguration );
1253 // [Planar 2] OR [Photo D]: LUT intervention done outside
1254 gdcmDebugMacro("--> RawRGB : LUT intervention done outside");
1258 if ( PlanarConfiguration == 1 )
1262 // [Planar 1] AND [Photo C] (remember YBR_FULL_422 acts as RGB)
1263 gdcmDebugMacro("--> YBRFull");
1264 ConvertYcBcRPlanesToRGBPixels();
1268 // [Planar 1] AND [Photo C]
1269 gdcmDebugMacro("--> YBRFull");
1270 ConvertRGBPlanesToRGBPixels();
1275 // When planarConf is 0, and RLELossless (forbidden by Dicom norm)
1276 // pixels need to be RGB-fyied anyway
1280 gdcmDebugMacro("--> RLE Lossless");
1281 ConvertRGBPlanesToRGBPixels();
1284 // In *normal *case, when planarConf is 0, pixels are already in RGB
1287 /// Computes the Pixels Size
1288 void PixelReadConvert::ComputeRawAndRGBSizes()
1290 int bitsAllocated = BitsAllocated;
1291 // Number of "Bits Allocated" is fixed to 16 when it's 12, since
1292 // in this case we will expand the image to 16 bits (see
1293 // \ref ReadAndDecompress12BitsTo16Bits() )
1294 if ( BitsAllocated == 12 )
1299 RawSize = XSize * YSize * ZSize
1300 * ( bitsAllocated / 8 )
1304 RGBSize = 3 * RawSize; // works for 8 and 16 bits per Pixel
1312 /// Allocates room for RGB Pixels
1313 void PixelReadConvert::AllocateRGB()
1317 RGB = new uint8_t[RGBSize];
1320 /// Allocates room for RAW Pixels
1321 void PixelReadConvert::AllocateRaw()
1325 Raw = new uint8_t[RawSize];
1328 //-----------------------------------------------------------------------------
1331 * \brief Print self.
1332 * @param indent Indentation string to be prepended during printing.
1333 * @param os Stream to print to.
1335 void PixelReadConvert::Print( std::ostream &os, std::string const &indent )
1338 << "--- Pixel information -------------------------"
1341 << "Pixel Data: offset " << PixelOffset
1342 << " x(" << std::hex << PixelOffset << std::dec
1343 << ") length " << PixelDataLength
1344 << " x(" << std::hex << PixelDataLength << std::dec
1345 << ")" << std::endl;
1347 if ( IsRLELossless )
1351 RLEInfo->Print( os, indent );
1355 gdcmWarningMacro("Set as RLE file but NO RLEinfo present.");
1359 if ( IsJPEG2000 || IsJPEGLossless || IsJPEGLossy || IsJPEGLS )
1363 JPEGInfo->Print( os, indent );
1367 gdcmWarningMacro("Set as JPEG file but NO JPEGinfo present.");
1372 //-----------------------------------------------------------------------------
1373 } // end namespace gdcm
1375 // Note to developpers :
1376 // Here is a very detailled post from David Clunie, on the troubles caused
1377 // 'non standard' LUT and LUT description
1378 // We shall have to take it into accound in our code.
1383 Subject: Problem with VOI LUTs in Agfa and Fuji CR and GE DX images, was Re: VOI LUT issues
1384 Date: Sun, 06 Feb 2005 17:13:40 GMT
1385 From: David Clunie <dclunie@dclunie.com>
1386 Reply-To: dclunie@dclunie.com
1387 Newsgroups: comp.protocols.dicom
1388 References: <1107553502.040221.189550@o13g2000cwo.googlegroups.com>
1390 > THE LUT that comes with [my] image claims to be 16-bit, but none of the
1391 > values goes higher than 4095. That being said, though, none of my
1392 > original pixel values goes higher than that, either. I have read
1393 > elsewhere on this group that when that happens you are supposed to
1394 > adjust the LUT. Can someone be more specific? There was a thread from
1395 > 2002 where Marco and David were mentioning doing precisely that.
1402 You have encountered the well known "we know what the standard says but
1403 we are going to ignore it and do what we have been doing for almost
1404 a decade regardless" CR vendor bug. Agfa started this, but they are not
1405 the only vendor doing this now; GE and Fuji may have joined the club.
1407 Sadly, one needs to look at the LUT Data, figure out what the maximum
1408 value actually encoded is, and find the next highest power of 2 (e.g.
1409 212 in this case), to figure out what the range of the data is
1410 supposed to be. I have assumed that if the maximum value in the LUT
1411 data is less than a power of 2 minus 1 (e.g. 0xebc) then the intent
1412 of the vendor was not to use the maximum available grayscale range
1413 of the display (e.g. the maximum is 0xfff in this case). An alternative
1414 would be to scale to the actual maximum rather than a power of two.
1416 Very irritating, and in theory not totally reliable if one really
1417 intended the full 16 bits and only used, say 15, but that is extremely
1418 unlikely since everything would be too dark, and this heuristic
1421 There has never been anything in the standard that describes having
1422 to go through these convolutions. Since the only value in the
1423 standard that describes the bit depth of the LUT values is LUT
1424 Descriptor value 3 and that is (usually) always required to be
1425 either 8 or 16, it mystifies me how the creators' of these images
1426 imagine that the receiver is going to divine the range that is intended. Further, the standard is quite explicit that this 3rd
1427 value defines the range of LUT values, but as far as I am aware, all
1428 the vendors are ignoring the standard and indeed sending a third value
1431 This problem is not confined to CR, and is also seen with DX products.
1433 Typically I have seen:
1435 - Agfa CR, which usually (always ?) sends LUTs, values up to 0x0fff
1436 - Fuji CR, which occasionally send LUTs, values up to 0x03ff
1437 - GE DX, for presentation, which always have LUTs, up to 0x3fff
1439 Swissray, Siemens, Philips, Canon and Kodak never seem to send VOI LUTs
1440 at this point (which is a whole other problem). Note that the presence
1441 or absence of a VOI LUT as opposed to window values may be configurable
1442 on the modality in some cases, and I have just looked at what I happen
1443 to have received from a myriad of sites over whose configuration I have
1444 no control. This may be why the majority of Fuji images have no VOI LUTs,
1445 but a few do (or it may be the Siemens system that these Fuji images went
1446 through that perhaps added it). I do have some test Hologic DX images that
1447 are not from a clinical site that do actually get this right (a value
1448 of 12 for the third value and a max of 0xfff).
1450 Since almost every vendor that I have encountered that encodes LUTs
1451 makes this mistake, perhaps it is time to amend the standard to warn
1452 implementor's of receivers and/or sanction this bad behavior. We have
1453 talked about this in the past in WG 6 but so far everyone has been
1454 reluctant to write into the standard such a comment. Maybe it is time
1455 to try again, since if one is not aware of this problem, one cannot
1456 effectively implement display using VOI LUTs, and there is a vast
1457 installed base to contend with.
1459 I did not check presentation states, in which VOI LUTs could also be
1460 encountered, for the prevalence of this mistake, nor did I look at the
1461 encoding of Modality LUT's, which are unusual. Nor did I check digital
1462 mammography images. I would be interested to hear from anyone who has.
1466 PS. The following older thread in this newsgroup discusses this:
1468 "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"
1470 PPS. From a historical perspective, the following may be of interest.
1472 In the original standard in 1993, all that was said about this was a
1473 reference to the corresponding such where Modality LUTs are described
1476 "The third value specifies the number of bits for each entry in the
1477 LUT Data. It shall take the value 8 or 16. The LUT Data shall be stored
1478 in a format equivalent to 8 or 16 bits allocated and high bit equal
1481 Since the high bit hint was not apparently explicit enough, a very
1482 early CP, CP 15 (submitted by Agfa as it happens), replaced this with:
1484 "The third value conveys the range of LUT entry values. It shall take
1485 the value 8 or 16, corresponding with the LUT entry value range of
1488 Note: The third value is not required for describing the
1489 LUT data and is only included for informational usage
1490 and for maintaining compatibility with ACRNEMA 2.0.
1492 The LUT Data contains the LUT entry values."
1494 That is how it read in the 1996, 1998 and 1999 editions.
1496 By the 2000 edition, Supplement 33 that introduced presentation states
1497 extensively reworked this entire section and tried to explain this in
1500 "The output range is from 0 to 2^n-1 where n is the third value of LUT
1501 Descriptor. This range is always unsigned."
1503 and also added a note to spell out what the output range meant in the
1506 "9. The output of the Window Center/Width or VOI LUT transformation
1507 is either implicitly scaled to the full range of the display device
1508 if there is no succeeding transformation defined, or implicitly scaled
1509 to the full input range of the succeeding transformation step (such as
1510 the Presentation LUT), if present. See C.11.6.1."
1512 It still reads this way in the 2004 edition.
1514 Note that LUTs in other applications than the general VOI LUT allow for
1515 values other than 8 or 16 in the third value of LUT descriptor to permit
1516 ranges other than 0 to 255 or 65535.
1518 In addition, the DX Image Module specializes the VOI LUT
1519 attributes as follows, in PS 3.3 section C.8.11.3.1.5 (added in Sup 32):
1521 "The third value specifies the number of bits for each entry in the LUT
1522 Data (analogous to ìbits storedî). It shall be between 10-16. The LUT
1523 Data shall be stored in a format equivalent to 16 ìbits allocatedî and
1524 ìhigh bitî equal to ìbits storedî - 1. The third value conveys the range
1525 of LUT entry values. These unsigned LUT entry values shall range between
1526 0 and 2^n-1, where n is the third value of the LUT Descriptor."
1528 So in the case of the GE DX for presentation images, the third value of
1529 LUT descriptor is allowed to be and probably should be 14 rather than 16.