1 /*=========================================================================
4 Module: $RCSfile: gdcmPixelReadConvert.cxx,v $
6 Date: $Date: 2006/06/29 13:27:59 $
7 Version: $Revision: 1.112 $
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
31 #if defined(__BORLANDC__)
32 #include <mem.h> // for memset
38 //bool ReadMPEGFile (std::ifstream *fp, char *inputdata, size_t lenght);
39 bool gdcm_read_JPEG2000_file (void* raw,
40 char *inputdata, size_t inputlength);
41 //-----------------------------------------------------------------------------
42 #define str2num(str, typeNum) *((typeNum *)(str))
44 //-----------------------------------------------------------------------------
45 // Constructor / Destructor
47 PixelReadConvert::PixelReadConvert()
63 /// Canonical Destructor
64 PixelReadConvert::~PixelReadConvert()
69 //-----------------------------------------------------------------------------
72 * \brief Predicate to know whether the image[s] (once Raw) is RGB.
73 * \note See comments of \ref ConvertHandleColor
75 bool PixelReadConvert::IsRawRGB()
78 || PlanarConfiguration == 2
86 * \brief Gets various usefull informations from the file header
87 * @param file gdcm::File pointer
88 * @param fileHelper gdcm::FileHelper pointer
90 void PixelReadConvert::GrabInformationsFromFile( File *file,
91 FileHelper *fileHelper )
93 // Number of Bits Allocated for storing a Pixel is defaulted to 16
94 // when absent from the file.
95 BitsAllocated = file->GetBitsAllocated();
96 if ( BitsAllocated == 0 )
101 // Number of "Bits Stored", defaulted to number of "Bits Allocated"
102 // when absent from the file.
103 BitsStored = file->GetBitsStored();
104 if ( BitsStored == 0 )
106 BitsStored = BitsAllocated;
109 // High Bit Position, defaulted to "Bits Allocated" - 1
110 HighBitPosition = file->GetHighBitPosition();
111 if ( HighBitPosition == 0 )
113 HighBitPosition = BitsAllocated - 1;
116 XSize = file->GetXSize();
117 YSize = file->GetYSize();
118 ZSize = file->GetZSize();
119 TSize = file->GetTSize();
120 SamplesPerPixel = file->GetSamplesPerPixel();
121 //PixelSize = file->GetPixelSize(); Useless
122 PixelSign = file->IsSignedPixelData();
123 SwapCode = file->GetSwapCode();
125 IsPrivateGETransferSyntax = IsMPEG
126 = IsJPEG2000 = IsJPEGLS = IsJPEGLossy
127 = IsJPEGLossless = IsRLELossless
130 if (! file->IsDicomV3() ) // Should be ACR-NEMA file
136 std::string ts = file->GetTransferSyntax();
139 while (true) // shorter to write than 'if elseif elseif elseif' ...
141 // mind the order : check the most usual first.
142 if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRLittleEndian) break;
143 if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRLittleEndian ) break;
144 if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRBigEndian) break;
145 if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRBigEndianPrivateGE) break;
146 // DeflatedExplicitVRLittleEndian syntax means the whole Dataset (Header + Pixels) is compressed !
147 // Not dealt with ! (Parser hangs)
148 //if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::DeflatedExplicitVRLittleEndian) break;
151 // cache whether this is a strange GE transfer syntax (which uses
152 // a little endian transfer syntax for the header and a big endian
153 // transfer syntax for the pixel data).
154 IsPrivateGETransferSyntax =
155 ( Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRBigEndianPrivateGE );
157 IsMPEG = IsJPEG2000 = IsJPEGLS = IsJPEGLossy = IsJPEGLossless = IsRLELossless = false;
162 // mind the order : check the most usual first.
163 if( IsJPEGLossy = Global::GetTS()->IsJPEGLossy(ts) ) break;
164 if( IsJPEGLossless = Global::GetTS()->IsJPEGLossless(ts) ) break;
165 if( IsRLELossless = Global::GetTS()->IsRLELossless(ts) ) break;
166 if( IsJPEG2000 = Global::GetTS()->IsJPEG2000(ts) ) break;
167 if( IsMPEG = Global::GetTS()->IsMPEG(ts) ) break;
168 if( IsJPEGLS = Global::GetTS()->IsJPEGLS(ts) ) break;
169 // DeflatedExplicitVRLittleEndian is considered as 'Unexpected' (we don't know yet haow to process !)
170 gdcmWarningMacro("Unexpected Transfer Syntax :[" << ts << "]");
176 PixelOffset = file->GetPixelOffset();
177 PixelDataLength = file->GetPixelAreaLength();
178 RLEInfo = file->GetRLEInfo();
179 JPEGInfo = file->GetJPEGInfo();
181 IsMonochrome = file->IsMonochrome();
182 IsMonochrome1 = file->IsMonochrome1();
183 IsPaletteColor = file->IsPaletteColor();
184 IsYBRFull = file->IsYBRFull();
186 PlanarConfiguration = file->GetPlanarConfiguration();
188 /////////////////////////////////////////////////////////////////
190 HasLUT = file->HasLUT();
193 // Just in case some access to a File element requires disk access.
194 LutRedDescriptor = file->GetEntryString( 0x0028, 0x1101 );
195 LutGreenDescriptor = file->GetEntryString( 0x0028, 0x1102 );
196 LutBlueDescriptor = file->GetEntryString( 0x0028, 0x1103 );
198 // FIXME : The following comment is probabely meaningless, since LUT are *always*
199 // loaded at parsing time, whatever their length is.
201 // Depending on the value of Document::MAX_SIZE_LOAD_ELEMENT_VALUE
202 // [ refer to invocation of Document::SetMaxSizeLoadEntry() in
203 // Document::Document() ], the loading of the value (content) of a
204 // [Bin|Val]Entry occurence migth have been hindered (read simply NOT
205 // loaded). Hence, we first try to obtain the LUTs data from the file
206 // and when this fails we read the LUTs data directly from disk.
207 // \TODO Reading a [Bin|Val]Entry directly from disk is a kludge.
208 // We should NOT bypass the [Bin|Val]Entry class. Instead
209 // an access to an UNLOADED content of a [Bin|Val]Entry occurence
210 // (e.g. DataEntry::GetBinArea()) should force disk access from
211 // within the [Bin|Val]Entry class itself. The only problem
212 // is that the [Bin|Val]Entry is unaware of the FILE* is was
213 // parsed from. Fix that. FIXME.
216 file->LoadEntryBinArea(0x0028, 0x1201);
217 LutRedData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1201 );
220 gdcmWarningMacro("Unable to read Red Palette Color Lookup Table data");
224 file->LoadEntryBinArea(0x0028, 0x1202);
225 LutGreenData = (uint8_t*)file->GetEntryBinArea(0x0028, 0x1202 );
228 gdcmWarningMacro("Unable to read Green Palette Color Lookup Table data");
232 file->LoadEntryBinArea(0x0028, 0x1203);
233 LutBlueData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1203 );
236 gdcmWarningMacro("Unable to read Blue Palette Color Lookup Table data");
241 ComputeRawAndRGBSizes();
244 /// \brief Reads from disk and decompresses Pixels
245 bool PixelReadConvert::ReadAndDecompressPixelData( std::ifstream *fp )
247 // ComputeRawAndRGBSizes is already made by
248 // ::GrabInformationsFromfile. So, the structure sizes are
252 //////////////////////////////////////////////////
253 //// First stage: get our hands on the Pixel Data.
256 gdcmWarningMacro( "Unavailable file pointer." );
260 fp->seekg( PixelOffset, std::ios::beg );
261 if ( fp->fail() || fp->eof() )
263 gdcmWarningMacro( "Unable to find PixelOffset in file." );
269 //////////////////////////////////////////////////
271 CallStartMethod(); // for progress bar
272 unsigned int count = 0;
273 unsigned int frameSize;
274 unsigned int bitsAllocated = BitsAllocated;
275 if(bitsAllocated == 12)
277 frameSize = XSize*YSize*SamplesPerPixel*bitsAllocated/8;
279 //// Second stage: read from disk and decompress.
281 if ( BitsAllocated == 12 ) // We suppose 'BitsAllocated' = 12 only exist for uncompressed files
283 ReadAndDecompress12BitsTo16Bits( fp);
287 // This problem can be found when some obvious informations are found
288 // after the field containing the image data. In this case, these
289 // bad data are added to the size of the image (in the PixelDataLength
290 // variable). But RawSize is the right size of the image !
291 if ( PixelDataLength != RawSize )
293 gdcmWarningMacro( "Mismatch between PixelReadConvert : "
294 << PixelDataLength << " and RawSize : " << RawSize );
297 //todo : is it the right patch?
298 char *raw = (char*)Raw;
299 uint32_t remainingLength;
301 unsigned int lengthToRead;
303 if ( PixelDataLength > RawSize )
304 lengthToRead = RawSize;
306 lengthToRead = PixelDataLength;
308 // perform a frame by frame reading
309 remainingLength = lengthToRead;
310 unsigned int nbFrames = lengthToRead / frameSize;
311 for (i=0;i<nbFrames; i++)
313 Progress = (float)(count+1)/(float)nbFrames;
314 fp->read( raw, frameSize);
316 remainingLength -= frameSize;
319 if (remainingLength !=0 )
320 fp->read( raw, remainingLength);
322 if ( fp->fail() || fp->eof())
324 gdcmWarningMacro( "Reading of Raw pixel data failed." );
328 else if ( IsRLELossless )
330 if ( ! RLEInfo->DecompressRLEFile
331 ( fp, Raw, XSize, YSize, ZSize, TSize, BitsAllocated ) )
333 gdcmWarningMacro( "RLE decompressor failed." );
339 //gdcmWarningMacro( "Sorry, MPEG not yet taken into account" );
341 // fp has already been seek to start of mpeg
342 //ReadMPEGFile(fp, (char*)Raw, PixelDataLength);
347 // Default case concerns JPEG family
348 if ( ! ReadAndDecompressJPEGFile( fp ) )
350 gdcmWarningMacro( "JPEG decompressor ( ReadAndDecompressJPEGFile()"
351 << " method ) failed." );
356 ////////////////////////////////////////////
357 //// Third stage: twigle the bytes and bits.
358 ConvertReorderEndianity();
359 ConvertReArrangeBits();
360 ConvertFixGreyLevels();
361 if (UserFunction) // user is allowed to Mirror, TopDown, Rotate,...the image
362 UserFunction( Raw, FileInternal);
363 ConvertHandleColor();
368 /// Deletes Pixels Area
369 void PixelReadConvert::Squeeze()
385 * \brief Build the RGB image from the Raw image and the LUTs.
387 bool PixelReadConvert::BuildRGBImage()
391 // The job is already done.
397 // The job can't be done
404 // The job can't be done
408 gdcmDebugMacro( "--> BuildRGBImage" );
414 if ( BitsAllocated <= 8 )
416 uint8_t *localRGB = RGB;
417 for (size_t i = 0; i < RawSize; ++i )
420 *localRGB++ = LutRGBA[j];
421 *localRGB++ = LutRGBA[j+1];
422 *localRGB++ = LutRGBA[j+2];
426 else // deal with 16 bits pixels and 16 bits Palette color
428 uint16_t *localRGB = (uint16_t *)RGB;
429 for (size_t i = 0; i < RawSize/2; ++i )
431 j = ((uint16_t *)Raw)[i] * 4;
432 *localRGB++ = ((uint16_t *)LutRGBA)[j];
433 *localRGB++ = ((uint16_t *)LutRGBA)[j+1];
434 *localRGB++ = ((uint16_t *)LutRGBA)[j+2];
441 //-----------------------------------------------------------------------------
444 //-----------------------------------------------------------------------------
447 * \brief Read from file a 12 bits per pixel image and decompress it
448 * into a 16 bits per pixel image.
450 void PixelReadConvert::ReadAndDecompress12BitsTo16Bits( std::ifstream *fp )
451 throw ( FormatError )
453 /// \todo Fix the 3D, 4D pb
454 int nbPixels = XSize * YSize * TSize;
455 uint16_t *localDecompres = (uint16_t*)Raw;
457 for( int p = 0; p < nbPixels; p += 2 )
461 fp->read( (char*)&b0, 1);
462 if ( fp->fail() || fp->eof() )
464 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
465 "Unfound first block" );
468 fp->read( (char*)&b1, 1 );
469 if ( fp->fail() || fp->eof())
471 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
472 "Unfound second block" );
475 fp->read( (char*)&b2, 1 );
476 if ( fp->fail() || fp->eof())
478 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
479 "Unfound second block" );
482 // Two steps are necessary to please VC++
484 // 2 pixels 12bit = [0xABCDEF]
485 // 2 pixels 16bit = [0x0ABD] + [0x0FCE]
487 *localDecompres++ = ((b0 >> 4) << 8) + ((b0 & 0x0f) << 4) + (b1 & 0x0f);
489 *localDecompres++ = ((b2 & 0x0f) << 8) + ((b1 >> 4) << 4) + (b2 >> 4);
491 /// \todo JPR Troubles expected on Big-Endian processors ?
496 * \brief Reads from disk the Pixel Data of JPEG Dicom encapsulated
497 * file and decompress it.
498 * @param fp File Pointer
501 bool PixelReadConvert::ReadAndDecompressJPEGFile( std::ifstream *fp )
505 // make sure this is the right JPEG compression
506 assert( !IsJPEGLossless || !IsJPEGLossy || !IsJPEGLS );
507 // FIXME this is really ugly but it seems I have to load the complete
508 // jpeg2000 stream to use jasper:
509 // I don't think we'll ever be able to deal with multiple fragments properly
511 unsigned long inputlength = 0;
512 JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment();
515 inputlength += jpegfrag->GetLength();
516 jpegfrag = JPEGInfo->GetNextFragment();
518 gdcmAssertMacro( inputlength != 0);
519 uint8_t *inputdata = new uint8_t[inputlength];
520 char *pinputdata = (char*)inputdata;
521 jpegfrag = JPEGInfo->GetFirstFragment();
524 fp->seekg( jpegfrag->GetOffset(), std::ios::beg);
525 fp->read(pinputdata, jpegfrag->GetLength());
526 pinputdata += jpegfrag->GetLength();
527 jpegfrag = JPEGInfo->GetNextFragment();
529 // Warning the inputdata buffer is delete in the function
530 if ( ! gdcm_read_JPEG2000_file( Raw,
531 (char*)inputdata, inputlength ) )
535 // wow what happen, must be an error
536 gdcmWarningMacro( "gdcm_read_JPEG2000_file() failed ");
541 // make sure this is the right JPEG compression
542 assert( !IsJPEGLossless || !IsJPEGLossy || !IsJPEG2000 );
543 // WARNING : JPEG-LS is NOT the 'classical' Jpeg Lossless :
544 // [JPEG-LS is the basis for new lossless/near-lossless compression
545 // standard for continuous-tone images intended for JPEG2000. The standard
546 // is based on the LOCO-I algorithm (LOw COmplexity LOssless COmpression
547 // for Images) developed at Hewlett-Packard Laboratories]
549 // see http://datacompression.info/JPEGLS.shtml
552 std::cerr << "count:" << JPEGInfo->GetFragmentCount() << std::endl;
553 unsigned long inputlength = 0;
554 JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment();
557 inputlength += jpegfrag->GetLength();
558 jpegfrag = JPEGInfo->GetNextFragment();
560 gdcmAssertMacro( inputlength != 0);
561 uint8_t *inputdata = new uint8_t[inputlength];
562 char *pinputdata = (char*)inputdata;
563 jpegfrag = JPEGInfo->GetFirstFragment();
566 fp->seekg( jpegfrag->GetOffset(), std::ios::beg);
567 fp->read(pinputdata, jpegfrag->GetLength());
568 pinputdata += jpegfrag->GetLength();
569 jpegfrag = JPEGInfo->GetNextFragment();
572 //fp->read((char*)Raw, PixelDataLength);
574 std::ofstream out("/tmp/jpegls.jpg");
575 out.write((char*)inputdata, inputlength);
580 gdcmWarningMacro( "Sorry, JPEG-LS not yet taken into account" );
581 fp->seekg( JPEGInfo->GetFirstFragment()->GetOffset(), std::ios::beg);
582 // if ( ! gdcm_read_JPEGLS_file( fp,Raw ) )
587 // make sure this is the right JPEG compression
588 assert( !IsJPEGLS || !IsJPEG2000 );
589 // Precompute the offset localRaw will be shifted with
590 int length = XSize * YSize * ZSize * SamplesPerPixel;
591 int numberBytes = BitsAllocated / 8;
593 JPEGInfo->DecompressFromFile(fp, Raw, BitsStored, numberBytes, length );
599 * \brief Build Red/Green/Blue/Alpha LUT from File when :
600 * - (0028,0004) : Photometric Interpretation == [PALETTE COLOR ]
602 * - (0028,1101),(0028,1102),(0028,1102)
603 * xxx Palette Color Lookup Table Descriptor are found
605 * - (0028,1201),(0028,1202),(0028,1202)
606 * xxx Palette Color Lookup Table Data - are found
607 * \warning does NOT deal with :
608 * - 0028 1100 Gray Lookup Table Descriptor (Retired)
609 * - 0028 1221 Segmented Red Palette Color Lookup Table Data
610 * - 0028 1222 Segmented Green Palette Color Lookup Table Data
611 * - 0028 1223 Segmented Blue Palette Color Lookup Table Data
612 * no known Dicom reader deals with them :-(
613 * @return a RGBA Lookup Table
615 void PixelReadConvert::BuildLUTRGBA()
618 // Note to code reviewers :
619 // The problem is *much more* complicated, since a lot of manufacturers
620 // Don't follow the norm :
621 // have a look at David Clunie's remark at the end of this .cxx file.
628 // http://www.barre.nom.fr/medical/dicom2/limitations.html#Color%20Lookup%20Tables
630 if ( ! IsPaletteColor )
635 if ( LutRedDescriptor == GDCM_UNFOUND
636 || LutGreenDescriptor == GDCM_UNFOUND
637 || LutBlueDescriptor == GDCM_UNFOUND )
639 gdcmWarningMacro( "(At least) a LUT Descriptor is missing" );
643 ////////////////////////////////////////////
644 // Extract the info from the LUT descriptors
645 int lengthR; // Red LUT length in Bytes
646 int debR; // Subscript of the first Lut Value
647 int nbitsR; // Lut item size (in Bits)
648 int nbRead; // nb of items in LUT descriptor (must be = 3)
650 nbRead = sscanf( LutRedDescriptor.c_str(),
652 &lengthR, &debR, &nbitsR );
655 gdcmWarningMacro( "Wrong Red LUT descriptor" );
657 int lengthG; // Green LUT length in Bytes
658 int debG; // Subscript of the first Lut Value
659 int nbitsG; // Lut item size (in Bits)
661 nbRead = sscanf( LutGreenDescriptor.c_str(),
663 &lengthG, &debG, &nbitsG );
666 gdcmWarningMacro( "Wrong Green LUT descriptor" );
669 int lengthB; // Blue LUT length in Bytes
670 int debB; // Subscript of the first Lut Value
671 int nbitsB; // Lut item size (in Bits)
672 nbRead = sscanf( LutRedDescriptor.c_str(),
674 &lengthB, &debB, &nbitsB );
677 gdcmWarningMacro( "Wrong Blue LUT descriptor" );
680 gdcmDebugMacro(" lengthR " << lengthR << " debR "
681 << debR << " nbitsR " << nbitsR);
682 gdcmDebugMacro(" lengthG " << lengthG << " debG "
683 << debG << " nbitsG " << nbitsG);
684 gdcmDebugMacro(" lengthB " << lengthB << " debB "
685 << debB << " nbitsB " << nbitsB);
687 if ( !lengthR ) // if = 2^16, this shall be 0 see : CP-143
689 if ( !lengthG ) // if = 2^16, this shall be 0
691 if ( !lengthB ) // if = 2^16, this shall be 0
694 ////////////////////////////////////////////////////////
696 if ( ( ! LutRedData ) || ( ! LutGreenData ) || ( ! LutBlueData ) )
698 gdcmWarningMacro( "(At least) a LUT is missing" );
702 // -------------------------------------------------------------
704 if ( BitsAllocated <= 8 )
706 // forge the 4 * 8 Bits Red/Green/Blue/Alpha LUT
707 LutRGBA = new uint8_t[ 1024 ]; // 256 * 4 (R, G, B, Alpha)
712 memset( LutRGBA, 0, 1024 );
715 if ( ( nbitsR == 16 ) && ( BitsAllocated == 8 ) )
717 // when LUT item size is different than pixel size
718 mult = 2; // high byte must be = low byte
722 // See PS 3.3-2003 C.11.1.1.2 p 619
726 // if we get a black image, let's just remove the '+1'
727 // from 'i*mult+1' and check again
728 // if it works, we shall have to check the 3 Palettes
729 // to see which byte is ==0 (first one, or second one)
731 // We give up the checking to avoid some (useless ?) overhead
732 // (optimistic asumption)
736 //take "Subscript of the first Lut Value" (debR,debG,debB) into account!
738 //FIXME : +1 : to get 'low value' byte
739 // Trouble expected on Big Endian Processors ?
740 // 16 BIts Per Pixel Palette Color to be swapped?
742 a = LutRGBA + 0 + debR;
743 for( i=0; i < lengthR; ++i )
745 *a = LutRedData[i*mult+1];
749 a = LutRGBA + 1 + debG;
750 for( i=0; i < lengthG; ++i)
752 *a = LutGreenData[i*mult+1];
756 a = LutRGBA + 2 + debB;
757 for(i=0; i < lengthB; ++i)
759 *a = LutBlueData[i*mult+1];
764 for(i=0; i < 256; ++i)
766 *a = 1; // Alpha component
772 // Probabely the same stuff is to be done for 16 Bits Pixels
773 // with 65536 entries LUT ?!?
774 // Still looking for accurate info on the web :-(
776 gdcmWarningMacro( "Sorry Palette Color Lookup Tables not yet dealt with"
777 << " for 16 Bits Per Pixel images" );
779 // forge the 4 * 16 Bits Red/Green/Blue/Alpha LUT
781 LutRGBA = (uint8_t *)new uint16_t[ 65536*4 ]; // 2^16 * 4 (R, G, B, Alpha)
784 memset( LutRGBA, 0, 65536*4*2 ); // 16 bits = 2 bytes ;-)
786 LutItemNumber = 65536;
792 //take "Subscript of the first Lut Value" (debR,debG,debB) into account!
794 a16 = (uint16_t*)LutRGBA + 0 + debR;
795 for( i=0; i < lengthR; ++i )
797 *a16 = ((uint16_t*)LutRedData)[i];
801 a16 = (uint16_t*)LutRGBA + 1 + debG;
802 for( i=0; i < lengthG; ++i)
804 *a16 = ((uint16_t*)LutGreenData)[i];
808 a16 = (uint16_t*)LutRGBA + 2 + debB;
809 for(i=0; i < lengthB; ++i)
811 *a16 = ((uint16_t*)LutBlueData)[i];
815 a16 = (uint16_t*)LutRGBA + 3 ;
816 for(i=0; i < 65536; ++i)
818 *a16 = 1; // Alpha component
821 /* Just to 'see' the LUT, at debug time
822 // Don't remove this commented out code.
824 a16=(uint16_t*)LutRGBA;
825 for (int j=0;j<65536;j++)
827 std::cout << *a16 << " " << *(a16+1) << " "
828 << *(a16+2) << " " << *(a16+3) << std::endl;
836 * \brief Swap the bytes, according to \ref SwapCode.
838 void PixelReadConvert::ConvertSwapZone()
842 // If this file is 'ImplicitVR BigEndian PrivateGE Transfer Syntax',
843 // then the header is in little endian format and the pixel data is in
844 // big endian format. When reading the header, GDCM has already established
845 // a byte swapping code suitable for this machine to read the
846 // header. In TS::ImplicitVRBigEndianPrivateGE, this code will need
847 // to be switched in order to read the pixel data. This must be
848 // done REGARDLESS of the processor endianess!
850 // Example: Assume we are on a little endian machine. When
851 // GDCM reads the header, the header will match the machine
852 // endianess and the swap code will be established as a no-op.
853 // When GDCM reaches the pixel data, it will need to switch the
854 // swap code to do big endian to little endian conversion.
856 // Now, assume we are on a big endian machine. When GDCM reads the
857 // header, the header will be recognized as a different endianess
858 // than the machine endianess, and a swap code will be established
859 // to convert from little endian to big endian. When GDCM readers
860 // the pixel data, the pixel data endianess will now match the
861 // machine endianess. But we currently have a swap code that
862 // converts from little endian to big endian. In this case, we
863 // need to switch the swap code to a no-op.
865 // Therefore, in either case, if the file is in
866 // 'ImplicitVR BigEndian PrivateGE Transfer Syntax', then GDCM needs to switch
867 // the byte swapping code when entering the pixel data.
869 int tempSwapCode = SwapCode;
870 if ( IsPrivateGETransferSyntax )
872 gdcmWarningMacro(" IsPrivateGETransferSyntax found; turn the SwapCode");
873 // PrivateGETransferSyntax only exists for 'true' Dicom images
874 // we assume there is no 'exotic' 32 bits endianess!
875 if (SwapCode == 1234)
879 else if (SwapCode == 4321)
885 if ( BitsAllocated == 16 )
887 uint16_t *im16 = (uint16_t*)Raw;
888 switch( tempSwapCode )
895 for( i = 0; i < RawSize / 2; i++ )
897 im16[i]= (im16[i] >> 8) | (im16[i] << 8 );
901 gdcmWarningMacro("SwapCode value (16 bits) not allowed."
905 else if ( BitsAllocated == 32 )
910 uint32_t *im32 = (uint32_t*)Raw;
911 switch ( tempSwapCode )
916 for( i = 0; i < RawSize / 4; i++ )
918 low = im32[i] & 0x0000ffff; // 4321
919 high = im32[i] >> 16;
920 high = ( high >> 8 ) | ( high << 8 );
921 low = ( low >> 8 ) | ( low << 8 );
923 im32[i] = ( s32 << 16 ) | high;
927 for( i = 0; i < RawSize / 4; i++ )
929 low = im32[i] & 0x0000ffff; // 2143
930 high = im32[i] >> 16;
931 high = ( high >> 8 ) | ( high << 8 );
932 low = ( low >> 8 ) | ( low << 8 );
934 im32[i] = ( s32 << 16 ) | low;
938 for( i = 0; i < RawSize / 4; i++ )
940 low = im32[i] & 0x0000ffff; // 3412
941 high = im32[i] >> 16;
943 im32[i] = ( s32 << 16 ) | high;
947 gdcmWarningMacro("SwapCode value (32 bits) not allowed." << tempSwapCode );
953 * \brief Deal with endianness i.e. re-arange bytes inside the integer
955 void PixelReadConvert::ConvertReorderEndianity()
957 if ( BitsAllocated != 8 )
962 // Special kludge in order to deal with xmedcon broken images:
963 if ( BitsAllocated == 16
964 && BitsStored < BitsAllocated
967 int l = (int)( RawSize / ( BitsAllocated / 8 ) );
968 uint16_t *deb = (uint16_t *)Raw;
969 for(int i = 0; i<l; i++)
971 if ( *deb == 0xffff )
981 * \brief Deal with Grey levels i.e. re-arange them
982 * to have low values = dark, high values = bright
984 void PixelReadConvert::ConvertFixGreyLevels()
989 uint32_t i; // to please M$VC6
994 if ( BitsAllocated == 8 )
996 uint8_t *deb = (uint8_t *)Raw;
997 for (i=0; i<RawSize; i++)
1005 if ( BitsAllocated == 16 )
1008 for (j=0; j<BitsStored-1; j++)
1010 mask = (mask << 1) +1; // will be fff when BitsStored=12
1013 uint16_t *deb = (uint16_t *)Raw;
1014 for (i=0; i<RawSize/2; i++)
1024 if ( BitsAllocated == 8 )
1026 uint8_t smask8 = 255;
1027 uint8_t *deb = (uint8_t *)Raw;
1028 for (i=0; i<RawSize; i++)
1030 *deb = smask8 - *deb;
1035 if ( BitsAllocated == 16 )
1037 uint16_t smask16 = 65535;
1038 uint16_t *deb = (uint16_t *)Raw;
1039 for (i=0; i<RawSize/2; i++)
1041 *deb = smask16 - *deb;
1050 * \brief Re-arrange the bits within the bytes.
1051 * @return Boolean always true
1053 bool PixelReadConvert::ConvertReArrangeBits() throw ( FormatError )
1056 if ( BitsStored != BitsAllocated )
1058 int l = (int)( RawSize / ( BitsAllocated / 8 ) );
1059 if ( BitsAllocated == 16 )
1061 // pmask : to mask the 'unused bits' (may contain overlays)
1062 uint16_t pmask = 0xffff;
1063 pmask = pmask >> ( BitsAllocated - BitsStored );
1065 uint16_t *deb = (uint16_t*)Raw;
1067 if ( !PixelSign ) // Pixels are unsigned
1069 for(int i = 0; i<l; i++)
1071 *deb = (*deb >> (BitsStored - HighBitPosition - 1)) & pmask;
1075 else // Pixels are signed
1077 // smask : to check the 'sign' when BitsStored != BitsAllocated
1078 uint16_t smask = 0x0001;
1079 smask = smask << ( 16 - (BitsAllocated - BitsStored + 1) );
1080 // nmask : to propagate sign bit on negative values
1081 int16_t nmask = (int16_t)0x8000;
1082 nmask = nmask >> ( BitsAllocated - BitsStored - 1 );
1084 for(int i = 0; i<l; i++)
1086 *deb = *deb >> (BitsStored - HighBitPosition - 1);
1089 *deb = *deb | nmask;
1093 *deb = *deb & pmask;
1099 else if ( BitsAllocated == 32 )
1101 // pmask : to mask the 'unused bits' (may contain overlays)
1102 uint32_t pmask = 0xffffffff;
1103 pmask = pmask >> ( BitsAllocated - BitsStored );
1105 uint32_t *deb = (uint32_t*)Raw;
1109 for(int i = 0; i<l; i++)
1111 *deb = (*deb >> (BitsStored - HighBitPosition - 1)) & pmask;
1117 // smask : to check the 'sign' when BitsStored != BitsAllocated
1118 uint32_t smask = 0x00000001;
1119 smask = smask >> ( 32 - (BitsAllocated - BitsStored +1 ));
1120 // nmask : to propagate sign bit on negative values
1121 int32_t nmask = 0x80000000;
1122 nmask = nmask >> ( BitsAllocated - BitsStored -1 );
1124 for(int i = 0; i<l; i++)
1126 *deb = *deb >> (BitsStored - HighBitPosition - 1);
1128 *deb = *deb | nmask;
1130 *deb = *deb & pmask;
1137 gdcmWarningMacro("Weird image (BitsAllocated !=8, 12, 16, 32)");
1138 throw FormatError( "Weird image !?" );
1145 * \brief Convert (Red plane, Green plane, Blue plane) to RGB pixels
1146 * \warning Works on all the frames at a time
1148 void PixelReadConvert::ConvertRGBPlanesToRGBPixels()
1150 gdcmWarningMacro("--> ConvertRGBPlanesToRGBPixels");
1152 uint8_t *localRaw = Raw;
1153 uint8_t *copyRaw = new uint8_t[ RawSize ];
1154 memmove( copyRaw, localRaw, RawSize );
1156 int l = XSize * YSize * ZSize;
1158 uint8_t *a = copyRaw;
1159 uint8_t *b = copyRaw + l;
1160 uint8_t *c = copyRaw + l + l;
1162 for (int j = 0; j < l; j++)
1164 *(localRaw++) = *(a++);
1165 *(localRaw++) = *(b++);
1166 *(localRaw++) = *(c++);
1172 * \brief Convert (cY plane, cB plane, cR plane) to RGB pixels
1173 * \warning Works on all the frames at a time
1175 void PixelReadConvert::ConvertYcBcRPlanesToRGBPixels()
1177 // Remarks for YBR newbees :
1178 // YBR_FULL works very much like RGB, i.e. three samples per pixel,
1179 // just the color space is YCbCr instead of RGB. This is particularly useful
1180 // for doppler ultrasound where most of the image is grayscale
1181 // (i.e. only populates the Y components) and Cb and Cr are mostly zero,
1182 // except for the few patches of color on the image.
1183 // On such images, RLE achieves a compression ratio that is much better
1184 // than the compression ratio on an equivalent RGB image.
1186 gdcmWarningMacro("--> ConvertYcBcRPlanesToRGBPixels");
1188 uint8_t *localRaw = Raw;
1189 uint8_t *copyRaw = new uint8_t[ RawSize ];
1190 memmove( copyRaw, localRaw, RawSize );
1192 // to see the tricks about YBR_FULL, YBR_FULL_422,
1193 // YBR_PARTIAL_422, YBR_ICT, YBR_RCT have a look at :
1194 // ftp://medical.nema.org/medical/dicom/final/sup61_ft.pdf
1195 // and be *very* affraid
1198 /// \todo : find an example to see how 3rd dim and 4th dim work together
1199 int l = XSize * YSize * TSize;
1200 int nbFrames = ZSize;
1202 uint8_t *a = copyRaw + 0;
1203 uint8_t *b = copyRaw + l;
1204 uint8_t *c = copyRaw + l+ l;
1207 /// We replaced easy to understand but time consuming floating point
1208 /// computations by the 'well known' integer computation counterpart
1210 /// http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf
1211 /// for code optimisation.
1213 for ( int i = 0; i < nbFrames; i++ )
1215 for ( int j = 0; j < l; j++ )
1217 R = 38142 *(*a-16) + 52298 *(*c -128);
1218 G = 38142 *(*a-16) - 26640 *(*c -128) - 12845 *(*b -128);
1219 B = 38142 *(*a-16) + 66093 *(*b -128);
1228 if (R > 255) R = 255;
1229 if (G > 255) G = 255;
1230 if (B > 255) B = 255;
1232 *(localRaw++) = (uint8_t)R;
1233 *(localRaw++) = (uint8_t)G;
1234 *(localRaw++) = (uint8_t)B;
1243 /// \brief Deals with the color decoding i.e. handle:
1244 /// - R, G, B planes (as opposed to RGB pixels)
1245 /// - YBR (various) encodings.
1246 /// - LUT[s] (or "PALETTE COLOR").
1248 void PixelReadConvert::ConvertHandleColor()
1250 //////////////////////////////////
1251 // Deal with the color decoding i.e. handle:
1252 // - R, G, B planes (as opposed to RGB pixels)
1253 // - YBR (various) encodings.
1254 // - LUT[s] (or "PALETTE COLOR").
1256 // The classification in the color decoding schema is based on the blending
1257 // of two Dicom tags values:
1258 // * "Photometric Interpretation" for which we have the cases:
1259 // - [Photo A] MONOCHROME[1|2] pictures,
1260 // - [Photo B] RGB or YBR_FULL_422 (which acts as RGB),
1261 // - [Photo C] YBR_* (with the above exception of YBR_FULL_422)
1262 // - [Photo D] "PALETTE COLOR" which indicates the presence of LUT[s].
1263 // * "Planar Configuration" for which we have the cases:
1264 // - [Planar 0] 0 then Pixels are already RGB
1265 // - [Planar 1] 1 then we have 3 planes : R, G, B,
1266 // - [Planar 2] 2 then we have 1 gray Plane and 3 LUTs
1268 // Now in theory, one could expect some coherence when blending the above
1269 // cases. For example we should not encounter files belonging at the
1270 // time to case [Planar 0] and case [Photo D].
1271 // Alas, this was only theory ! Because in practice some odd (read ill
1272 // formated Dicom) files (e.g. gdcmData/US-PAL-8-10x-echo.dcm) we encounter:
1273 // - "Planar Configuration" = 0,
1274 // - "Photometric Interpretation" = "PALETTE COLOR".
1275 // Hence gdcm will use the folowing "heuristic" in order to be tolerant
1276 // towards Dicom-non-conformant files:
1277 // << whatever the "Planar Configuration" value might be, a
1278 // "Photometric Interpretation" set to "PALETTE COLOR" forces
1279 // a LUT intervention >>
1281 // Now we are left with the following handling of the cases:
1282 // - [Planar 0] OR [Photo A] no color decoding (since respectively
1283 // Pixels are already RGB and monochrome pictures have no color :),
1284 // - [Planar 1] AND [Photo B] handled with ConvertRGBPlanesToRGBPixels()
1285 // - [Planar 1] AND [Photo C] handled with ConvertYcBcRPlanesToRGBPixels()
1286 // - [Planar 2] OR [Photo D] requires LUT intervention.
1288 gdcmDebugMacro("--> ConvertHandleColor "
1289 << "Planar Configuration " << PlanarConfiguration );
1293 // [Planar 2] OR [Photo D]: LUT intervention done outside
1294 gdcmDebugMacro("--> RawRGB : LUT intervention done outside");
1298 if ( PlanarConfiguration == 1 )
1302 // [Planar 1] AND [Photo C] (remember YBR_FULL_422 acts as RGB)
1303 gdcmDebugMacro("--> YBRFull");
1304 ConvertYcBcRPlanesToRGBPixels();
1308 // [Planar 1] AND [Photo C]
1309 gdcmDebugMacro("--> YBRFull");
1310 ConvertRGBPlanesToRGBPixels();
1315 // When planarConf is 0, and RLELossless (forbidden by Dicom norm)
1316 // pixels need to be RGB-fyied anyway
1320 gdcmDebugMacro("--> RLE Lossless");
1321 ConvertRGBPlanesToRGBPixels();
1324 // In *normal *case, when planarConf is 0, pixels are already in RGB
1327 /// Computes the Pixels Size
1328 void PixelReadConvert::ComputeRawAndRGBSizes()
1330 int bitsAllocated = BitsAllocated;
1331 // Number of "Bits Allocated" is fixed to 16 when it's 12, since
1332 // in this case we will expand the image to 16 bits (see
1333 // \ref ReadAndDecompress12BitsTo16Bits() )
1334 if ( BitsAllocated == 12 )
1339 RawSize = XSize * YSize * ZSize * TSize
1340 * ( bitsAllocated / 8 )
1344 RGBSize = 3 * RawSize; // works for 8 and 16 bits per Pixel
1352 /// Allocates room for RGB Pixels
1353 void PixelReadConvert::AllocateRGB()
1357 RGB = new uint8_t[RGBSize];
1360 /// Allocates room for RAW Pixels
1361 void PixelReadConvert::AllocateRaw()
1365 Raw = new uint8_t[RawSize];
1368 //-----------------------------------------------------------------------------
1371 * \brief Print self.
1372 * @param indent Indentation string to be prepended during printing.
1373 * @param os Stream to print to.
1375 void PixelReadConvert::Print( std::ostream &os, std::string const &indent )
1378 << "--- Pixel information -------------------------"
1381 << "Pixel Data: offset " << PixelOffset
1382 << " x(" << std::hex << PixelOffset << std::dec
1383 << ") length " << PixelDataLength
1384 << " x(" << std::hex << PixelDataLength << std::dec
1385 << ")" << std::endl;
1387 if ( IsRLELossless )
1391 RLEInfo->Print( os, indent );
1395 gdcmWarningMacro("Set as RLE file but NO RLEinfo present.");
1399 if ( IsJPEG2000 || IsJPEGLossless || IsJPEGLossy || IsJPEGLS )
1403 JPEGInfo->Print( os, indent );
1407 gdcmWarningMacro("Set as JPEG file but NO JPEGinfo present.");
1413 * \brief CallStartMethod
1415 void PixelReadConvert::CallStartMethod()
1419 CommandManager::ExecuteCommand(FH,CMD_STARTPROGRESS);
1423 * \brief CallProgressMethod
1425 void PixelReadConvert::CallProgressMethod()
1427 CommandManager::ExecuteCommand(FH,CMD_PROGRESS);
1431 * \brief CallEndMethod
1433 void PixelReadConvert::CallEndMethod()
1436 CommandManager::ExecuteCommand(FH,CMD_ENDPROGRESS);
1440 //-----------------------------------------------------------------------------
1441 } // end namespace gdcm
1443 // Note to developpers :
1444 // Here is a very detailled post from David Clunie, on the troubles caused
1445 // 'non standard' LUT and LUT description
1446 // We shall have to take it into accound in our code.
1451 Subject: Problem with VOI LUTs in Agfa and Fuji CR and GE DX images, was Re: VOI LUT issues
1452 Date: Sun, 06 Feb 2005 17:13:40 GMT
1453 From: David Clunie <dclunie@dclunie.com>
1454 Reply-To: dclunie@dclunie.com
1455 Newsgroups: comp.protocols.dicom
1456 References: <1107553502.040221.189550@o13g2000cwo.googlegroups.com>
1458 > THE LUT that comes with [my] image claims to be 16-bit, but none of the
1459 > values goes higher than 4095. That being said, though, none of my
1460 > original pixel values goes higher than that, either. I have read
1461 > elsewhere on this group that when that happens you are supposed to
1462 > adjust the LUT. Can someone be more specific? There was a thread from
1463 > 2002 where Marco and David were mentioning doing precisely that.
1470 You have encountered the well known "we know what the standard says but
1471 we are going to ignore it and do what we have been doing for almost
1472 a decade regardless" CR vendor bug. Agfa started this, but they are not
1473 the only vendor doing this now; GE and Fuji may have joined the club.
1475 Sadly, one needs to look at the LUT Data, figure out what the maximum
1476 value actually encoded is, and find the next highest power of 2 (e.g.
1477 212 in this case), to figure out what the range of the data is
1478 supposed to be. I have assumed that if the maximum value in the LUT
1479 data is less than a power of 2 minus 1 (e.g. 0xebc) then the intent
1480 of the vendor was not to use the maximum available grayscale range
1481 of the display (e.g. the maximum is 0xfff in this case). An alternative
1482 would be to scale to the actual maximum rather than a power of two.
1484 Very irritating, and in theory not totally reliable if one really
1485 intended the full 16 bits and only used, say 15, but that is extremely
1486 unlikely since everything would be too dark, and this heuristic
1489 There has never been anything in the standard that describes having
1490 to go through these convolutions. Since the only value in the
1491 standard that describes the bit depth of the LUT values is LUT
1492 Descriptor value 3 and that is (usually) always required to be
1493 either 8 or 16, it mystifies me how the creators' of these images
1494 imagine that the receiver is going to divine the range that is intended. Further, the standard is quite explicit that this 3rd
1495 value defines the range of LUT values, but as far as I am aware, all
1496 the vendors are ignoring the standard and indeed sending a third value
1499 This problem is not confined to CR, and is also seen with DX products.
1501 Typically I have seen:
1503 - Agfa CR, which usually (always ?) sends LUTs, values up to 0x0fff
1504 - Fuji CR, which occasionally send LUTs, values up to 0x03ff
1505 - GE DX, for presentation, which always have LUTs, up to 0x3fff
1507 Swissray, Siemens, Philips, Canon and Kodak never seem to send VOI LUTs
1508 at this point (which is a whole other problem). Note that the presence
1509 or absence of a VOI LUT as opposed to window values may be configurable
1510 on the modality in some cases, and I have just looked at what I happen
1511 to have received from a myriad of sites over whose configuration I have
1512 no control. This may be why the majority of Fuji images have no VOI LUTs,
1513 but a few do (or it may be the Siemens system that these Fuji images went
1514 through that perhaps added it). I do have some test Hologic DX images that
1515 are not from a clinical site that do actually get this right (a value
1516 of 12 for the third value and a max of 0xfff).
1518 Since almost every vendor that I have encountered that encodes LUTs
1519 makes this mistake, perhaps it is time to amend the standard to warn
1520 implementor's of receivers and/or sanction this bad behavior. We have
1521 talked about this in the past in WG 6 but so far everyone has been
1522 reluctant to write into the standard such a comment. Maybe it is time
1523 to try again, since if one is not aware of this problem, one cannot
1524 effectively implement display using VOI LUTs, and there is a vast
1525 installed base to contend with.
1527 I did not check presentation states, in which VOI LUTs could also be
1528 encountered, for the prevalence of this mistake, nor did I look at the
1529 encoding of Modality LUT's, which are unusual. Nor did I check digital
1530 mammography images. I would be interested to hear from anyone who has.
1534 PS. The following older thread in this newsgroup discusses this:
1536 "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"
1538 PPS. From a historical perspective, the following may be of interest.
1540 In the original standard in 1993, all that was said about this was a
1541 reference to the corresponding such where Modality LUTs are described
1544 "The third value specifies the number of bits for each entry in the
1545 LUT Data. It shall take the value 8 or 16. The LUT Data shall be stored
1546 in a format equivalent to 8 or 16 bits allocated and high bit equal
1549 Since the high bit hint was not apparently explicit enough, a very
1550 early CP, CP 15 (submitted by Agfa as it happens), replaced this with:
1552 "The third value conveys the range of LUT entry values. It shall take
1553 the value 8 or 16, corresponding with the LUT entry value range of
1556 Note: The third value is not required for describing the
1557 LUT data and is only included for informational usage
1558 and for maintaining compatibility with ACRNEMA 2.0.
1560 The LUT Data contains the LUT entry values."
1562 That is how it read in the 1996, 1998 and 1999 editions.
1564 By the 2000 edition, Supplement 33 that introduced presentation states
1565 extensively reworked this entire section and tried to explain this in
1568 "The output range is from 0 to 2^n-1 where n is the third value of LUT
1569 Descriptor. This range is always unsigned."
1571 and also added a note to spell out what the output range meant in the
1574 "9. The output of the Window Center/Width or VOI LUT transformation
1575 is either implicitly scaled to the full range of the display device
1576 if there is no succeeding transformation defined, or implicitly scaled
1577 to the full input range of the succeeding transformation step (such as
1578 the Presentation LUT), if present. See C.11.6.1."
1580 It still reads this way in the 2004 edition.
1582 Note that LUTs in other applications than the general VOI LUT allow for
1583 values other than 8 or 16 in the third value of LUT descriptor to permit
1584 ranges other than 0 to 255 or 65535.
1586 In addition, the DX Image Module specializes the VOI LUT
1587 attributes as follows, in PS 3.3 section C.8.11.3.1.5 (added in Sup 32):
1589 "The third value specifies the number of bits for each entry in the LUT
1590 Data (analogous to ìbits storedî). It shall be between 10-16. The LUT
1591 Data shall be stored in a format equivalent to 16 ìbits allocatedî and
1592 ìhigh bitî equal to ìbits storedî - 1. The third value conveys the range
1593 of LUT entry values. These unsigned LUT entry values shall range between
1594 0 and 2^n-1, where n is the third value of the LUT Descriptor."
1596 So in the case of the GE DX for presentation images, the third value of
1597 LUT descriptor is allowed to be and probably should be 14 rather than 16.