1 /*=========================================================================
4 Module: $RCSfile: gdcmPixelReadConvert.cxx,v $
6 Date: $Date: 2005/10/25 18:14:49 $
7 Version: $Revision: 1.88 $
9 Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10 l'Image). All rights reserved. See Doc/License.txt or
11 http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
13 This software is distributed WITHOUT ANY WARRANTY; without even
14 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 PURPOSE. See the above copyright notices for more information.
17 =========================================================================*/
19 #include "gdcmPixelReadConvert.h"
20 #include "gdcmDebug.h"
22 #include "gdcmGlobal.h"
24 #include "gdcmDocEntry.h"
25 #include "gdcmRLEFramesInfo.h"
26 #include "gdcmJPEGFragmentsInfo.h"
29 #include <stdio.h> //for sscanf
34 //bool ReadMPEGFile (std::ifstream *fp, void *image_buffer, size_t lenght);
35 bool gdcm_read_JPEG2000_file (void* raw,
36 char *inputdata, size_t inputlength);
37 //-----------------------------------------------------------------------------
38 #define str2num(str, typeNum) *((typeNum *)(str))
40 //-----------------------------------------------------------------------------
41 // Constructor / Destructor
43 PixelReadConvert::PixelReadConvert()
59 /// Canonical Destructor
60 PixelReadConvert::~PixelReadConvert()
65 //-----------------------------------------------------------------------------
68 * \brief Predicate to know whether the image[s] (once Raw) is RGB.
69 * \note See comments of \ref ConvertHandleColor
71 bool PixelReadConvert::IsRawRGB()
74 || PlanarConfiguration == 2
82 * \brief Gets various usefull informations from the file header
83 * @param file gdcm::File pointer
85 void PixelReadConvert::GrabInformationsFromFile( File *file )
87 // Number of Bits Allocated for storing a Pixel is defaulted to 16
88 // when absent from the file.
89 BitsAllocated = file->GetBitsAllocated();
90 if ( BitsAllocated == 0 )
95 // Number of "Bits Stored", defaulted to number of "Bits Allocated"
96 // when absent from the file.
97 BitsStored = file->GetBitsStored();
98 if ( BitsStored == 0 )
100 BitsStored = BitsAllocated;
103 // High Bit Position, defaulted to "Bits Allocated" - 1
104 HighBitPosition = file->GetHighBitPosition();
105 if ( HighBitPosition == 0 )
107 HighBitPosition = BitsAllocated - 1;
110 XSize = file->GetXSize();
111 YSize = file->GetYSize();
112 ZSize = file->GetZSize();
113 SamplesPerPixel = file->GetSamplesPerPixel();
114 //PixelSize = file->GetPixelSize(); Useless
115 PixelSign = file->IsSignedPixelData();
116 SwapCode = file->GetSwapCode();
117 std::string ts = file->GetTransferSyntax();
118 if ( ts == GDCM_UNKNOWN )
120 gdcmErrorMacro( "Could someone tell me how in the world could this happen !" );
121 abort(); // DO NOT REMOVE. WE SHOULD NEVER READ SUCH IMAGE EVER (only gdcm can write such broekn dicom file)
124 ( ! file->IsDicomV3() )
125 || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRLittleEndian
126 || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRBigEndianPrivateGE
127 || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRLittleEndian
128 || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRBigEndian
129 || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::DeflatedExplicitVRLittleEndian;
131 IsPrivateGETransferSyntax =
132 ( Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRBigEndianPrivateGE );
134 IsMPEG = Global::GetTS()->IsMPEG(ts);
135 IsJPEG2000 = Global::GetTS()->IsJPEG2000(ts);
136 IsJPEGLS = Global::GetTS()->IsJPEGLS(ts);
137 IsJPEGLossy = Global::GetTS()->IsJPEGLossy(ts);
138 IsJPEGLossless = Global::GetTS()->IsJPEGLossless(ts);
139 IsRLELossless = Global::GetTS()->IsRLELossless(ts);
141 PixelOffset = file->GetPixelOffset();
142 PixelDataLength = file->GetPixelAreaLength();
143 RLEInfo = file->GetRLEInfo();
144 JPEGInfo = file->GetJPEGInfo();
146 IsMonochrome = file->IsMonochrome();
147 IsMonochrome1 = file->IsMonochrome1();
148 IsPaletteColor = file->IsPaletteColor();
149 IsYBRFull = file->IsYBRFull();
151 PlanarConfiguration = file->GetPlanarConfiguration();
153 /////////////////////////////////////////////////////////////////
155 HasLUT = file->HasLUT();
158 // Just in case some access to a File element requires disk access.
159 LutRedDescriptor = file->GetEntryString( 0x0028, 0x1101 );
160 LutGreenDescriptor = file->GetEntryString( 0x0028, 0x1102 );
161 LutBlueDescriptor = file->GetEntryString( 0x0028, 0x1103 );
163 // The following comment is probabely meaningless, since LUT are *always*
164 // loaded at parsing time, whatever their length is.
166 // Depending on the value of Document::MAX_SIZE_LOAD_ELEMENT_VALUE
167 // [ refer to invocation of Document::SetMaxSizeLoadEntry() in
168 // Document::Document() ], the loading of the value (content) of a
169 // [Bin|Val]Entry occurence migth have been hindered (read simply NOT
170 // loaded). Hence, we first try to obtain the LUTs data from the file
171 // and when this fails we read the LUTs data directly from disk.
172 // \TODO Reading a [Bin|Val]Entry directly from disk is a kludge.
173 // We should NOT bypass the [Bin|Val]Entry class. Instead
174 // an access to an UNLOADED content of a [Bin|Val]Entry occurence
175 // (e.g. DataEntry::GetBinArea()) should force disk access from
176 // within the [Bin|Val]Entry class itself. The only problem
177 // is that the [Bin|Val]Entry is unaware of the FILE* is was
178 // parsed from. Fix that. FIXME.
181 file->LoadEntryBinArea(0x0028, 0x1201);
182 LutRedData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1201 );
185 gdcmWarningMacro("Unable to read Red Palette Color Lookup Table data");
189 file->LoadEntryBinArea(0x0028, 0x1202);
190 LutGreenData = (uint8_t*)file->GetEntryBinArea(0x0028, 0x1202 );
193 gdcmWarningMacro("Unable to read Green Palette Color Lookup Table data");
197 file->LoadEntryBinArea(0x0028, 0x1203);
198 LutBlueData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1203 );
201 gdcmWarningMacro("Unable to read Blue Palette Color Lookup Table data");
206 ComputeRawAndRGBSizes();
209 /// \brief Reads from disk and decompresses Pixels
210 bool PixelReadConvert::ReadAndDecompressPixelData( std::ifstream *fp )
212 // ComputeRawAndRGBSizes is already made by
213 // ::GrabInformationsFromfile. So, the structure sizes are
217 //////////////////////////////////////////////////
218 //// First stage: get our hands on the Pixel Data.
221 gdcmWarningMacro( "Unavailable file pointer." );
225 fp->seekg( PixelOffset, std::ios::beg );
226 if ( fp->fail() || fp->eof() )
228 gdcmWarningMacro( "Unable to find PixelOffset in file." );
234 //////////////////////////////////////////////////
235 //// Second stage: read from disk and decompress.
236 if ( BitsAllocated == 12 )
238 ReadAndDecompress12BitsTo16Bits( fp);
242 // This problem can be found when some obvious informations are found
243 // after the field containing the image data. In this case, these
244 // bad data are added to the size of the image (in the PixelDataLength
245 // variable). But RawSize is the right size of the image !
246 if ( PixelDataLength != RawSize )
248 gdcmWarningMacro( "Mismatch between PixelReadConvert : "
249 << PixelDataLength << " and RawSize : " << RawSize );
251 if ( PixelDataLength > RawSize )
253 fp->read( (char*)Raw, RawSize);
257 fp->read( (char*)Raw, PixelDataLength);
260 if ( fp->fail() || fp->eof())
262 gdcmWarningMacro( "Reading of Raw pixel data failed." );
266 else if ( IsRLELossless )
268 if ( ! RLEInfo->DecompressRLEFile
269 ( fp, Raw, XSize, YSize, ZSize, BitsAllocated ) )
271 gdcmWarningMacro( "RLE decompressor failed." );
277 //gdcmWarningMacro( "Sorry, MPEG not yet taken into account" );
279 // fp has already been seek to start of mpeg
280 //ReadMPEGFile(fp, Raw, PixelDataLength);
285 // Default case concerns JPEG family
286 if ( ! ReadAndDecompressJPEGFile( fp ) )
288 gdcmWarningMacro( "JPEG decompressor failed." );
293 ////////////////////////////////////////////
294 //// Third stage: twigle the bytes and bits.
295 ConvertReorderEndianity();
296 ConvertReArrangeBits();
297 ConvertFixGreyLevels();
298 if (UserFunction) // user is allowed to Mirror, TopDown, Rotate,...the image
299 UserFunction( Raw, FileInternal);
300 ConvertHandleColor();
305 /// Deletes Pixels Area
306 void PixelReadConvert::Squeeze()
322 * \brief Build the RGB image from the Raw image and the LUTs.
324 bool PixelReadConvert::BuildRGBImage()
328 // The job is already done.
334 // The job can't be done
341 // The job can't be done
345 gdcmWarningMacro( "--> BuildRGBImage" );
351 if ( BitsAllocated <= 8 )
353 uint8_t *localRGB = RGB;
354 for (size_t i = 0; i < RawSize; ++i )
357 *localRGB++ = LutRGBA[j];
358 *localRGB++ = LutRGBA[j+1];
359 *localRGB++ = LutRGBA[j+2];
363 else // deal with 16 bits pixels and 16 bits Palette color
365 uint16_t *localRGB = (uint16_t *)RGB;
366 for (size_t i = 0; i < RawSize/2; ++i )
368 j = ((uint16_t *)Raw)[i] * 4;
369 *localRGB++ = ((uint16_t *)LutRGBA)[j];
370 *localRGB++ = ((uint16_t *)LutRGBA)[j+1];
371 *localRGB++ = ((uint16_t *)LutRGBA)[j+2];
378 //-----------------------------------------------------------------------------
381 //-----------------------------------------------------------------------------
384 * \brief Read from file a 12 bits per pixel image and decompress it
385 * into a 16 bits per pixel image.
387 void PixelReadConvert::ReadAndDecompress12BitsTo16Bits( std::ifstream *fp )
388 throw ( FormatError )
390 int nbPixels = XSize * YSize;
391 uint16_t *localDecompres = (uint16_t*)Raw;
393 for( int p = 0; p < nbPixels; p += 2 )
397 fp->read( (char*)&b0, 1);
398 if ( fp->fail() || fp->eof() )
400 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
401 "Unfound first block" );
404 fp->read( (char*)&b1, 1 );
405 if ( fp->fail() || fp->eof())
407 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
408 "Unfound second block" );
411 fp->read( (char*)&b2, 1 );
412 if ( fp->fail() || fp->eof())
414 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
415 "Unfound second block" );
418 // Two steps are necessary to please VC++
420 // 2 pixels 12bit = [0xABCDEF]
421 // 2 pixels 16bit = [0x0ABD] + [0x0FCE]
423 *localDecompres++ = ((b0 >> 4) << 8) + ((b0 & 0x0f) << 4) + (b1 & 0x0f);
425 *localDecompres++ = ((b2 & 0x0f) << 8) + ((b1 >> 4) << 4) + (b2 >> 4);
427 /// \todo JPR Troubles expected on Big-Endian processors ?
432 * \brief Reads from disk the Pixel Data of JPEG Dicom encapsulated
433 * file and decompress it.
434 * @param fp File Pointer
437 bool PixelReadConvert::ReadAndDecompressJPEGFile( std::ifstream *fp )
441 // make sure this is the right JPEG compression
442 assert( !IsJPEGLossless || !IsJPEGLossy || !IsJPEGLS );
443 // FIXME this is really ugly but it seems I have to load the complete
444 // jpeg2000 stream to use jasper:
445 // I don't think we'll ever be able to deal with multiple fragments properly
447 unsigned long inputlength = 0;
448 JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment();
451 inputlength += jpegfrag->GetLength();
452 jpegfrag = JPEGInfo->GetNextFragment();
454 gdcmAssertMacro( inputlength != 0);
455 uint8_t *inputdata = new uint8_t[inputlength];
456 char *pinputdata = (char*)inputdata;
457 jpegfrag = JPEGInfo->GetFirstFragment();
460 fp->seekg( jpegfrag->GetOffset(), std::ios::beg);
461 fp->read(pinputdata, jpegfrag->GetLength());
462 pinputdata += jpegfrag->GetLength();
463 jpegfrag = JPEGInfo->GetNextFragment();
465 // Warning the inputdata buffer is delete in the function
466 if ( ! gdcm_read_JPEG2000_file( Raw,
467 (char*)inputdata, inputlength ) )
471 // wow what happen, must be an error
476 // make sure this is the right JPEG compression
477 assert( !IsJPEGLossless || !IsJPEGLossy || !IsJPEG2000 );
478 // WARNING : JPEG-LS is NOT the 'classical' Jpeg Lossless :
479 // [JPEG-LS is the basis for new lossless/near-lossless compression
480 // standard for continuous-tone images intended for JPEG2000. The standard
481 // is based on the LOCO-I algorithm (LOw COmplexity LOssless COmpression
482 // for Images) developed at Hewlett-Packard Laboratories]
484 // see http://datacompression.info/JPEGLS.shtml
487 std::cerr << "count:" << JPEGInfo->GetFragmentCount() << std::endl;
488 unsigned long inputlength = 0;
489 JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment();
492 inputlength += jpegfrag->GetLength();
493 jpegfrag = JPEGInfo->GetNextFragment();
495 gdcmAssertMacro( inputlength != 0);
496 uint8_t *inputdata = new uint8_t[inputlength];
497 char *pinputdata = (char*)inputdata;
498 jpegfrag = JPEGInfo->GetFirstFragment();
501 fp->seekg( jpegfrag->GetOffset(), std::ios::beg);
502 fp->read(pinputdata, jpegfrag->GetLength());
503 pinputdata += jpegfrag->GetLength();
504 jpegfrag = JPEGInfo->GetNextFragment();
507 //fp->read((char*)Raw, PixelDataLength);
509 std::ofstream out("/tmp/jpegls.jpg");
510 out.write((char*)inputdata, inputlength);
515 gdcmWarningMacro( "Sorry, JPEG-LS not yet taken into account" );
516 fp->seekg( JPEGInfo->GetFirstFragment()->GetOffset(), std::ios::beg);
517 // if ( ! gdcm_read_JPEGLS_file( fp,Raw ) )
522 // make sure this is the right JPEG compression
523 assert( !IsJPEGLS || !IsJPEG2000 );
524 // Precompute the offset localRaw will be shifted with
525 int length = XSize * YSize * SamplesPerPixel;
526 int numberBytes = BitsAllocated / 8;
528 JPEGInfo->DecompressFromFile(fp, Raw, BitsStored, numberBytes, length );
534 * \brief Build Red/Green/Blue/Alpha LUT from File when :
535 * - (0028,0004) : Photometric Interpretation == [PALETTE COLOR ]
537 * - (0028,1101),(0028,1102),(0028,1102)
538 * xxx Palette Color Lookup Table Descriptor are found
540 * - (0028,1201),(0028,1202),(0028,1202)
541 * xxx Palette Color Lookup Table Data - are found
542 * \warning does NOT deal with :
543 * - 0028 1100 Gray Lookup Table Descriptor (Retired)
544 * - 0028 1221 Segmented Red Palette Color Lookup Table Data
545 * - 0028 1222 Segmented Green Palette Color Lookup Table Data
546 * - 0028 1223 Segmented Blue Palette Color Lookup Table Data
547 * no known Dicom reader deals with them :-(
548 * @return a RGBA Lookup Table
550 void PixelReadConvert::BuildLUTRGBA()
553 // Note to code reviewers :
554 // The problem is *much more* complicated, since a lot of manufacturers
555 // Don't follow the norm :
556 // have a look at David Clunie's remark at the end of this .cxx file.
563 // http://www.barre.nom.fr/medical/dicom2/limitations.html#Color%20Lookup%20Tables
565 if ( ! IsPaletteColor )
570 if ( LutRedDescriptor == GDCM_UNFOUND
571 || LutGreenDescriptor == GDCM_UNFOUND
572 || LutBlueDescriptor == GDCM_UNFOUND )
574 gdcmWarningMacro( "(At least) a LUT Descriptor is missing" );
578 ////////////////////////////////////////////
579 // Extract the info from the LUT descriptors
580 int lengthR; // Red LUT length in Bytes
581 int debR; // Subscript of the first Lut Value
582 int nbitsR; // Lut item size (in Bits)
583 int nbRead; // nb of items in LUT descriptor (must be = 3)
585 nbRead = sscanf( LutRedDescriptor.c_str(),
587 &lengthR, &debR, &nbitsR );
590 gdcmWarningMacro( "Wrong Red LUT descriptor" );
592 int lengthG; // Green LUT length in Bytes
593 int debG; // Subscript of the first Lut Value
594 int nbitsG; // Lut item size (in Bits)
596 nbRead = sscanf( LutGreenDescriptor.c_str(),
598 &lengthG, &debG, &nbitsG );
601 gdcmWarningMacro( "Wrong Green LUT descriptor" );
604 int lengthB; // Blue LUT length in Bytes
605 int debB; // Subscript of the first Lut Value
606 int nbitsB; // Lut item size (in Bits)
607 nbRead = sscanf( LutRedDescriptor.c_str(),
609 &lengthB, &debB, &nbitsB );
612 gdcmWarningMacro( "Wrong Blue LUT descriptor" );
615 gdcmWarningMacro(" lengthR " << lengthR << " debR "
616 << debR << " nbitsR " << nbitsR);
617 gdcmWarningMacro(" lengthG " << lengthG << " debG "
618 << debG << " nbitsG " << nbitsG);
619 gdcmWarningMacro(" lengthB " << lengthB << " debB "
620 << debB << " nbitsB " << nbitsB);
622 if ( !lengthR ) // if = 2^16, this shall be 0 see : CP-143
624 if ( !lengthG ) // if = 2^16, this shall be 0
626 if ( !lengthB ) // if = 2^16, this shall be 0
629 ////////////////////////////////////////////////////////
631 if ( ( ! LutRedData ) || ( ! LutGreenData ) || ( ! LutBlueData ) )
633 gdcmWarningMacro( "(At least) a LUT is missing" );
637 // -------------------------------------------------------------
639 if ( BitsAllocated <= 8 )
641 // forge the 4 * 8 Bits Red/Green/Blue/Alpha LUT
642 LutRGBA = new uint8_t[ 1024 ]; // 256 * 4 (R, G, B, Alpha)
647 memset( LutRGBA, 0, 1024 );
650 if ( ( nbitsR == 16 ) && ( BitsAllocated == 8 ) )
652 // when LUT item size is different than pixel size
653 mult = 2; // high byte must be = low byte
657 // See PS 3.3-2003 C.11.1.1.2 p 619
661 // if we get a black image, let's just remove the '+1'
662 // from 'i*mult+1' and check again
663 // if it works, we shall have to check the 3 Palettes
664 // to see which byte is ==0 (first one, or second one)
666 // We give up the checking to avoid some (useless ?) overhead
667 // (optimistic asumption)
671 //take "Subscript of the first Lut Value" (debR,debG,debB) into account!
673 //FIXME : +1 : to get 'low value' byte
674 // Trouble expected on Big Endian Processors ?
675 // 16 BIts Per Pixel Palette Color to be swapped?
677 a = LutRGBA + 0 + debR;
678 for( i=0; i < lengthR; ++i )
680 *a = LutRedData[i*mult+1];
684 a = LutRGBA + 1 + debG;
685 for( i=0; i < lengthG; ++i)
687 *a = LutGreenData[i*mult+1];
691 a = LutRGBA + 2 + debB;
692 for(i=0; i < lengthB; ++i)
694 *a = LutBlueData[i*mult+1];
699 for(i=0; i < 256; ++i)
701 *a = 1; // Alpha component
707 // Probabely the same stuff is to be done for 16 Bits Pixels
708 // with 65536 entries LUT ?!?
709 // Still looking for accurate info on the web :-(
711 gdcmWarningMacro( "Sorry Palette Color Lookup Tables not yet dealt with"
712 << " for 16 Bits Per Pixel images" );
714 // forge the 4 * 16 Bits Red/Green/Blue/Alpha LUT
716 LutRGBA = (uint8_t *)new uint16_t[ 65536*4 ]; // 2^16 * 4 (R, G, B, Alpha)
719 memset( LutRGBA, 0, 65536*4*2 ); // 16 bits = 2 bytes ;-)
721 LutItemNumber = 65536;
727 //take "Subscript of the first Lut Value" (debR,debG,debB) into account!
729 a16 = (uint16_t*)LutRGBA + 0 + debR;
730 for( i=0; i < lengthR; ++i )
732 *a16 = ((uint16_t*)LutRedData)[i];
736 a16 = (uint16_t*)LutRGBA + 1 + debG;
737 for( i=0; i < lengthG; ++i)
739 *a16 = ((uint16_t*)LutGreenData)[i];
743 a16 = (uint16_t*)LutRGBA + 2 + debB;
744 for(i=0; i < lengthB; ++i)
746 *a16 = ((uint16_t*)LutBlueData)[i];
750 a16 = (uint16_t*)LutRGBA + 3 ;
751 for(i=0; i < 65536; ++i)
753 *a16 = 1; // Alpha component
756 /* Just to 'see' the LUT, at debug time
757 // Don't remove this commented out code.
759 a16=(uint16_t*)LutRGBA;
760 for (int j=0;j<65536;j++)
762 std::cout << *a16 << " " << *(a16+1) << " "
763 << *(a16+2) << " " << *(a16+3) << std::endl;
771 * \brief Swap the bytes, according to \ref SwapCode.
773 void PixelReadConvert::ConvertSwapZone()
776 uint16_t localSwapCode = SwapCode;
778 // If this file is 'ImplicitVR BigEndian PrivateGE Transfer Syntax',
779 // then the header is in little endian format and the pixel data is in
780 // big endian format. When reading the header, GDCM has already established
781 // a byte swapping code suitable for this machine to read the
782 // header. In TS::ImplicitVRBigEndianPrivateGE, this code will need
783 // to be switched in order to read the pixel data. This must be
784 // done REGARDLESS of the processor endianess!
786 // Example: Assume we are on a little endian machine. When
787 // GDCM reads the header, the header will match the machine
788 // endianess and the swap code will be established as a no-op.
789 // When GDCM reaches the pixel data, it will need to switch the
790 // swap code to do big endian to little endian conversion.
792 // Now, assume we are on a big endian machine. When GDCM reads the
793 // header, the header will be recognized as a different endianess
794 // than the machine endianess, and a swap code will be established
795 // to convert from little endian to big endian. When GDCM readers
796 // the pixel data, the pixel data endianess will now match the
797 // machine endianess. But we currently have a swap code that
798 // converts from little endian to big endian. In this case, we
799 // need to switch the swap code to a no-op.
801 // Therefore, in either case, if the file is in
802 // 'ImplicitVR BigEndian PrivateGE Transfer Syntax', then GDCM needs to switch
803 // the byte swapping code when entering the pixel data.
805 /* //Let me check something.
806 //I wait for the Dashboard !
807 if ( IsPrivateGETransferSyntax )
809 // PrivateGETransferSyntax only exists for 'true' Dicom images
810 // we assume there is no 'exotic' 32 bits endianess!
811 switch (localSwapCode)
814 localSwapCode = 4321;
817 localSwapCode = 1234;
822 if ( BitsAllocated == 16 )
824 uint16_t *im16 = (uint16_t*)Raw;
825 switch( localSwapCode )
832 for( i = 0; i < RawSize / 2; i++ )
834 im16[i]= (im16[i] >> 8) | (im16[i] << 8 );
838 gdcmWarningMacro("SwapCode value (16 bits) not allowed.");
841 else if ( BitsAllocated == 32 )
846 uint32_t *im32 = (uint32_t*)Raw;
847 switch ( localSwapCode )
852 for( i = 0; i < RawSize / 4; i++ )
854 low = im32[i] & 0x0000ffff; // 4321
855 high = im32[i] >> 16;
856 high = ( high >> 8 ) | ( high << 8 );
857 low = ( low >> 8 ) | ( low << 8 );
859 im32[i] = ( s32 << 16 ) | high;
863 for( i = 0; i < RawSize / 4; i++ )
865 low = im32[i] & 0x0000ffff; // 2143
866 high = im32[i] >> 16;
867 high = ( high >> 8 ) | ( high << 8 );
868 low = ( low >> 8 ) | ( low << 8 );
870 im32[i] = ( s32 << 16 ) | low;
874 for( i = 0; i < RawSize / 4; i++ )
876 low = im32[i] & 0x0000ffff; // 3412
877 high = im32[i] >> 16;
879 im32[i] = ( s32 << 16 ) | high;
883 gdcmWarningMacro("SwapCode value (32 bits) not allowed." );
889 * \brief Deal with endianness i.e. re-arange bytes inside the integer
891 void PixelReadConvert::ConvertReorderEndianity()
893 if ( BitsAllocated != 8 )
898 // Special kludge in order to deal with xmedcon broken images:
899 if ( BitsAllocated == 16
900 && BitsStored < BitsAllocated
903 int l = (int)( RawSize / ( BitsAllocated / 8 ) );
904 uint16_t *deb = (uint16_t *)Raw;
905 for(int i = 0; i<l; i++)
907 if ( *deb == 0xffff )
917 * \brief Deal with Grey levels i.e. re-arange them
918 * to have low values = dark, high values = bright
920 void PixelReadConvert::ConvertFixGreyLevels()
925 uint32_t i; // to please M$VC6
930 if ( BitsAllocated == 8 )
932 uint8_t *deb = (uint8_t *)Raw;
933 for (i=0; i<RawSize; i++)
941 if ( BitsAllocated == 16 )
944 for (j=0; j<BitsStored-1; j++)
946 mask = (mask << 1) +1; // will be fff when BitsStored=12
949 uint16_t *deb = (uint16_t *)Raw;
950 for (i=0; i<RawSize/2; i++)
960 if ( BitsAllocated == 8 )
962 uint8_t smask8 = 255;
963 uint8_t *deb = (uint8_t *)Raw;
964 for (i=0; i<RawSize; i++)
966 *deb = smask8 - *deb;
971 if ( BitsAllocated == 16 )
973 uint16_t smask16 = 65535;
974 uint16_t *deb = (uint16_t *)Raw;
975 for (i=0; i<RawSize/2; i++)
977 *deb = smask16 - *deb;
986 * \brief Re-arrange the bits within the bytes.
987 * @return Boolean always true
989 bool PixelReadConvert::ConvertReArrangeBits() throw ( FormatError )
992 if ( BitsStored != BitsAllocated )
994 int l = (int)( RawSize / ( BitsAllocated / 8 ) );
995 if ( BitsAllocated == 16 )
997 // pmask : to mask the 'unused bits' (may contain overlays)
998 uint16_t pmask = 0xffff;
999 pmask = pmask >> ( BitsAllocated - BitsStored );
1001 uint16_t *deb = (uint16_t*)Raw;
1003 if ( !PixelSign ) // Pixels are unsigned
1005 for(int i = 0; i<l; i++)
1007 *deb = (*deb >> (BitsStored - HighBitPosition - 1)) & pmask;
1011 else // Pixels are signed
1013 // smask : to check the 'sign' when BitsStored != BitsAllocated
1014 uint16_t smask = 0x0001;
1015 smask = smask << ( 16 - (BitsAllocated - BitsStored + 1) );
1016 // nmask : to propagate sign bit on negative values
1017 int16_t nmask = (int16_t)0x8000;
1018 nmask = nmask >> ( BitsAllocated - BitsStored - 1 );
1020 for(int i = 0; i<l; i++)
1022 *deb = *deb >> (BitsStored - HighBitPosition - 1);
1025 *deb = *deb | nmask;
1029 *deb = *deb & pmask;
1035 else if ( BitsAllocated == 32 )
1037 // pmask : to mask the 'unused bits' (may contain overlays)
1038 uint32_t pmask = 0xffffffff;
1039 pmask = pmask >> ( BitsAllocated - BitsStored );
1041 uint32_t *deb = (uint32_t*)Raw;
1045 for(int i = 0; i<l; i++)
1047 *deb = (*deb >> (BitsStored - HighBitPosition - 1)) & pmask;
1053 // smask : to check the 'sign' when BitsStored != BitsAllocated
1054 uint32_t smask = 0x00000001;
1055 smask = smask >> ( 32 - (BitsAllocated - BitsStored +1 ));
1056 // nmask : to propagate sign bit on negative values
1057 int32_t nmask = 0x80000000;
1058 nmask = nmask >> ( BitsAllocated - BitsStored -1 );
1060 for(int i = 0; i<l; i++)
1062 *deb = *deb >> (BitsStored - HighBitPosition - 1);
1064 *deb = *deb | nmask;
1066 *deb = *deb & pmask;
1073 gdcmWarningMacro("Weird image (BitsAllocated !=8, 12, 16, 32)");
1074 throw FormatError( "Weird image !?" );
1081 * \brief Convert (Red plane, Green plane, Blue plane) to RGB pixels
1082 * \warning Works on all the frames at a time
1084 void PixelReadConvert::ConvertRGBPlanesToRGBPixels()
1086 gdcmWarningMacro("--> ConvertRGBPlanesToRGBPixels");
1088 uint8_t *localRaw = Raw;
1089 uint8_t *copyRaw = new uint8_t[ RawSize ];
1090 memmove( copyRaw, localRaw, RawSize );
1092 int l = XSize * YSize * ZSize;
1094 uint8_t *a = copyRaw;
1095 uint8_t *b = copyRaw + l;
1096 uint8_t *c = copyRaw + l + l;
1098 for (int j = 0; j < l; j++)
1100 *(localRaw++) = *(a++);
1101 *(localRaw++) = *(b++);
1102 *(localRaw++) = *(c++);
1108 * \brief Convert (cY plane, cB plane, cR plane) to RGB pixels
1109 * \warning Works on all the frames at a time
1111 void PixelReadConvert::ConvertYcBcRPlanesToRGBPixels()
1113 // Remarks for YBR newbees :
1114 // YBR_FULL works very much like RGB, i.e. three samples per pixel,
1115 // just the color space is YCbCr instead of RGB. This is particularly useful
1116 // for doppler ultrasound where most of the image is grayscale
1117 // (i.e. only populates the Y components) and Cb and Cr are mostly zero,
1118 // except for the few patches of color on the image.
1119 // On such images, RLE achieves a compression ratio that is much better
1120 // than the compression ratio on an equivalent RGB image.
1122 gdcmWarningMacro("--> ConvertYcBcRPlanesToRGBPixels");
1124 uint8_t *localRaw = Raw;
1125 uint8_t *copyRaw = new uint8_t[ RawSize ];
1126 memmove( copyRaw, localRaw, RawSize );
1128 // to see the tricks about YBR_FULL, YBR_FULL_422,
1129 // YBR_PARTIAL_422, YBR_ICT, YBR_RCT have a look at :
1130 // ftp://medical.nema.org/medical/dicom/final/sup61_ft.pdf
1131 // and be *very* affraid
1133 int l = XSize * YSize;
1134 int nbFrames = ZSize;
1136 uint8_t *a = copyRaw + 0;
1137 uint8_t *b = copyRaw + l;
1138 uint8_t *c = copyRaw + l+ l;
1141 /// We replaced easy to understand but time consuming floating point
1142 /// computations by the 'well known' integer computation counterpart
1144 /// http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf
1145 /// for code optimisation.
1147 for ( int i = 0; i < nbFrames; i++ )
1149 for ( int j = 0; j < l; j++ )
1151 R = 38142 *(*a-16) + 52298 *(*c -128);
1152 G = 38142 *(*a-16) - 26640 *(*c -128) - 12845 *(*b -128);
1153 B = 38142 *(*a-16) + 66093 *(*b -128);
1162 if (R > 255) R = 255;
1163 if (G > 255) G = 255;
1164 if (B > 255) B = 255;
1166 *(localRaw++) = (uint8_t)R;
1167 *(localRaw++) = (uint8_t)G;
1168 *(localRaw++) = (uint8_t)B;
1177 /// \brief Deals with the color decoding i.e. handle:
1178 /// - R, G, B planes (as opposed to RGB pixels)
1179 /// - YBR (various) encodings.
1180 /// - LUT[s] (or "PALETTE COLOR").
1182 void PixelReadConvert::ConvertHandleColor()
1184 //////////////////////////////////
1185 // Deal 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 // The classification in the color decoding schema is based on the blending
1191 // of two Dicom tags values:
1192 // * "Photometric Interpretation" for which we have the cases:
1193 // - [Photo A] MONOCHROME[1|2] pictures,
1194 // - [Photo B] RGB or YBR_FULL_422 (which acts as RGB),
1195 // - [Photo C] YBR_* (with the above exception of YBR_FULL_422)
1196 // - [Photo D] "PALETTE COLOR" which indicates the presence of LUT[s].
1197 // * "Planar Configuration" for which we have the cases:
1198 // - [Planar 0] 0 then Pixels are already RGB
1199 // - [Planar 1] 1 then we have 3 planes : R, G, B,
1200 // - [Planar 2] 2 then we have 1 gray Plane and 3 LUTs
1202 // Now in theory, one could expect some coherence when blending the above
1203 // cases. For example we should not encounter files belonging at the
1204 // time to case [Planar 0] and case [Photo D].
1205 // Alas, this was only theory ! Because in practice some odd (read ill
1206 // formated Dicom) files (e.g. gdcmData/US-PAL-8-10x-echo.dcm) we encounter:
1207 // - "Planar Configuration" = 0,
1208 // - "Photometric Interpretation" = "PALETTE COLOR".
1209 // Hence gdcm will use the folowing "heuristic" in order to be tolerant
1210 // towards Dicom-non-conformant files:
1211 // << whatever the "Planar Configuration" value might be, a
1212 // "Photometric Interpretation" set to "PALETTE COLOR" forces
1213 // a LUT intervention >>
1215 // Now we are left with the following handling of the cases:
1216 // - [Planar 0] OR [Photo A] no color decoding (since respectively
1217 // Pixels are already RGB and monochrome pictures have no color :),
1218 // - [Planar 1] AND [Photo B] handled with ConvertRGBPlanesToRGBPixels()
1219 // - [Planar 1] AND [Photo C] handled with ConvertYcBcRPlanesToRGBPixels()
1220 // - [Planar 2] OR [Photo D] requires LUT intervention.
1222 gdcmWarningMacro("--> ConvertHandleColor"
1223 << "Planar Configuration " << PlanarConfiguration );
1227 // [Planar 2] OR [Photo D]: LUT intervention done outside
1228 gdcmWarningMacro("--> RawRGB : LUT intervention done outside");
1232 if ( PlanarConfiguration == 1 )
1236 // [Planar 1] AND [Photo C] (remember YBR_FULL_422 acts as RGB)
1237 gdcmWarningMacro("--> YBRFull");
1238 ConvertYcBcRPlanesToRGBPixels();
1242 // [Planar 1] AND [Photo C]
1243 gdcmWarningMacro("--> YBRFull");
1244 ConvertRGBPlanesToRGBPixels();
1249 // When planarConf is 0, and RLELossless (forbidden by Dicom norm)
1250 // pixels need to be RGB-fyied anyway
1254 gdcmWarningMacro("--> RLE Lossless");
1255 ConvertRGBPlanesToRGBPixels();
1258 // In *normal *case, when planarConf is 0, pixels are already in RGB
1261 /// Computes the Pixels Size
1262 void PixelReadConvert::ComputeRawAndRGBSizes()
1264 int bitsAllocated = BitsAllocated;
1265 // Number of "Bits Allocated" is fixed to 16 when it's 12, since
1266 // in this case we will expand the image to 16 bits (see
1267 // \ref ReadAndDecompress12BitsTo16Bits() )
1268 if ( BitsAllocated == 12 )
1273 RawSize = XSize * YSize * ZSize
1274 * ( bitsAllocated / 8 )
1278 RGBSize = 3 * RawSize; // works for 8 and 16 bits per Pixel
1286 /// Allocates room for RGB Pixels
1287 void PixelReadConvert::AllocateRGB()
1291 RGB = new uint8_t[RGBSize];
1294 /// Allocates room for RAW Pixels
1295 void PixelReadConvert::AllocateRaw()
1299 Raw = new uint8_t[RawSize];
1302 //-----------------------------------------------------------------------------
1305 * \brief Print self.
1306 * @param indent Indentation string to be prepended during printing.
1307 * @param os Stream to print to.
1309 void PixelReadConvert::Print( std::ostream &os, std::string const &indent )
1312 << "--- Pixel information -------------------------"
1315 << "Pixel Data: offset " << PixelOffset
1316 << " x(" << std::hex << PixelOffset << std::dec
1317 << ") length " << PixelDataLength
1318 << " x(" << std::hex << PixelDataLength << std::dec
1319 << ")" << std::endl;
1321 if ( IsRLELossless )
1325 RLEInfo->Print( os, indent );
1329 gdcmWarningMacro("Set as RLE file but NO RLEinfo present.");
1333 if ( IsJPEG2000 || IsJPEGLossless || IsJPEGLossy || IsJPEGLS )
1337 JPEGInfo->Print( os, indent );
1341 gdcmWarningMacro("Set as JPEG file but NO JPEGinfo present.");
1346 //-----------------------------------------------------------------------------
1347 } // end namespace gdcm
1349 // Note to developpers :
1350 // Here is a very detailled post from David Clunie, on the troubles caused
1351 // 'non standard' LUT and LUT description
1352 // We shall have to take it into accound in our code.
1357 Subject: Problem with VOI LUTs in Agfa and Fuji CR and GE DX images, was Re: VOI LUT issues
1358 Date: Sun, 06 Feb 2005 17:13:40 GMT
1359 From: David Clunie <dclunie@dclunie.com>
1360 Reply-To: dclunie@dclunie.com
1361 Newsgroups: comp.protocols.dicom
1362 References: <1107553502.040221.189550@o13g2000cwo.googlegroups.com>
1364 > THE LUT that comes with [my] image claims to be 16-bit, but none of the
1365 > values goes higher than 4095. That being said, though, none of my
1366 > original pixel values goes higher than that, either. I have read
1367 > elsewhere on this group that when that happens you are supposed to
1368 > adjust the LUT. Can someone be more specific? There was a thread from
1369 > 2002 where Marco and David were mentioning doing precisely that.
1376 You have encountered the well known "we know what the standard says but
1377 we are going to ignore it and do what we have been doing for almost
1378 a decade regardless" CR vendor bug. Agfa started this, but they are not
1379 the only vendor doing this now; GE and Fuji may have joined the club.
1381 Sadly, one needs to look at the LUT Data, figure out what the maximum
1382 value actually encoded is, and find the next highest power of 2 (e.g.
1383 212 in this case), to figure out what the range of the data is
1384 supposed to be. I have assumed that if the maximum value in the LUT
1385 data is less than a power of 2 minus 1 (e.g. 0xebc) then the intent
1386 of the vendor was not to use the maximum available grayscale range
1387 of the display (e.g. the maximum is 0xfff in this case). An alternative
1388 would be to scale to the actual maximum rather than a power of two.
1390 Very irritating, and in theory not totally reliable if one really
1391 intended the full 16 bits and only used, say 15, but that is extremely
1392 unlikely since everything would be too dark, and this heuristic
1395 There has never been anything in the standard that describes having
1396 to go through these convolutions. Since the only value in the
1397 standard that describes the bit depth of the LUT values is LUT
1398 Descriptor value 3 and that is (usually) always required to be
1399 either 8 or 16, it mystifies me how the creators' of these images
1400 imagine that the receiver is going to divine the range that is intended. Further, the standard is quite explicit that this 3rd
1401 value defines the range of LUT values, but as far as I am aware, all
1402 the vendors are ignoring the standard and indeed sending a third value
1405 This problem is not confined to CR, and is also seen with DX products.
1407 Typically I have seen:
1409 - Agfa CR, which usually (always ?) sends LUTs, values up to 0x0fff
1410 - Fuji CR, which occasionally send LUTs, values up to 0x03ff
1411 - GE DX, for presentation, which always have LUTs, up to 0x3fff
1413 Swissray, Siemens, Philips, Canon and Kodak never seem to send VOI LUTs
1414 at this point (which is a whole other problem). Note that the presence
1415 or absence of a VOI LUT as opposed to window values may be configurable
1416 on the modality in some cases, and I have just looked at what I happen
1417 to have received from a myriad of sites over whose configuration I have
1418 no control. This may be why the majority of Fuji images have no VOI LUTs,
1419 but a few do (or it may be the Siemens system that these Fuji images went
1420 through that perhaps added it). I do have some test Hologic DX images that
1421 are not from a clinical site that do actually get this right (a value
1422 of 12 for the third value and a max of 0xfff).
1424 Since almost every vendor that I have encountered that encodes LUTs
1425 makes this mistake, perhaps it is time to amend the standard to warn
1426 implementor's of receivers and/or sanction this bad behavior. We have
1427 talked about this in the past in WG 6 but so far everyone has been
1428 reluctant to write into the standard such a comment. Maybe it is time
1429 to try again, since if one is not aware of this problem, one cannot
1430 effectively implement display using VOI LUTs, and there is a vast
1431 installed base to contend with.
1433 I did not check presentation states, in which VOI LUTs could also be
1434 encountered, for the prevalence of this mistake, nor did I look at the
1435 encoding of Modality LUT's, which are unusual. Nor did I check digital
1436 mammography images. I would be interested to hear from anyone who has.
1440 PS. The following older thread in this newsgroup discusses this:
1442 "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"
1444 PPS. From a historical perspective, the following may be of interest.
1446 In the original standard in 1993, all that was said about this was a
1447 reference to the corresponding such where Modality LUTs are described
1450 "The third value specifies the number of bits for each entry in the
1451 LUT Data. It shall take the value 8 or 16. The LUT Data shall be stored
1452 in a format equivalent to 8 or 16 bits allocated and high bit equal
1455 Since the high bit hint was not apparently explicit enough, a very
1456 early CP, CP 15 (submitted by Agfa as it happens), replaced this with:
1458 "The third value conveys the range of LUT entry values. It shall take
1459 the value 8 or 16, corresponding with the LUT entry value range of
1462 Note: The third value is not required for describing the
1463 LUT data and is only included for informational usage
1464 and for maintaining compatibility with ACRNEMA 2.0.
1466 The LUT Data contains the LUT entry values."
1468 That is how it read in the 1996, 1998 and 1999 editions.
1470 By the 2000 edition, Supplement 33 that introduced presentation states
1471 extensively reworked this entire section and tried to explain this in
1474 "The output range is from 0 to 2^n-1 where n is the third value of LUT
1475 Descriptor. This range is always unsigned."
1477 and also added a note to spell out what the output range meant in the
1480 "9. The output of the Window Center/Width or VOI LUT transformation
1481 is either implicitly scaled to the full range of the display device
1482 if there is no succeeding transformation defined, or implicitly scaled
1483 to the full input range of the succeeding transformation step (such as
1484 the Presentation LUT), if present. See C.11.6.1."
1486 It still reads this way in the 2004 edition.
1488 Note that LUTs in other applications than the general VOI LUT allow for
1489 values other than 8 or 16 in the third value of LUT descriptor to permit
1490 ranges other than 0 to 255 or 65535.
1492 In addition, the DX Image Module specializes the VOI LUT
1493 attributes as follows, in PS 3.3 section C.8.11.3.1.5 (added in Sup 32):
1495 "The third value specifies the number of bits for each entry in the LUT
1496 Data (analogous to ìbits storedî). It shall be between 10-16. The LUT
1497 Data shall be stored in a format equivalent to 16 ìbits allocatedî and
1498 ìhigh bitî equal to ìbits storedî - 1. The third value conveys the range
1499 of LUT entry values. These unsigned LUT entry values shall range between
1500 0 and 2^n-1, where n is the third value of the LUT Descriptor."
1502 So in the case of the GE DX for presentation images, the third value of
1503 LUT descriptor is allowed to be and probably should be 14 rather than 16.