1 /*=========================================================================
4 Module: $RCSfile: gdcmPixelReadConvert.cxx,v $
6 Date: $Date: 2005/11/08 16:35:54 $
7 Version: $Revision: 1.97 $
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 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();
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;
143 IsPrivateGETransferSyntax =
144 ( Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRBigEndianPrivateGE );
146 IsMPEG = IsJPEG2000 = IsJPEGLS = IsJPEGLossy = IsJPEGLossless = IsRLELossless = false;
152 // mind the order : check the most usual first.
153 if( IsJPEGLossy = Global::GetTS()->IsJPEGLossy(ts) ) break;
154 if( IsJPEGLossless = Global::GetTS()->IsJPEGLossless(ts) ) break;
155 if( IsRLELossless = Global::GetTS()->IsRLELossless(ts) ) break;
156 if( IsJPEG2000 = Global::GetTS()->IsJPEG2000(ts) ) break;
157 if( IsMPEG = Global::GetTS()->IsMPEG(ts) ) break;
158 if( IsJPEGLS = Global::GetTS()->IsJPEGLS(ts) ) break;
159 gdcmWarningMacro("Unexepected Transfer Syntax :[" << ts << "]");
165 PixelOffset = file->GetPixelOffset();
166 PixelDataLength = file->GetPixelAreaLength();
167 RLEInfo = file->GetRLEInfo();
168 JPEGInfo = file->GetJPEGInfo();
170 IsMonochrome = file->IsMonochrome();
171 IsMonochrome1 = file->IsMonochrome1();
172 IsPaletteColor = file->IsPaletteColor();
173 IsYBRFull = file->IsYBRFull();
175 PlanarConfiguration = file->GetPlanarConfiguration();
177 /////////////////////////////////////////////////////////////////
179 HasLUT = file->HasLUT();
182 // Just in case some access to a File element requires disk access.
183 LutRedDescriptor = file->GetEntryString( 0x0028, 0x1101 );
184 LutGreenDescriptor = file->GetEntryString( 0x0028, 0x1102 );
185 LutBlueDescriptor = file->GetEntryString( 0x0028, 0x1103 );
187 // FIXME : The following comment is probabely meaningless, since LUT are *always*
188 // loaded at parsing time, whatever their length is.
190 // Depending on the value of Document::MAX_SIZE_LOAD_ELEMENT_VALUE
191 // [ refer to invocation of Document::SetMaxSizeLoadEntry() in
192 // Document::Document() ], the loading of the value (content) of a
193 // [Bin|Val]Entry occurence migth have been hindered (read simply NOT
194 // loaded). Hence, we first try to obtain the LUTs data from the file
195 // and when this fails we read the LUTs data directly from disk.
196 // \TODO Reading a [Bin|Val]Entry directly from disk is a kludge.
197 // We should NOT bypass the [Bin|Val]Entry class. Instead
198 // an access to an UNLOADED content of a [Bin|Val]Entry occurence
199 // (e.g. DataEntry::GetBinArea()) should force disk access from
200 // within the [Bin|Val]Entry class itself. The only problem
201 // is that the [Bin|Val]Entry is unaware of the FILE* is was
202 // parsed from. Fix that. FIXME.
205 file->LoadEntryBinArea(0x0028, 0x1201);
206 LutRedData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1201 );
209 gdcmWarningMacro("Unable to read Red Palette Color Lookup Table data");
213 file->LoadEntryBinArea(0x0028, 0x1202);
214 LutGreenData = (uint8_t*)file->GetEntryBinArea(0x0028, 0x1202 );
217 gdcmWarningMacro("Unable to read Green Palette Color Lookup Table data");
221 file->LoadEntryBinArea(0x0028, 0x1203);
222 LutBlueData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1203 );
225 gdcmWarningMacro("Unable to read Blue Palette Color Lookup Table data");
230 ComputeRawAndRGBSizes();
233 /// \brief Reads from disk and decompresses Pixels
234 bool PixelReadConvert::ReadAndDecompressPixelData( std::ifstream *fp )
236 // ComputeRawAndRGBSizes is already made by
237 // ::GrabInformationsFromfile. So, the structure sizes are
241 //////////////////////////////////////////////////
242 //// First stage: get our hands on the Pixel Data.
245 gdcmWarningMacro( "Unavailable file pointer." );
249 fp->seekg( PixelOffset, std::ios::beg );
250 if ( fp->fail() || fp->eof() )
252 gdcmWarningMacro( "Unable to find PixelOffset in file." );
258 //////////////////////////////////////////////////
259 //// Second stage: read from disk and decompress.
260 if ( BitsAllocated == 12 )
262 ReadAndDecompress12BitsTo16Bits( fp);
266 // This problem can be found when some obvious informations are found
267 // after the field containing the image data. In this case, these
268 // bad data are added to the size of the image (in the PixelDataLength
269 // variable). But RawSize is the right size of the image !
270 if ( PixelDataLength != RawSize )
272 gdcmWarningMacro( "Mismatch between PixelReadConvert : "
273 << PixelDataLength << " and RawSize : " << RawSize );
275 if ( PixelDataLength > RawSize )
277 fp->read( (char*)Raw, RawSize);
281 fp->read( (char*)Raw, PixelDataLength);
284 if ( fp->fail() || fp->eof())
286 gdcmWarningMacro( "Reading of Raw pixel data failed." );
290 else if ( IsRLELossless )
292 if ( ! RLEInfo->DecompressRLEFile
293 ( fp, Raw, XSize, YSize, ZSize, BitsAllocated ) )
295 gdcmWarningMacro( "RLE decompressor failed." );
301 //gdcmWarningMacro( "Sorry, MPEG not yet taken into account" );
303 // fp has already been seek to start of mpeg
304 ReadMPEGFile(fp, (char*)Raw, PixelDataLength);
309 // Default case concerns JPEG family
310 if ( ! ReadAndDecompressJPEGFile( fp ) )
312 gdcmWarningMacro( "JPEG decompressor failed." );
317 ////////////////////////////////////////////
318 //// Third stage: twigle the bytes and bits.
319 ConvertReorderEndianity();
320 ConvertReArrangeBits();
321 ConvertFixGreyLevels();
322 if (UserFunction) // user is allowed to Mirror, TopDown, Rotate,...the image
323 UserFunction( Raw, FileInternal);
324 ConvertHandleColor();
329 /// Deletes Pixels Area
330 void PixelReadConvert::Squeeze()
346 * \brief Build the RGB image from the Raw image and the LUTs.
348 bool PixelReadConvert::BuildRGBImage()
352 // The job is already done.
358 // The job can't be done
365 // The job can't be done
369 gdcmWarningMacro( "--> BuildRGBImage" );
375 if ( BitsAllocated <= 8 )
377 uint8_t *localRGB = RGB;
378 for (size_t i = 0; i < RawSize; ++i )
381 *localRGB++ = LutRGBA[j];
382 *localRGB++ = LutRGBA[j+1];
383 *localRGB++ = LutRGBA[j+2];
387 else // deal with 16 bits pixels and 16 bits Palette color
389 uint16_t *localRGB = (uint16_t *)RGB;
390 for (size_t i = 0; i < RawSize/2; ++i )
392 j = ((uint16_t *)Raw)[i] * 4;
393 *localRGB++ = ((uint16_t *)LutRGBA)[j];
394 *localRGB++ = ((uint16_t *)LutRGBA)[j+1];
395 *localRGB++ = ((uint16_t *)LutRGBA)[j+2];
402 //-----------------------------------------------------------------------------
405 //-----------------------------------------------------------------------------
408 * \brief Read from file a 12 bits per pixel image and decompress it
409 * into a 16 bits per pixel image.
411 void PixelReadConvert::ReadAndDecompress12BitsTo16Bits( std::ifstream *fp )
412 throw ( FormatError )
414 int nbPixels = XSize * YSize;
415 uint16_t *localDecompres = (uint16_t*)Raw;
417 for( int p = 0; p < nbPixels; p += 2 )
421 fp->read( (char*)&b0, 1);
422 if ( fp->fail() || fp->eof() )
424 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
425 "Unfound first block" );
428 fp->read( (char*)&b1, 1 );
429 if ( fp->fail() || fp->eof())
431 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
432 "Unfound second block" );
435 fp->read( (char*)&b2, 1 );
436 if ( fp->fail() || fp->eof())
438 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
439 "Unfound second block" );
442 // Two steps are necessary to please VC++
444 // 2 pixels 12bit = [0xABCDEF]
445 // 2 pixels 16bit = [0x0ABD] + [0x0FCE]
447 *localDecompres++ = ((b0 >> 4) << 8) + ((b0 & 0x0f) << 4) + (b1 & 0x0f);
449 *localDecompres++ = ((b2 & 0x0f) << 8) + ((b1 >> 4) << 4) + (b2 >> 4);
451 /// \todo JPR Troubles expected on Big-Endian processors ?
456 * \brief Reads from disk the Pixel Data of JPEG Dicom encapsulated
457 * file and decompress it.
458 * @param fp File Pointer
461 bool PixelReadConvert::ReadAndDecompressJPEGFile( std::ifstream *fp )
465 // make sure this is the right JPEG compression
466 assert( !IsJPEGLossless || !IsJPEGLossy || !IsJPEGLS );
467 // FIXME this is really ugly but it seems I have to load the complete
468 // jpeg2000 stream to use jasper:
469 // I don't think we'll ever be able to deal with multiple fragments properly
471 unsigned long inputlength = 0;
472 JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment();
475 inputlength += jpegfrag->GetLength();
476 jpegfrag = JPEGInfo->GetNextFragment();
478 gdcmAssertMacro( inputlength != 0);
479 uint8_t *inputdata = new uint8_t[inputlength];
480 char *pinputdata = (char*)inputdata;
481 jpegfrag = JPEGInfo->GetFirstFragment();
484 fp->seekg( jpegfrag->GetOffset(), std::ios::beg);
485 fp->read(pinputdata, jpegfrag->GetLength());
486 pinputdata += jpegfrag->GetLength();
487 jpegfrag = JPEGInfo->GetNextFragment();
489 // Warning the inputdata buffer is delete in the function
490 if ( ! gdcm_read_JPEG2000_file( Raw,
491 (char*)inputdata, inputlength ) )
495 // wow what happen, must be an error
500 // make sure this is the right JPEG compression
501 assert( !IsJPEGLossless || !IsJPEGLossy || !IsJPEG2000 );
502 // WARNING : JPEG-LS is NOT the 'classical' Jpeg Lossless :
503 // [JPEG-LS is the basis for new lossless/near-lossless compression
504 // standard for continuous-tone images intended for JPEG2000. The standard
505 // is based on the LOCO-I algorithm (LOw COmplexity LOssless COmpression
506 // for Images) developed at Hewlett-Packard Laboratories]
508 // see http://datacompression.info/JPEGLS.shtml
511 std::cerr << "count:" << JPEGInfo->GetFragmentCount() << std::endl;
512 unsigned long inputlength = 0;
513 JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment();
516 inputlength += jpegfrag->GetLength();
517 jpegfrag = JPEGInfo->GetNextFragment();
519 gdcmAssertMacro( inputlength != 0);
520 uint8_t *inputdata = new uint8_t[inputlength];
521 char *pinputdata = (char*)inputdata;
522 jpegfrag = JPEGInfo->GetFirstFragment();
525 fp->seekg( jpegfrag->GetOffset(), std::ios::beg);
526 fp->read(pinputdata, jpegfrag->GetLength());
527 pinputdata += jpegfrag->GetLength();
528 jpegfrag = JPEGInfo->GetNextFragment();
531 //fp->read((char*)Raw, PixelDataLength);
533 std::ofstream out("/tmp/jpegls.jpg");
534 out.write((char*)inputdata, inputlength);
539 gdcmWarningMacro( "Sorry, JPEG-LS not yet taken into account" );
540 fp->seekg( JPEGInfo->GetFirstFragment()->GetOffset(), std::ios::beg);
541 // if ( ! gdcm_read_JPEGLS_file( fp,Raw ) )
546 // make sure this is the right JPEG compression
547 assert( !IsJPEGLS || !IsJPEG2000 );
548 // Precompute the offset localRaw will be shifted with
549 int length = XSize * YSize * SamplesPerPixel;
550 int numberBytes = BitsAllocated / 8;
552 JPEGInfo->DecompressFromFile(fp, Raw, BitsStored, numberBytes, length );
558 * \brief Build Red/Green/Blue/Alpha LUT from File when :
559 * - (0028,0004) : Photometric Interpretation == [PALETTE COLOR ]
561 * - (0028,1101),(0028,1102),(0028,1102)
562 * xxx Palette Color Lookup Table Descriptor are found
564 * - (0028,1201),(0028,1202),(0028,1202)
565 * xxx Palette Color Lookup Table Data - are found
566 * \warning does NOT deal with :
567 * - 0028 1100 Gray Lookup Table Descriptor (Retired)
568 * - 0028 1221 Segmented Red Palette Color Lookup Table Data
569 * - 0028 1222 Segmented Green Palette Color Lookup Table Data
570 * - 0028 1223 Segmented Blue Palette Color Lookup Table Data
571 * no known Dicom reader deals with them :-(
572 * @return a RGBA Lookup Table
574 void PixelReadConvert::BuildLUTRGBA()
577 // Note to code reviewers :
578 // The problem is *much more* complicated, since a lot of manufacturers
579 // Don't follow the norm :
580 // have a look at David Clunie's remark at the end of this .cxx file.
587 // http://www.barre.nom.fr/medical/dicom2/limitations.html#Color%20Lookup%20Tables
589 if ( ! IsPaletteColor )
594 if ( LutRedDescriptor == GDCM_UNFOUND
595 || LutGreenDescriptor == GDCM_UNFOUND
596 || LutBlueDescriptor == GDCM_UNFOUND )
598 gdcmWarningMacro( "(At least) a LUT Descriptor is missing" );
602 ////////////////////////////////////////////
603 // Extract the info from the LUT descriptors
604 int lengthR; // Red LUT length in Bytes
605 int debR; // Subscript of the first Lut Value
606 int nbitsR; // Lut item size (in Bits)
607 int nbRead; // nb of items in LUT descriptor (must be = 3)
609 nbRead = sscanf( LutRedDescriptor.c_str(),
611 &lengthR, &debR, &nbitsR );
614 gdcmWarningMacro( "Wrong Red LUT descriptor" );
616 int lengthG; // Green LUT length in Bytes
617 int debG; // Subscript of the first Lut Value
618 int nbitsG; // Lut item size (in Bits)
620 nbRead = sscanf( LutGreenDescriptor.c_str(),
622 &lengthG, &debG, &nbitsG );
625 gdcmWarningMacro( "Wrong Green LUT descriptor" );
628 int lengthB; // Blue LUT length in Bytes
629 int debB; // Subscript of the first Lut Value
630 int nbitsB; // Lut item size (in Bits)
631 nbRead = sscanf( LutRedDescriptor.c_str(),
633 &lengthB, &debB, &nbitsB );
636 gdcmWarningMacro( "Wrong Blue LUT descriptor" );
639 gdcmWarningMacro(" lengthR " << lengthR << " debR "
640 << debR << " nbitsR " << nbitsR);
641 gdcmWarningMacro(" lengthG " << lengthG << " debG "
642 << debG << " nbitsG " << nbitsG);
643 gdcmWarningMacro(" lengthB " << lengthB << " debB "
644 << debB << " nbitsB " << nbitsB);
646 if ( !lengthR ) // if = 2^16, this shall be 0 see : CP-143
648 if ( !lengthG ) // if = 2^16, this shall be 0
650 if ( !lengthB ) // if = 2^16, this shall be 0
653 ////////////////////////////////////////////////////////
655 if ( ( ! LutRedData ) || ( ! LutGreenData ) || ( ! LutBlueData ) )
657 gdcmWarningMacro( "(At least) a LUT is missing" );
661 // -------------------------------------------------------------
663 if ( BitsAllocated <= 8 )
665 // forge the 4 * 8 Bits Red/Green/Blue/Alpha LUT
666 LutRGBA = new uint8_t[ 1024 ]; // 256 * 4 (R, G, B, Alpha)
671 memset( LutRGBA, 0, 1024 );
674 if ( ( nbitsR == 16 ) && ( BitsAllocated == 8 ) )
676 // when LUT item size is different than pixel size
677 mult = 2; // high byte must be = low byte
681 // See PS 3.3-2003 C.11.1.1.2 p 619
685 // if we get a black image, let's just remove the '+1'
686 // from 'i*mult+1' and check again
687 // if it works, we shall have to check the 3 Palettes
688 // to see which byte is ==0 (first one, or second one)
690 // We give up the checking to avoid some (useless ?) overhead
691 // (optimistic asumption)
695 //take "Subscript of the first Lut Value" (debR,debG,debB) into account!
697 //FIXME : +1 : to get 'low value' byte
698 // Trouble expected on Big Endian Processors ?
699 // 16 BIts Per Pixel Palette Color to be swapped?
701 a = LutRGBA + 0 + debR;
702 for( i=0; i < lengthR; ++i )
704 *a = LutRedData[i*mult+1];
708 a = LutRGBA + 1 + debG;
709 for( i=0; i < lengthG; ++i)
711 *a = LutGreenData[i*mult+1];
715 a = LutRGBA + 2 + debB;
716 for(i=0; i < lengthB; ++i)
718 *a = LutBlueData[i*mult+1];
723 for(i=0; i < 256; ++i)
725 *a = 1; // Alpha component
731 // Probabely the same stuff is to be done for 16 Bits Pixels
732 // with 65536 entries LUT ?!?
733 // Still looking for accurate info on the web :-(
735 gdcmWarningMacro( "Sorry Palette Color Lookup Tables not yet dealt with"
736 << " for 16 Bits Per Pixel images" );
738 // forge the 4 * 16 Bits Red/Green/Blue/Alpha LUT
740 LutRGBA = (uint8_t *)new uint16_t[ 65536*4 ]; // 2^16 * 4 (R, G, B, Alpha)
743 memset( LutRGBA, 0, 65536*4*2 ); // 16 bits = 2 bytes ;-)
745 LutItemNumber = 65536;
751 //take "Subscript of the first Lut Value" (debR,debG,debB) into account!
753 a16 = (uint16_t*)LutRGBA + 0 + debR;
754 for( i=0; i < lengthR; ++i )
756 *a16 = ((uint16_t*)LutRedData)[i];
760 a16 = (uint16_t*)LutRGBA + 1 + debG;
761 for( i=0; i < lengthG; ++i)
763 *a16 = ((uint16_t*)LutGreenData)[i];
767 a16 = (uint16_t*)LutRGBA + 2 + debB;
768 for(i=0; i < lengthB; ++i)
770 *a16 = ((uint16_t*)LutBlueData)[i];
774 a16 = (uint16_t*)LutRGBA + 3 ;
775 for(i=0; i < 65536; ++i)
777 *a16 = 1; // Alpha component
780 /* Just to 'see' the LUT, at debug time
781 // Don't remove this commented out code.
783 a16=(uint16_t*)LutRGBA;
784 for (int j=0;j<65536;j++)
786 std::cout << *a16 << " " << *(a16+1) << " "
787 << *(a16+2) << " " << *(a16+3) << std::endl;
795 * \brief Swap the bytes, according to \ref SwapCode.
797 void PixelReadConvert::ConvertSwapZone()
800 uint16_t localSwapCode = SwapCode;
802 // If this file is 'ImplicitVR BigEndian PrivateGE Transfer Syntax',
803 // then the header is in little endian format and the pixel data is in
804 // big endian format. When reading the header, GDCM has already established
805 // a byte swapping code suitable for this machine to read the
806 // header. In TS::ImplicitVRBigEndianPrivateGE, this code will need
807 // to be switched in order to read the pixel data. This must be
808 // done REGARDLESS of the processor endianess!
810 // Example: Assume we are on a little endian machine. When
811 // GDCM reads the header, the header will match the machine
812 // endianess and the swap code will be established as a no-op.
813 // When GDCM reaches the pixel data, it will need to switch the
814 // swap code to do big endian to little endian conversion.
816 // Now, assume we are on a big endian machine. When GDCM reads the
817 // header, the header will be recognized as a different endianess
818 // than the machine endianess, and a swap code will be established
819 // to convert from little endian to big endian. When GDCM readers
820 // the pixel data, the pixel data endianess will now match the
821 // machine endianess. But we currently have a swap code that
822 // converts from little endian to big endian. In this case, we
823 // need to switch the swap code to a no-op.
825 // Therefore, in either case, if the file is in
826 // 'ImplicitVR BigEndian PrivateGE Transfer Syntax', then GDCM needs to switch
827 // the byte swapping code when entering the pixel data.
829 if ( IsPrivateGETransferSyntax )
831 // PrivateGETransferSyntax only exists for 'true' Dicom images
832 // we assume there is no 'exotic' 32 bits endianess!
833 switch (localSwapCode)
836 localSwapCode = 4321;
839 localSwapCode = 1234;
844 if ( BitsAllocated == 16 )
846 uint16_t *im16 = (uint16_t*)Raw;
847 switch( localSwapCode )
854 for( i = 0; i < RawSize / 2; i++ )
856 im16[i]= (im16[i] >> 8) | (im16[i] << 8 );
860 gdcmWarningMacro("SwapCode value (16 bits) not allowed.");
863 else if ( BitsAllocated == 32 )
868 uint32_t *im32 = (uint32_t*)Raw;
869 switch ( localSwapCode )
874 for( i = 0; i < RawSize / 4; i++ )
876 low = im32[i] & 0x0000ffff; // 4321
877 high = im32[i] >> 16;
878 high = ( high >> 8 ) | ( high << 8 );
879 low = ( low >> 8 ) | ( low << 8 );
881 im32[i] = ( s32 << 16 ) | high;
885 for( i = 0; i < RawSize / 4; i++ )
887 low = im32[i] & 0x0000ffff; // 2143
888 high = im32[i] >> 16;
889 high = ( high >> 8 ) | ( high << 8 );
890 low = ( low >> 8 ) | ( low << 8 );
892 im32[i] = ( s32 << 16 ) | low;
896 for( i = 0; i < RawSize / 4; i++ )
898 low = im32[i] & 0x0000ffff; // 3412
899 high = im32[i] >> 16;
901 im32[i] = ( s32 << 16 ) | high;
905 gdcmWarningMacro("SwapCode value (32 bits) not allowed." );
911 * \brief Deal with endianness i.e. re-arange bytes inside the integer
913 void PixelReadConvert::ConvertReorderEndianity()
915 if ( BitsAllocated != 8 )
920 // Special kludge in order to deal with xmedcon broken images:
921 if ( BitsAllocated == 16
922 && BitsStored < BitsAllocated
925 int l = (int)( RawSize / ( BitsAllocated / 8 ) );
926 uint16_t *deb = (uint16_t *)Raw;
927 for(int i = 0; i<l; i++)
929 if ( *deb == 0xffff )
939 * \brief Deal with Grey levels i.e. re-arange them
940 * to have low values = dark, high values = bright
942 void PixelReadConvert::ConvertFixGreyLevels()
947 uint32_t i; // to please M$VC6
952 if ( BitsAllocated == 8 )
954 uint8_t *deb = (uint8_t *)Raw;
955 for (i=0; i<RawSize; i++)
963 if ( BitsAllocated == 16 )
966 for (j=0; j<BitsStored-1; j++)
968 mask = (mask << 1) +1; // will be fff when BitsStored=12
971 uint16_t *deb = (uint16_t *)Raw;
972 for (i=0; i<RawSize/2; i++)
982 if ( BitsAllocated == 8 )
984 uint8_t smask8 = 255;
985 uint8_t *deb = (uint8_t *)Raw;
986 for (i=0; i<RawSize; i++)
988 *deb = smask8 - *deb;
993 if ( BitsAllocated == 16 )
995 uint16_t smask16 = 65535;
996 uint16_t *deb = (uint16_t *)Raw;
997 for (i=0; i<RawSize/2; i++)
999 *deb = smask16 - *deb;
1008 * \brief Re-arrange the bits within the bytes.
1009 * @return Boolean always true
1011 bool PixelReadConvert::ConvertReArrangeBits() throw ( FormatError )
1014 if ( BitsStored != BitsAllocated )
1016 int l = (int)( RawSize / ( BitsAllocated / 8 ) );
1017 if ( BitsAllocated == 16 )
1019 // pmask : to mask the 'unused bits' (may contain overlays)
1020 uint16_t pmask = 0xffff;
1021 pmask = pmask >> ( BitsAllocated - BitsStored );
1023 uint16_t *deb = (uint16_t*)Raw;
1025 if ( !PixelSign ) // Pixels are unsigned
1027 for(int i = 0; i<l; i++)
1029 *deb = (*deb >> (BitsStored - HighBitPosition - 1)) & pmask;
1033 else // Pixels are signed
1035 // smask : to check the 'sign' when BitsStored != BitsAllocated
1036 uint16_t smask = 0x0001;
1037 smask = smask << ( 16 - (BitsAllocated - BitsStored + 1) );
1038 // nmask : to propagate sign bit on negative values
1039 int16_t nmask = (int16_t)0x8000;
1040 nmask = nmask >> ( BitsAllocated - BitsStored - 1 );
1042 for(int i = 0; i<l; i++)
1044 *deb = *deb >> (BitsStored - HighBitPosition - 1);
1047 *deb = *deb | nmask;
1051 *deb = *deb & pmask;
1057 else if ( BitsAllocated == 32 )
1059 // pmask : to mask the 'unused bits' (may contain overlays)
1060 uint32_t pmask = 0xffffffff;
1061 pmask = pmask >> ( BitsAllocated - BitsStored );
1063 uint32_t *deb = (uint32_t*)Raw;
1067 for(int i = 0; i<l; i++)
1069 *deb = (*deb >> (BitsStored - HighBitPosition - 1)) & pmask;
1075 // smask : to check the 'sign' when BitsStored != BitsAllocated
1076 uint32_t smask = 0x00000001;
1077 smask = smask >> ( 32 - (BitsAllocated - BitsStored +1 ));
1078 // nmask : to propagate sign bit on negative values
1079 int32_t nmask = 0x80000000;
1080 nmask = nmask >> ( BitsAllocated - BitsStored -1 );
1082 for(int i = 0; i<l; i++)
1084 *deb = *deb >> (BitsStored - HighBitPosition - 1);
1086 *deb = *deb | nmask;
1088 *deb = *deb & pmask;
1095 gdcmWarningMacro("Weird image (BitsAllocated !=8, 12, 16, 32)");
1096 throw FormatError( "Weird image !?" );
1103 * \brief Convert (Red plane, Green plane, Blue plane) to RGB pixels
1104 * \warning Works on all the frames at a time
1106 void PixelReadConvert::ConvertRGBPlanesToRGBPixels()
1108 gdcmWarningMacro("--> ConvertRGBPlanesToRGBPixels");
1110 uint8_t *localRaw = Raw;
1111 uint8_t *copyRaw = new uint8_t[ RawSize ];
1112 memmove( copyRaw, localRaw, RawSize );
1114 int l = XSize * YSize * ZSize;
1116 uint8_t *a = copyRaw;
1117 uint8_t *b = copyRaw + l;
1118 uint8_t *c = copyRaw + l + l;
1120 for (int j = 0; j < l; j++)
1122 *(localRaw++) = *(a++);
1123 *(localRaw++) = *(b++);
1124 *(localRaw++) = *(c++);
1130 * \brief Convert (cY plane, cB plane, cR plane) to RGB pixels
1131 * \warning Works on all the frames at a time
1133 void PixelReadConvert::ConvertYcBcRPlanesToRGBPixels()
1135 // Remarks for YBR newbees :
1136 // YBR_FULL works very much like RGB, i.e. three samples per pixel,
1137 // just the color space is YCbCr instead of RGB. This is particularly useful
1138 // for doppler ultrasound where most of the image is grayscale
1139 // (i.e. only populates the Y components) and Cb and Cr are mostly zero,
1140 // except for the few patches of color on the image.
1141 // On such images, RLE achieves a compression ratio that is much better
1142 // than the compression ratio on an equivalent RGB image.
1144 gdcmWarningMacro("--> ConvertYcBcRPlanesToRGBPixels");
1146 uint8_t *localRaw = Raw;
1147 uint8_t *copyRaw = new uint8_t[ RawSize ];
1148 memmove( copyRaw, localRaw, RawSize );
1150 // to see the tricks about YBR_FULL, YBR_FULL_422,
1151 // YBR_PARTIAL_422, YBR_ICT, YBR_RCT have a look at :
1152 // ftp://medical.nema.org/medical/dicom/final/sup61_ft.pdf
1153 // and be *very* affraid
1155 int l = XSize * YSize;
1156 int nbFrames = ZSize;
1158 uint8_t *a = copyRaw + 0;
1159 uint8_t *b = copyRaw + l;
1160 uint8_t *c = copyRaw + l+ l;
1163 /// We replaced easy to understand but time consuming floating point
1164 /// computations by the 'well known' integer computation counterpart
1166 /// http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf
1167 /// for code optimisation.
1169 for ( int i = 0; i < nbFrames; i++ )
1171 for ( int j = 0; j < l; j++ )
1173 R = 38142 *(*a-16) + 52298 *(*c -128);
1174 G = 38142 *(*a-16) - 26640 *(*c -128) - 12845 *(*b -128);
1175 B = 38142 *(*a-16) + 66093 *(*b -128);
1184 if (R > 255) R = 255;
1185 if (G > 255) G = 255;
1186 if (B > 255) B = 255;
1188 *(localRaw++) = (uint8_t)R;
1189 *(localRaw++) = (uint8_t)G;
1190 *(localRaw++) = (uint8_t)B;
1199 /// \brief Deals with the color decoding i.e. handle:
1200 /// - R, G, B planes (as opposed to RGB pixels)
1201 /// - YBR (various) encodings.
1202 /// - LUT[s] (or "PALETTE COLOR").
1204 void PixelReadConvert::ConvertHandleColor()
1206 //////////////////////////////////
1207 // Deal with the color decoding i.e. handle:
1208 // - R, G, B planes (as opposed to RGB pixels)
1209 // - YBR (various) encodings.
1210 // - LUT[s] (or "PALETTE COLOR").
1212 // The classification in the color decoding schema is based on the blending
1213 // of two Dicom tags values:
1214 // * "Photometric Interpretation" for which we have the cases:
1215 // - [Photo A] MONOCHROME[1|2] pictures,
1216 // - [Photo B] RGB or YBR_FULL_422 (which acts as RGB),
1217 // - [Photo C] YBR_* (with the above exception of YBR_FULL_422)
1218 // - [Photo D] "PALETTE COLOR" which indicates the presence of LUT[s].
1219 // * "Planar Configuration" for which we have the cases:
1220 // - [Planar 0] 0 then Pixels are already RGB
1221 // - [Planar 1] 1 then we have 3 planes : R, G, B,
1222 // - [Planar 2] 2 then we have 1 gray Plane and 3 LUTs
1224 // Now in theory, one could expect some coherence when blending the above
1225 // cases. For example we should not encounter files belonging at the
1226 // time to case [Planar 0] and case [Photo D].
1227 // Alas, this was only theory ! Because in practice some odd (read ill
1228 // formated Dicom) files (e.g. gdcmData/US-PAL-8-10x-echo.dcm) we encounter:
1229 // - "Planar Configuration" = 0,
1230 // - "Photometric Interpretation" = "PALETTE COLOR".
1231 // Hence gdcm will use the folowing "heuristic" in order to be tolerant
1232 // towards Dicom-non-conformant files:
1233 // << whatever the "Planar Configuration" value might be, a
1234 // "Photometric Interpretation" set to "PALETTE COLOR" forces
1235 // a LUT intervention >>
1237 // Now we are left with the following handling of the cases:
1238 // - [Planar 0] OR [Photo A] no color decoding (since respectively
1239 // Pixels are already RGB and monochrome pictures have no color :),
1240 // - [Planar 1] AND [Photo B] handled with ConvertRGBPlanesToRGBPixels()
1241 // - [Planar 1] AND [Photo C] handled with ConvertYcBcRPlanesToRGBPixels()
1242 // - [Planar 2] OR [Photo D] requires LUT intervention.
1244 gdcmDebugMacro("--> ConvertHandleColor "
1245 << "Planar Configuration " << PlanarConfiguration );
1249 // [Planar 2] OR [Photo D]: LUT intervention done outside
1250 gdcmDebugMacro("--> RawRGB : LUT intervention done outside");
1254 if ( PlanarConfiguration == 1 )
1258 // [Planar 1] AND [Photo C] (remember YBR_FULL_422 acts as RGB)
1259 gdcmWarningMacro("--> YBRFull");
1260 ConvertYcBcRPlanesToRGBPixels();
1264 // [Planar 1] AND [Photo C]
1265 gdcmWarningMacro("--> YBRFull");
1266 ConvertRGBPlanesToRGBPixels();
1271 // When planarConf is 0, and RLELossless (forbidden by Dicom norm)
1272 // pixels need to be RGB-fyied anyway
1276 gdcmWarningMacro("--> RLE Lossless");
1277 ConvertRGBPlanesToRGBPixels();
1280 // In *normal *case, when planarConf is 0, pixels are already in RGB
1283 /// Computes the Pixels Size
1284 void PixelReadConvert::ComputeRawAndRGBSizes()
1286 int bitsAllocated = BitsAllocated;
1287 // Number of "Bits Allocated" is fixed to 16 when it's 12, since
1288 // in this case we will expand the image to 16 bits (see
1289 // \ref ReadAndDecompress12BitsTo16Bits() )
1290 if ( BitsAllocated == 12 )
1295 RawSize = XSize * YSize * ZSize
1296 * ( bitsAllocated / 8 )
1300 RGBSize = 3 * RawSize; // works for 8 and 16 bits per Pixel
1308 /// Allocates room for RGB Pixels
1309 void PixelReadConvert::AllocateRGB()
1313 RGB = new uint8_t[RGBSize];
1316 /// Allocates room for RAW Pixels
1317 void PixelReadConvert::AllocateRaw()
1321 Raw = new uint8_t[RawSize];
1324 //-----------------------------------------------------------------------------
1327 * \brief Print self.
1328 * @param indent Indentation string to be prepended during printing.
1329 * @param os Stream to print to.
1331 void PixelReadConvert::Print( std::ostream &os, std::string const &indent )
1334 << "--- Pixel information -------------------------"
1337 << "Pixel Data: offset " << PixelOffset
1338 << " x(" << std::hex << PixelOffset << std::dec
1339 << ") length " << PixelDataLength
1340 << " x(" << std::hex << PixelDataLength << std::dec
1341 << ")" << std::endl;
1343 if ( IsRLELossless )
1347 RLEInfo->Print( os, indent );
1351 gdcmWarningMacro("Set as RLE file but NO RLEinfo present.");
1355 if ( IsJPEG2000 || IsJPEGLossless || IsJPEGLossy || IsJPEGLS )
1359 JPEGInfo->Print( os, indent );
1363 gdcmWarningMacro("Set as JPEG file but NO JPEGinfo present.");
1368 //-----------------------------------------------------------------------------
1369 } // end namespace gdcm
1371 // Note to developpers :
1372 // Here is a very detailled post from David Clunie, on the troubles caused
1373 // 'non standard' LUT and LUT description
1374 // We shall have to take it into accound in our code.
1379 Subject: Problem with VOI LUTs in Agfa and Fuji CR and GE DX images, was Re: VOI LUT issues
1380 Date: Sun, 06 Feb 2005 17:13:40 GMT
1381 From: David Clunie <dclunie@dclunie.com>
1382 Reply-To: dclunie@dclunie.com
1383 Newsgroups: comp.protocols.dicom
1384 References: <1107553502.040221.189550@o13g2000cwo.googlegroups.com>
1386 > THE LUT that comes with [my] image claims to be 16-bit, but none of the
1387 > values goes higher than 4095. That being said, though, none of my
1388 > original pixel values goes higher than that, either. I have read
1389 > elsewhere on this group that when that happens you are supposed to
1390 > adjust the LUT. Can someone be more specific? There was a thread from
1391 > 2002 where Marco and David were mentioning doing precisely that.
1398 You have encountered the well known "we know what the standard says but
1399 we are going to ignore it and do what we have been doing for almost
1400 a decade regardless" CR vendor bug. Agfa started this, but they are not
1401 the only vendor doing this now; GE and Fuji may have joined the club.
1403 Sadly, one needs to look at the LUT Data, figure out what the maximum
1404 value actually encoded is, and find the next highest power of 2 (e.g.
1405 212 in this case), to figure out what the range of the data is
1406 supposed to be. I have assumed that if the maximum value in the LUT
1407 data is less than a power of 2 minus 1 (e.g. 0xebc) then the intent
1408 of the vendor was not to use the maximum available grayscale range
1409 of the display (e.g. the maximum is 0xfff in this case). An alternative
1410 would be to scale to the actual maximum rather than a power of two.
1412 Very irritating, and in theory not totally reliable if one really
1413 intended the full 16 bits and only used, say 15, but that is extremely
1414 unlikely since everything would be too dark, and this heuristic
1417 There has never been anything in the standard that describes having
1418 to go through these convolutions. Since the only value in the
1419 standard that describes the bit depth of the LUT values is LUT
1420 Descriptor value 3 and that is (usually) always required to be
1421 either 8 or 16, it mystifies me how the creators' of these images
1422 imagine that the receiver is going to divine the range that is intended. Further, the standard is quite explicit that this 3rd
1423 value defines the range of LUT values, but as far as I am aware, all
1424 the vendors are ignoring the standard and indeed sending a third value
1427 This problem is not confined to CR, and is also seen with DX products.
1429 Typically I have seen:
1431 - Agfa CR, which usually (always ?) sends LUTs, values up to 0x0fff
1432 - Fuji CR, which occasionally send LUTs, values up to 0x03ff
1433 - GE DX, for presentation, which always have LUTs, up to 0x3fff
1435 Swissray, Siemens, Philips, Canon and Kodak never seem to send VOI LUTs
1436 at this point (which is a whole other problem). Note that the presence
1437 or absence of a VOI LUT as opposed to window values may be configurable
1438 on the modality in some cases, and I have just looked at what I happen
1439 to have received from a myriad of sites over whose configuration I have
1440 no control. This may be why the majority of Fuji images have no VOI LUTs,
1441 but a few do (or it may be the Siemens system that these Fuji images went
1442 through that perhaps added it). I do have some test Hologic DX images that
1443 are not from a clinical site that do actually get this right (a value
1444 of 12 for the third value and a max of 0xfff).
1446 Since almost every vendor that I have encountered that encodes LUTs
1447 makes this mistake, perhaps it is time to amend the standard to warn
1448 implementor's of receivers and/or sanction this bad behavior. We have
1449 talked about this in the past in WG 6 but so far everyone has been
1450 reluctant to write into the standard such a comment. Maybe it is time
1451 to try again, since if one is not aware of this problem, one cannot
1452 effectively implement display using VOI LUTs, and there is a vast
1453 installed base to contend with.
1455 I did not check presentation states, in which VOI LUTs could also be
1456 encountered, for the prevalence of this mistake, nor did I look at the
1457 encoding of Modality LUT's, which are unusual. Nor did I check digital
1458 mammography images. I would be interested to hear from anyone who has.
1462 PS. The following older thread in this newsgroup discusses this:
1464 "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"
1466 PPS. From a historical perspective, the following may be of interest.
1468 In the original standard in 1993, all that was said about this was a
1469 reference to the corresponding such where Modality LUTs are described
1472 "The third value specifies the number of bits for each entry in the
1473 LUT Data. It shall take the value 8 or 16. The LUT Data shall be stored
1474 in a format equivalent to 8 or 16 bits allocated and high bit equal
1477 Since the high bit hint was not apparently explicit enough, a very
1478 early CP, CP 15 (submitted by Agfa as it happens), replaced this with:
1480 "The third value conveys the range of LUT entry values. It shall take
1481 the value 8 or 16, corresponding with the LUT entry value range of
1484 Note: The third value is not required for describing the
1485 LUT data and is only included for informational usage
1486 and for maintaining compatibility with ACRNEMA 2.0.
1488 The LUT Data contains the LUT entry values."
1490 That is how it read in the 1996, 1998 and 1999 editions.
1492 By the 2000 edition, Supplement 33 that introduced presentation states
1493 extensively reworked this entire section and tried to explain this in
1496 "The output range is from 0 to 2^n-1 where n is the third value of LUT
1497 Descriptor. This range is always unsigned."
1499 and also added a note to spell out what the output range meant in the
1502 "9. The output of the Window Center/Width or VOI LUT transformation
1503 is either implicitly scaled to the full range of the display device
1504 if there is no succeeding transformation defined, or implicitly scaled
1505 to the full input range of the succeeding transformation step (such as
1506 the Presentation LUT), if present. See C.11.6.1."
1508 It still reads this way in the 2004 edition.
1510 Note that LUTs in other applications than the general VOI LUT allow for
1511 values other than 8 or 16 in the third value of LUT descriptor to permit
1512 ranges other than 0 to 255 or 65535.
1514 In addition, the DX Image Module specializes the VOI LUT
1515 attributes as follows, in PS 3.3 section C.8.11.3.1.5 (added in Sup 32):
1517 "The third value specifies the number of bits for each entry in the LUT
1518 Data (analogous to ìbits storedî). It shall be between 10-16. The LUT
1519 Data shall be stored in a format equivalent to 16 ìbits allocatedî and
1520 ìhigh bitî equal to ìbits storedî - 1. The third value conveys the range
1521 of LUT entry values. These unsigned LUT entry values shall range between
1522 0 and 2^n-1, where n is the third value of the LUT Descriptor."
1524 So in the case of the GE DX for presentation images, the third value of
1525 LUT descriptor is allowed to be and probably should be 14 rather than 16.