1 /*=========================================================================
4 Module: $RCSfile: gdcmPixelReadConvert.cxx,v $
6 Date: $Date: 2006/03/29 16:09:48 $
7 Version: $Revision: 1.111 $
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
89 void PixelReadConvert::GrabInformationsFromFile( File *file,
90 FileHelper *fileHelper )
92 // Number of Bits Allocated for storing a Pixel is defaulted to 16
93 // when absent from the file.
94 BitsAllocated = file->GetBitsAllocated();
95 if ( BitsAllocated == 0 )
100 // Number of "Bits Stored", defaulted to number of "Bits Allocated"
101 // when absent from the file.
102 BitsStored = file->GetBitsStored();
103 if ( BitsStored == 0 )
105 BitsStored = BitsAllocated;
108 // High Bit Position, defaulted to "Bits Allocated" - 1
109 HighBitPosition = file->GetHighBitPosition();
110 if ( HighBitPosition == 0 )
112 HighBitPosition = BitsAllocated - 1;
115 XSize = file->GetXSize();
116 YSize = file->GetYSize();
117 ZSize = file->GetZSize();
118 TSize = file->GetTSize();
119 SamplesPerPixel = file->GetSamplesPerPixel();
120 //PixelSize = file->GetPixelSize(); Useless
121 PixelSign = file->IsSignedPixelData();
122 SwapCode = file->GetSwapCode();
124 IsPrivateGETransferSyntax = IsMPEG
125 = IsJPEG2000 = IsJPEGLS = IsJPEGLossy
126 = IsJPEGLossless = IsRLELossless
129 if (! file->IsDicomV3() ) // Should be ACR-NEMA file
135 std::string ts = file->GetTransferSyntax();
138 while (true) // shorter to write than 'if elseif elseif elseif' ...
140 // mind the order : check the most usual first.
141 if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRLittleEndian) break;
142 if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRLittleEndian ) break;
143 if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRBigEndian) break;
144 if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRBigEndianPrivateGE) break;
145 // DeflatedExplicitVRLittleEndian syntax means the whole Dataset (Header + Pixels) is compressed !
146 // Not dealt with ! (Parser hangs)
147 //if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::DeflatedExplicitVRLittleEndian) break;
150 // cache whether this is a strange GE transfer syntax (which uses
151 // a little endian transfer syntax for the header and a big endian
152 // transfer syntax for the pixel data).
153 IsPrivateGETransferSyntax =
154 ( Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRBigEndianPrivateGE );
156 IsMPEG = IsJPEG2000 = IsJPEGLS = IsJPEGLossy = IsJPEGLossless = IsRLELossless = false;
161 // mind the order : check the most usual first.
162 if( IsJPEGLossy = Global::GetTS()->IsJPEGLossy(ts) ) break;
163 if( IsJPEGLossless = Global::GetTS()->IsJPEGLossless(ts) ) break;
164 if( IsRLELossless = Global::GetTS()->IsRLELossless(ts) ) break;
165 if( IsJPEG2000 = Global::GetTS()->IsJPEG2000(ts) ) break;
166 if( IsMPEG = Global::GetTS()->IsMPEG(ts) ) break;
167 if( IsJPEGLS = Global::GetTS()->IsJPEGLS(ts) ) break;
168 // DeflatedExplicitVRLittleEndian is considered as 'Unexpected' (we don't know yet haow to process !)
169 gdcmWarningMacro("Unexpected Transfer Syntax :[" << ts << "]");
175 PixelOffset = file->GetPixelOffset();
176 PixelDataLength = file->GetPixelAreaLength();
177 RLEInfo = file->GetRLEInfo();
178 JPEGInfo = file->GetJPEGInfo();
180 IsMonochrome = file->IsMonochrome();
181 IsMonochrome1 = file->IsMonochrome1();
182 IsPaletteColor = file->IsPaletteColor();
183 IsYBRFull = file->IsYBRFull();
185 PlanarConfiguration = file->GetPlanarConfiguration();
187 /////////////////////////////////////////////////////////////////
189 HasLUT = file->HasLUT();
192 // Just in case some access to a File element requires disk access.
193 LutRedDescriptor = file->GetEntryString( 0x0028, 0x1101 );
194 LutGreenDescriptor = file->GetEntryString( 0x0028, 0x1102 );
195 LutBlueDescriptor = file->GetEntryString( 0x0028, 0x1103 );
197 // FIXME : The following comment is probabely meaningless, since LUT are *always*
198 // loaded at parsing time, whatever their length is.
200 // Depending on the value of Document::MAX_SIZE_LOAD_ELEMENT_VALUE
201 // [ refer to invocation of Document::SetMaxSizeLoadEntry() in
202 // Document::Document() ], the loading of the value (content) of a
203 // [Bin|Val]Entry occurence migth have been hindered (read simply NOT
204 // loaded). Hence, we first try to obtain the LUTs data from the file
205 // and when this fails we read the LUTs data directly from disk.
206 // \TODO Reading a [Bin|Val]Entry directly from disk is a kludge.
207 // We should NOT bypass the [Bin|Val]Entry class. Instead
208 // an access to an UNLOADED content of a [Bin|Val]Entry occurence
209 // (e.g. DataEntry::GetBinArea()) should force disk access from
210 // within the [Bin|Val]Entry class itself. The only problem
211 // is that the [Bin|Val]Entry is unaware of the FILE* is was
212 // parsed from. Fix that. FIXME.
215 file->LoadEntryBinArea(0x0028, 0x1201);
216 LutRedData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1201 );
219 gdcmWarningMacro("Unable to read Red Palette Color Lookup Table data");
223 file->LoadEntryBinArea(0x0028, 0x1202);
224 LutGreenData = (uint8_t*)file->GetEntryBinArea(0x0028, 0x1202 );
227 gdcmWarningMacro("Unable to read Green Palette Color Lookup Table data");
231 file->LoadEntryBinArea(0x0028, 0x1203);
232 LutBlueData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1203 );
235 gdcmWarningMacro("Unable to read Blue Palette Color Lookup Table data");
240 ComputeRawAndRGBSizes();
243 /// \brief Reads from disk and decompresses Pixels
244 bool PixelReadConvert::ReadAndDecompressPixelData( std::ifstream *fp )
246 // ComputeRawAndRGBSizes is already made by
247 // ::GrabInformationsFromfile. So, the structure sizes are
251 //////////////////////////////////////////////////
252 //// First stage: get our hands on the Pixel Data.
255 gdcmWarningMacro( "Unavailable file pointer." );
259 fp->seekg( PixelOffset, std::ios::beg );
260 if ( fp->fail() || fp->eof() )
262 gdcmWarningMacro( "Unable to find PixelOffset in file." );
268 //////////////////////////////////////////////////
270 CallStartMethod(); // for progress bar
271 unsigned int count = 0;
272 unsigned int frameSize;
273 unsigned int bitsAllocated = BitsAllocated;
274 if(bitsAllocated == 12)
276 frameSize = XSize*YSize*SamplesPerPixel*bitsAllocated/8;
278 //// Second stage: read from disk and decompress.
280 if ( BitsAllocated == 12 ) // We suppose 'BitsAllocated' = 12 only exist for uncompressed files
282 ReadAndDecompress12BitsTo16Bits( fp);
286 // This problem can be found when some obvious informations are found
287 // after the field containing the image data. In this case, these
288 // bad data are added to the size of the image (in the PixelDataLength
289 // variable). But RawSize is the right size of the image !
290 if ( PixelDataLength != RawSize )
292 gdcmWarningMacro( "Mismatch between PixelReadConvert : "
293 << PixelDataLength << " and RawSize : " << RawSize );
296 //todo : is it the right patch?
297 char *raw = (char*)Raw;
298 uint32_t remainingLength;
300 unsigned int lengthToRead;
302 if ( PixelDataLength > RawSize )
303 lengthToRead = RawSize;
305 lengthToRead = PixelDataLength;
307 // perform a frame by frame reading
308 remainingLength = lengthToRead;
309 unsigned int nbFrames = lengthToRead / frameSize;
310 for (i=0;i<nbFrames; i++)
312 Progress = (float)(count+1)/(float)nbFrames;
313 fp->read( raw, frameSize);
315 remainingLength -= frameSize;
318 if (remainingLength !=0 )
319 fp->read( raw, remainingLength);
321 if ( fp->fail() || fp->eof())
323 gdcmWarningMacro( "Reading of Raw pixel data failed." );
327 else if ( IsRLELossless )
329 if ( ! RLEInfo->DecompressRLEFile
330 ( fp, Raw, XSize, YSize, ZSize, TSize, BitsAllocated ) )
332 gdcmWarningMacro( "RLE decompressor failed." );
338 //gdcmWarningMacro( "Sorry, MPEG not yet taken into account" );
340 // fp has already been seek to start of mpeg
341 //ReadMPEGFile(fp, (char*)Raw, PixelDataLength);
346 // Default case concerns JPEG family
347 if ( ! ReadAndDecompressJPEGFile( fp ) )
349 gdcmWarningMacro( "JPEG decompressor ( ReadAndDecompressJPEGFile()"
350 << " method ) failed." );
355 ////////////////////////////////////////////
356 //// Third stage: twigle the bytes and bits.
357 ConvertReorderEndianity();
358 ConvertReArrangeBits();
359 ConvertFixGreyLevels();
360 if (UserFunction) // user is allowed to Mirror, TopDown, Rotate,...the image
361 UserFunction( Raw, FileInternal);
362 ConvertHandleColor();
367 /// Deletes Pixels Area
368 void PixelReadConvert::Squeeze()
384 * \brief Build the RGB image from the Raw image and the LUTs.
386 bool PixelReadConvert::BuildRGBImage()
390 // The job is already done.
396 // The job can't be done
403 // The job can't be done
407 gdcmDebugMacro( "--> BuildRGBImage" );
413 if ( BitsAllocated <= 8 )
415 uint8_t *localRGB = RGB;
416 for (size_t i = 0; i < RawSize; ++i )
419 *localRGB++ = LutRGBA[j];
420 *localRGB++ = LutRGBA[j+1];
421 *localRGB++ = LutRGBA[j+2];
425 else // deal with 16 bits pixels and 16 bits Palette color
427 uint16_t *localRGB = (uint16_t *)RGB;
428 for (size_t i = 0; i < RawSize/2; ++i )
430 j = ((uint16_t *)Raw)[i] * 4;
431 *localRGB++ = ((uint16_t *)LutRGBA)[j];
432 *localRGB++ = ((uint16_t *)LutRGBA)[j+1];
433 *localRGB++ = ((uint16_t *)LutRGBA)[j+2];
440 //-----------------------------------------------------------------------------
443 //-----------------------------------------------------------------------------
446 * \brief Read from file a 12 bits per pixel image and decompress it
447 * into a 16 bits per pixel image.
449 void PixelReadConvert::ReadAndDecompress12BitsTo16Bits( std::ifstream *fp )
450 throw ( FormatError )
452 /// \todo Fix the 3D, 4D pb
453 int nbPixels = XSize * YSize * TSize;
454 uint16_t *localDecompres = (uint16_t*)Raw;
456 for( int p = 0; p < nbPixels; p += 2 )
460 fp->read( (char*)&b0, 1);
461 if ( fp->fail() || fp->eof() )
463 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
464 "Unfound first block" );
467 fp->read( (char*)&b1, 1 );
468 if ( fp->fail() || fp->eof())
470 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
471 "Unfound second block" );
474 fp->read( (char*)&b2, 1 );
475 if ( fp->fail() || fp->eof())
477 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
478 "Unfound second block" );
481 // Two steps are necessary to please VC++
483 // 2 pixels 12bit = [0xABCDEF]
484 // 2 pixels 16bit = [0x0ABD] + [0x0FCE]
486 *localDecompres++ = ((b0 >> 4) << 8) + ((b0 & 0x0f) << 4) + (b1 & 0x0f);
488 *localDecompres++ = ((b2 & 0x0f) << 8) + ((b1 >> 4) << 4) + (b2 >> 4);
490 /// \todo JPR Troubles expected on Big-Endian processors ?
495 * \brief Reads from disk the Pixel Data of JPEG Dicom encapsulated
496 * file and decompress it.
497 * @param fp File Pointer
500 bool PixelReadConvert::ReadAndDecompressJPEGFile( std::ifstream *fp )
504 // make sure this is the right JPEG compression
505 assert( !IsJPEGLossless || !IsJPEGLossy || !IsJPEGLS );
506 // FIXME this is really ugly but it seems I have to load the complete
507 // jpeg2000 stream to use jasper:
508 // I don't think we'll ever be able to deal with multiple fragments properly
510 unsigned long inputlength = 0;
511 JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment();
514 inputlength += jpegfrag->GetLength();
515 jpegfrag = JPEGInfo->GetNextFragment();
517 gdcmAssertMacro( inputlength != 0);
518 uint8_t *inputdata = new uint8_t[inputlength];
519 char *pinputdata = (char*)inputdata;
520 jpegfrag = JPEGInfo->GetFirstFragment();
523 fp->seekg( jpegfrag->GetOffset(), std::ios::beg);
524 fp->read(pinputdata, jpegfrag->GetLength());
525 pinputdata += jpegfrag->GetLength();
526 jpegfrag = JPEGInfo->GetNextFragment();
528 // Warning the inputdata buffer is delete in the function
529 if ( ! gdcm_read_JPEG2000_file( Raw,
530 (char*)inputdata, inputlength ) )
534 // wow what happen, must be an error
535 gdcmWarningMacro( "gdcm_read_JPEG2000_file() failed ");
540 // make sure this is the right JPEG compression
541 assert( !IsJPEGLossless || !IsJPEGLossy || !IsJPEG2000 );
542 // WARNING : JPEG-LS is NOT the 'classical' Jpeg Lossless :
543 // [JPEG-LS is the basis for new lossless/near-lossless compression
544 // standard for continuous-tone images intended for JPEG2000. The standard
545 // is based on the LOCO-I algorithm (LOw COmplexity LOssless COmpression
546 // for Images) developed at Hewlett-Packard Laboratories]
548 // see http://datacompression.info/JPEGLS.shtml
551 std::cerr << "count:" << JPEGInfo->GetFragmentCount() << std::endl;
552 unsigned long inputlength = 0;
553 JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment();
556 inputlength += jpegfrag->GetLength();
557 jpegfrag = JPEGInfo->GetNextFragment();
559 gdcmAssertMacro( inputlength != 0);
560 uint8_t *inputdata = new uint8_t[inputlength];
561 char *pinputdata = (char*)inputdata;
562 jpegfrag = JPEGInfo->GetFirstFragment();
565 fp->seekg( jpegfrag->GetOffset(), std::ios::beg);
566 fp->read(pinputdata, jpegfrag->GetLength());
567 pinputdata += jpegfrag->GetLength();
568 jpegfrag = JPEGInfo->GetNextFragment();
571 //fp->read((char*)Raw, PixelDataLength);
573 std::ofstream out("/tmp/jpegls.jpg");
574 out.write((char*)inputdata, inputlength);
579 gdcmWarningMacro( "Sorry, JPEG-LS not yet taken into account" );
580 fp->seekg( JPEGInfo->GetFirstFragment()->GetOffset(), std::ios::beg);
581 // if ( ! gdcm_read_JPEGLS_file( fp,Raw ) )
586 // make sure this is the right JPEG compression
587 assert( !IsJPEGLS || !IsJPEG2000 );
588 // Precompute the offset localRaw will be shifted with
589 int length = XSize * YSize * ZSize * SamplesPerPixel;
590 int numberBytes = BitsAllocated / 8;
592 JPEGInfo->DecompressFromFile(fp, Raw, BitsStored, numberBytes, length );
598 * \brief Build Red/Green/Blue/Alpha LUT from File when :
599 * - (0028,0004) : Photometric Interpretation == [PALETTE COLOR ]
601 * - (0028,1101),(0028,1102),(0028,1102)
602 * xxx Palette Color Lookup Table Descriptor are found
604 * - (0028,1201),(0028,1202),(0028,1202)
605 * xxx Palette Color Lookup Table Data - are found
606 * \warning does NOT deal with :
607 * - 0028 1100 Gray Lookup Table Descriptor (Retired)
608 * - 0028 1221 Segmented Red Palette Color Lookup Table Data
609 * - 0028 1222 Segmented Green Palette Color Lookup Table Data
610 * - 0028 1223 Segmented Blue Palette Color Lookup Table Data
611 * no known Dicom reader deals with them :-(
612 * @return a RGBA Lookup Table
614 void PixelReadConvert::BuildLUTRGBA()
617 // Note to code reviewers :
618 // The problem is *much more* complicated, since a lot of manufacturers
619 // Don't follow the norm :
620 // have a look at David Clunie's remark at the end of this .cxx file.
627 // http://www.barre.nom.fr/medical/dicom2/limitations.html#Color%20Lookup%20Tables
629 if ( ! IsPaletteColor )
634 if ( LutRedDescriptor == GDCM_UNFOUND
635 || LutGreenDescriptor == GDCM_UNFOUND
636 || LutBlueDescriptor == GDCM_UNFOUND )
638 gdcmWarningMacro( "(At least) a LUT Descriptor is missing" );
642 ////////////////////////////////////////////
643 // Extract the info from the LUT descriptors
644 int lengthR; // Red LUT length in Bytes
645 int debR; // Subscript of the first Lut Value
646 int nbitsR; // Lut item size (in Bits)
647 int nbRead; // nb of items in LUT descriptor (must be = 3)
649 nbRead = sscanf( LutRedDescriptor.c_str(),
651 &lengthR, &debR, &nbitsR );
654 gdcmWarningMacro( "Wrong Red LUT descriptor" );
656 int lengthG; // Green LUT length in Bytes
657 int debG; // Subscript of the first Lut Value
658 int nbitsG; // Lut item size (in Bits)
660 nbRead = sscanf( LutGreenDescriptor.c_str(),
662 &lengthG, &debG, &nbitsG );
665 gdcmWarningMacro( "Wrong Green LUT descriptor" );
668 int lengthB; // Blue LUT length in Bytes
669 int debB; // Subscript of the first Lut Value
670 int nbitsB; // Lut item size (in Bits)
671 nbRead = sscanf( LutRedDescriptor.c_str(),
673 &lengthB, &debB, &nbitsB );
676 gdcmWarningMacro( "Wrong Blue LUT descriptor" );
679 gdcmDebugMacro(" lengthR " << lengthR << " debR "
680 << debR << " nbitsR " << nbitsR);
681 gdcmDebugMacro(" lengthG " << lengthG << " debG "
682 << debG << " nbitsG " << nbitsG);
683 gdcmDebugMacro(" lengthB " << lengthB << " debB "
684 << debB << " nbitsB " << nbitsB);
686 if ( !lengthR ) // if = 2^16, this shall be 0 see : CP-143
688 if ( !lengthG ) // if = 2^16, this shall be 0
690 if ( !lengthB ) // if = 2^16, this shall be 0
693 ////////////////////////////////////////////////////////
695 if ( ( ! LutRedData ) || ( ! LutGreenData ) || ( ! LutBlueData ) )
697 gdcmWarningMacro( "(At least) a LUT is missing" );
701 // -------------------------------------------------------------
703 if ( BitsAllocated <= 8 )
705 // forge the 4 * 8 Bits Red/Green/Blue/Alpha LUT
706 LutRGBA = new uint8_t[ 1024 ]; // 256 * 4 (R, G, B, Alpha)
711 memset( LutRGBA, 0, 1024 );
714 if ( ( nbitsR == 16 ) && ( BitsAllocated == 8 ) )
716 // when LUT item size is different than pixel size
717 mult = 2; // high byte must be = low byte
721 // See PS 3.3-2003 C.11.1.1.2 p 619
725 // if we get a black image, let's just remove the '+1'
726 // from 'i*mult+1' and check again
727 // if it works, we shall have to check the 3 Palettes
728 // to see which byte is ==0 (first one, or second one)
730 // We give up the checking to avoid some (useless ?) overhead
731 // (optimistic asumption)
735 //take "Subscript of the first Lut Value" (debR,debG,debB) into account!
737 //FIXME : +1 : to get 'low value' byte
738 // Trouble expected on Big Endian Processors ?
739 // 16 BIts Per Pixel Palette Color to be swapped?
741 a = LutRGBA + 0 + debR;
742 for( i=0; i < lengthR; ++i )
744 *a = LutRedData[i*mult+1];
748 a = LutRGBA + 1 + debG;
749 for( i=0; i < lengthG; ++i)
751 *a = LutGreenData[i*mult+1];
755 a = LutRGBA + 2 + debB;
756 for(i=0; i < lengthB; ++i)
758 *a = LutBlueData[i*mult+1];
763 for(i=0; i < 256; ++i)
765 *a = 1; // Alpha component
771 // Probabely the same stuff is to be done for 16 Bits Pixels
772 // with 65536 entries LUT ?!?
773 // Still looking for accurate info on the web :-(
775 gdcmWarningMacro( "Sorry Palette Color Lookup Tables not yet dealt with"
776 << " for 16 Bits Per Pixel images" );
778 // forge the 4 * 16 Bits Red/Green/Blue/Alpha LUT
780 LutRGBA = (uint8_t *)new uint16_t[ 65536*4 ]; // 2^16 * 4 (R, G, B, Alpha)
783 memset( LutRGBA, 0, 65536*4*2 ); // 16 bits = 2 bytes ;-)
785 LutItemNumber = 65536;
791 //take "Subscript of the first Lut Value" (debR,debG,debB) into account!
793 a16 = (uint16_t*)LutRGBA + 0 + debR;
794 for( i=0; i < lengthR; ++i )
796 *a16 = ((uint16_t*)LutRedData)[i];
800 a16 = (uint16_t*)LutRGBA + 1 + debG;
801 for( i=0; i < lengthG; ++i)
803 *a16 = ((uint16_t*)LutGreenData)[i];
807 a16 = (uint16_t*)LutRGBA + 2 + debB;
808 for(i=0; i < lengthB; ++i)
810 *a16 = ((uint16_t*)LutBlueData)[i];
814 a16 = (uint16_t*)LutRGBA + 3 ;
815 for(i=0; i < 65536; ++i)
817 *a16 = 1; // Alpha component
820 /* Just to 'see' the LUT, at debug time
821 // Don't remove this commented out code.
823 a16=(uint16_t*)LutRGBA;
824 for (int j=0;j<65536;j++)
826 std::cout << *a16 << " " << *(a16+1) << " "
827 << *(a16+2) << " " << *(a16+3) << std::endl;
835 * \brief Swap the bytes, according to \ref SwapCode.
837 void PixelReadConvert::ConvertSwapZone()
841 // If this file is 'ImplicitVR BigEndian PrivateGE Transfer Syntax',
842 // then the header is in little endian format and the pixel data is in
843 // big endian format. When reading the header, GDCM has already established
844 // a byte swapping code suitable for this machine to read the
845 // header. In TS::ImplicitVRBigEndianPrivateGE, this code will need
846 // to be switched in order to read the pixel data. This must be
847 // done REGARDLESS of the processor endianess!
849 // Example: Assume we are on a little endian machine. When
850 // GDCM reads the header, the header will match the machine
851 // endianess and the swap code will be established as a no-op.
852 // When GDCM reaches the pixel data, it will need to switch the
853 // swap code to do big endian to little endian conversion.
855 // Now, assume we are on a big endian machine. When GDCM reads the
856 // header, the header will be recognized as a different endianess
857 // than the machine endianess, and a swap code will be established
858 // to convert from little endian to big endian. When GDCM readers
859 // the pixel data, the pixel data endianess will now match the
860 // machine endianess. But we currently have a swap code that
861 // converts from little endian to big endian. In this case, we
862 // need to switch the swap code to a no-op.
864 // Therefore, in either case, if the file is in
865 // 'ImplicitVR BigEndian PrivateGE Transfer Syntax', then GDCM needs to switch
866 // the byte swapping code when entering the pixel data.
868 int tempSwapCode = SwapCode;
869 if ( IsPrivateGETransferSyntax )
871 gdcmWarningMacro(" IsPrivateGETransferSyntax found; turn the SwapCode");
872 // PrivateGETransferSyntax only exists for 'true' Dicom images
873 // we assume there is no 'exotic' 32 bits endianess!
874 if (SwapCode == 1234)
878 else if (SwapCode == 4321)
884 if ( BitsAllocated == 16 )
886 uint16_t *im16 = (uint16_t*)Raw;
887 switch( tempSwapCode )
894 for( i = 0; i < RawSize / 2; i++ )
896 im16[i]= (im16[i] >> 8) | (im16[i] << 8 );
900 gdcmWarningMacro("SwapCode value (16 bits) not allowed."
904 else if ( BitsAllocated == 32 )
909 uint32_t *im32 = (uint32_t*)Raw;
910 switch ( tempSwapCode )
915 for( i = 0; i < RawSize / 4; i++ )
917 low = im32[i] & 0x0000ffff; // 4321
918 high = im32[i] >> 16;
919 high = ( high >> 8 ) | ( high << 8 );
920 low = ( low >> 8 ) | ( low << 8 );
922 im32[i] = ( s32 << 16 ) | high;
926 for( i = 0; i < RawSize / 4; i++ )
928 low = im32[i] & 0x0000ffff; // 2143
929 high = im32[i] >> 16;
930 high = ( high >> 8 ) | ( high << 8 );
931 low = ( low >> 8 ) | ( low << 8 );
933 im32[i] = ( s32 << 16 ) | low;
937 for( i = 0; i < RawSize / 4; i++ )
939 low = im32[i] & 0x0000ffff; // 3412
940 high = im32[i] >> 16;
942 im32[i] = ( s32 << 16 ) | high;
946 gdcmWarningMacro("SwapCode value (32 bits) not allowed." << tempSwapCode );
952 * \brief Deal with endianness i.e. re-arange bytes inside the integer
954 void PixelReadConvert::ConvertReorderEndianity()
956 if ( BitsAllocated != 8 )
961 // Special kludge in order to deal with xmedcon broken images:
962 if ( BitsAllocated == 16
963 && BitsStored < BitsAllocated
966 int l = (int)( RawSize / ( BitsAllocated / 8 ) );
967 uint16_t *deb = (uint16_t *)Raw;
968 for(int i = 0; i<l; i++)
970 if ( *deb == 0xffff )
980 * \brief Deal with Grey levels i.e. re-arange them
981 * to have low values = dark, high values = bright
983 void PixelReadConvert::ConvertFixGreyLevels()
988 uint32_t i; // to please M$VC6
993 if ( BitsAllocated == 8 )
995 uint8_t *deb = (uint8_t *)Raw;
996 for (i=0; i<RawSize; i++)
1004 if ( BitsAllocated == 16 )
1007 for (j=0; j<BitsStored-1; j++)
1009 mask = (mask << 1) +1; // will be fff when BitsStored=12
1012 uint16_t *deb = (uint16_t *)Raw;
1013 for (i=0; i<RawSize/2; i++)
1023 if ( BitsAllocated == 8 )
1025 uint8_t smask8 = 255;
1026 uint8_t *deb = (uint8_t *)Raw;
1027 for (i=0; i<RawSize; i++)
1029 *deb = smask8 - *deb;
1034 if ( BitsAllocated == 16 )
1036 uint16_t smask16 = 65535;
1037 uint16_t *deb = (uint16_t *)Raw;
1038 for (i=0; i<RawSize/2; i++)
1040 *deb = smask16 - *deb;
1049 * \brief Re-arrange the bits within the bytes.
1050 * @return Boolean always true
1052 bool PixelReadConvert::ConvertReArrangeBits() throw ( FormatError )
1055 if ( BitsStored != BitsAllocated )
1057 int l = (int)( RawSize / ( BitsAllocated / 8 ) );
1058 if ( BitsAllocated == 16 )
1060 // pmask : to mask the 'unused bits' (may contain overlays)
1061 uint16_t pmask = 0xffff;
1062 pmask = pmask >> ( BitsAllocated - BitsStored );
1064 uint16_t *deb = (uint16_t*)Raw;
1066 if ( !PixelSign ) // Pixels are unsigned
1068 for(int i = 0; i<l; i++)
1070 *deb = (*deb >> (BitsStored - HighBitPosition - 1)) & pmask;
1074 else // Pixels are signed
1076 // smask : to check the 'sign' when BitsStored != BitsAllocated
1077 uint16_t smask = 0x0001;
1078 smask = smask << ( 16 - (BitsAllocated - BitsStored + 1) );
1079 // nmask : to propagate sign bit on negative values
1080 int16_t nmask = (int16_t)0x8000;
1081 nmask = nmask >> ( BitsAllocated - BitsStored - 1 );
1083 for(int i = 0; i<l; i++)
1085 *deb = *deb >> (BitsStored - HighBitPosition - 1);
1088 *deb = *deb | nmask;
1092 *deb = *deb & pmask;
1098 else if ( BitsAllocated == 32 )
1100 // pmask : to mask the 'unused bits' (may contain overlays)
1101 uint32_t pmask = 0xffffffff;
1102 pmask = pmask >> ( BitsAllocated - BitsStored );
1104 uint32_t *deb = (uint32_t*)Raw;
1108 for(int i = 0; i<l; i++)
1110 *deb = (*deb >> (BitsStored - HighBitPosition - 1)) & pmask;
1116 // smask : to check the 'sign' when BitsStored != BitsAllocated
1117 uint32_t smask = 0x00000001;
1118 smask = smask >> ( 32 - (BitsAllocated - BitsStored +1 ));
1119 // nmask : to propagate sign bit on negative values
1120 int32_t nmask = 0x80000000;
1121 nmask = nmask >> ( BitsAllocated - BitsStored -1 );
1123 for(int i = 0; i<l; i++)
1125 *deb = *deb >> (BitsStored - HighBitPosition - 1);
1127 *deb = *deb | nmask;
1129 *deb = *deb & pmask;
1136 gdcmWarningMacro("Weird image (BitsAllocated !=8, 12, 16, 32)");
1137 throw FormatError( "Weird image !?" );
1144 * \brief Convert (Red plane, Green plane, Blue plane) to RGB pixels
1145 * \warning Works on all the frames at a time
1147 void PixelReadConvert::ConvertRGBPlanesToRGBPixels()
1149 gdcmWarningMacro("--> ConvertRGBPlanesToRGBPixels");
1151 uint8_t *localRaw = Raw;
1152 uint8_t *copyRaw = new uint8_t[ RawSize ];
1153 memmove( copyRaw, localRaw, RawSize );
1155 int l = XSize * YSize * ZSize;
1157 uint8_t *a = copyRaw;
1158 uint8_t *b = copyRaw + l;
1159 uint8_t *c = copyRaw + l + l;
1161 for (int j = 0; j < l; j++)
1163 *(localRaw++) = *(a++);
1164 *(localRaw++) = *(b++);
1165 *(localRaw++) = *(c++);
1171 * \brief Convert (cY plane, cB plane, cR plane) to RGB pixels
1172 * \warning Works on all the frames at a time
1174 void PixelReadConvert::ConvertYcBcRPlanesToRGBPixels()
1176 // Remarks for YBR newbees :
1177 // YBR_FULL works very much like RGB, i.e. three samples per pixel,
1178 // just the color space is YCbCr instead of RGB. This is particularly useful
1179 // for doppler ultrasound where most of the image is grayscale
1180 // (i.e. only populates the Y components) and Cb and Cr are mostly zero,
1181 // except for the few patches of color on the image.
1182 // On such images, RLE achieves a compression ratio that is much better
1183 // than the compression ratio on an equivalent RGB image.
1185 gdcmWarningMacro("--> ConvertYcBcRPlanesToRGBPixels");
1187 uint8_t *localRaw = Raw;
1188 uint8_t *copyRaw = new uint8_t[ RawSize ];
1189 memmove( copyRaw, localRaw, RawSize );
1191 // to see the tricks about YBR_FULL, YBR_FULL_422,
1192 // YBR_PARTIAL_422, YBR_ICT, YBR_RCT have a look at :
1193 // ftp://medical.nema.org/medical/dicom/final/sup61_ft.pdf
1194 // and be *very* affraid
1197 /// \todo : find an example to see how 3rd dim and 4th dim work together
1198 int l = XSize * YSize * TSize;
1199 int nbFrames = ZSize;
1201 uint8_t *a = copyRaw + 0;
1202 uint8_t *b = copyRaw + l;
1203 uint8_t *c = copyRaw + l+ l;
1206 /// We replaced easy to understand but time consuming floating point
1207 /// computations by the 'well known' integer computation counterpart
1209 /// http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf
1210 /// for code optimisation.
1212 for ( int i = 0; i < nbFrames; i++ )
1214 for ( int j = 0; j < l; j++ )
1216 R = 38142 *(*a-16) + 52298 *(*c -128);
1217 G = 38142 *(*a-16) - 26640 *(*c -128) - 12845 *(*b -128);
1218 B = 38142 *(*a-16) + 66093 *(*b -128);
1227 if (R > 255) R = 255;
1228 if (G > 255) G = 255;
1229 if (B > 255) B = 255;
1231 *(localRaw++) = (uint8_t)R;
1232 *(localRaw++) = (uint8_t)G;
1233 *(localRaw++) = (uint8_t)B;
1242 /// \brief Deals with the color decoding i.e. handle:
1243 /// - R, G, B planes (as opposed to RGB pixels)
1244 /// - YBR (various) encodings.
1245 /// - LUT[s] (or "PALETTE COLOR").
1247 void PixelReadConvert::ConvertHandleColor()
1249 //////////////////////////////////
1250 // Deal with the color decoding i.e. handle:
1251 // - R, G, B planes (as opposed to RGB pixels)
1252 // - YBR (various) encodings.
1253 // - LUT[s] (or "PALETTE COLOR").
1255 // The classification in the color decoding schema is based on the blending
1256 // of two Dicom tags values:
1257 // * "Photometric Interpretation" for which we have the cases:
1258 // - [Photo A] MONOCHROME[1|2] pictures,
1259 // - [Photo B] RGB or YBR_FULL_422 (which acts as RGB),
1260 // - [Photo C] YBR_* (with the above exception of YBR_FULL_422)
1261 // - [Photo D] "PALETTE COLOR" which indicates the presence of LUT[s].
1262 // * "Planar Configuration" for which we have the cases:
1263 // - [Planar 0] 0 then Pixels are already RGB
1264 // - [Planar 1] 1 then we have 3 planes : R, G, B,
1265 // - [Planar 2] 2 then we have 1 gray Plane and 3 LUTs
1267 // Now in theory, one could expect some coherence when blending the above
1268 // cases. For example we should not encounter files belonging at the
1269 // time to case [Planar 0] and case [Photo D].
1270 // Alas, this was only theory ! Because in practice some odd (read ill
1271 // formated Dicom) files (e.g. gdcmData/US-PAL-8-10x-echo.dcm) we encounter:
1272 // - "Planar Configuration" = 0,
1273 // - "Photometric Interpretation" = "PALETTE COLOR".
1274 // Hence gdcm will use the folowing "heuristic" in order to be tolerant
1275 // towards Dicom-non-conformant files:
1276 // << whatever the "Planar Configuration" value might be, a
1277 // "Photometric Interpretation" set to "PALETTE COLOR" forces
1278 // a LUT intervention >>
1280 // Now we are left with the following handling of the cases:
1281 // - [Planar 0] OR [Photo A] no color decoding (since respectively
1282 // Pixels are already RGB and monochrome pictures have no color :),
1283 // - [Planar 1] AND [Photo B] handled with ConvertRGBPlanesToRGBPixels()
1284 // - [Planar 1] AND [Photo C] handled with ConvertYcBcRPlanesToRGBPixels()
1285 // - [Planar 2] OR [Photo D] requires LUT intervention.
1287 gdcmDebugMacro("--> ConvertHandleColor "
1288 << "Planar Configuration " << PlanarConfiguration );
1292 // [Planar 2] OR [Photo D]: LUT intervention done outside
1293 gdcmDebugMacro("--> RawRGB : LUT intervention done outside");
1297 if ( PlanarConfiguration == 1 )
1301 // [Planar 1] AND [Photo C] (remember YBR_FULL_422 acts as RGB)
1302 gdcmDebugMacro("--> YBRFull");
1303 ConvertYcBcRPlanesToRGBPixels();
1307 // [Planar 1] AND [Photo C]
1308 gdcmDebugMacro("--> YBRFull");
1309 ConvertRGBPlanesToRGBPixels();
1314 // When planarConf is 0, and RLELossless (forbidden by Dicom norm)
1315 // pixels need to be RGB-fyied anyway
1319 gdcmDebugMacro("--> RLE Lossless");
1320 ConvertRGBPlanesToRGBPixels();
1323 // In *normal *case, when planarConf is 0, pixels are already in RGB
1326 /// Computes the Pixels Size
1327 void PixelReadConvert::ComputeRawAndRGBSizes()
1329 int bitsAllocated = BitsAllocated;
1330 // Number of "Bits Allocated" is fixed to 16 when it's 12, since
1331 // in this case we will expand the image to 16 bits (see
1332 // \ref ReadAndDecompress12BitsTo16Bits() )
1333 if ( BitsAllocated == 12 )
1338 RawSize = XSize * YSize * ZSize * TSize
1339 * ( bitsAllocated / 8 )
1343 RGBSize = 3 * RawSize; // works for 8 and 16 bits per Pixel
1351 /// Allocates room for RGB Pixels
1352 void PixelReadConvert::AllocateRGB()
1356 RGB = new uint8_t[RGBSize];
1359 /// Allocates room for RAW Pixels
1360 void PixelReadConvert::AllocateRaw()
1364 Raw = new uint8_t[RawSize];
1367 //-----------------------------------------------------------------------------
1370 * \brief Print self.
1371 * @param indent Indentation string to be prepended during printing.
1372 * @param os Stream to print to.
1374 void PixelReadConvert::Print( std::ostream &os, std::string const &indent )
1377 << "--- Pixel information -------------------------"
1380 << "Pixel Data: offset " << PixelOffset
1381 << " x(" << std::hex << PixelOffset << std::dec
1382 << ") length " << PixelDataLength
1383 << " x(" << std::hex << PixelDataLength << std::dec
1384 << ")" << std::endl;
1386 if ( IsRLELossless )
1390 RLEInfo->Print( os, indent );
1394 gdcmWarningMacro("Set as RLE file but NO RLEinfo present.");
1398 if ( IsJPEG2000 || IsJPEGLossless || IsJPEGLossy || IsJPEGLS )
1402 JPEGInfo->Print( os, indent );
1406 gdcmWarningMacro("Set as JPEG file but NO JPEGinfo present.");
1412 * \brief CallStartMethod
1414 void PixelReadConvert::CallStartMethod()
1418 CommandManager::ExecuteCommand(FH,CMD_STARTPROGRESS);
1422 * \brief CallProgressMethod
1424 void PixelReadConvert::CallProgressMethod()
1426 CommandManager::ExecuteCommand(FH,CMD_PROGRESS);
1430 * \brief CallEndMethod
1432 void PixelReadConvert::CallEndMethod()
1435 CommandManager::ExecuteCommand(FH,CMD_ENDPROGRESS);
1439 //-----------------------------------------------------------------------------
1440 } // end namespace gdcm
1442 // Note to developpers :
1443 // Here is a very detailled post from David Clunie, on the troubles caused
1444 // 'non standard' LUT and LUT description
1445 // We shall have to take it into accound in our code.
1450 Subject: Problem with VOI LUTs in Agfa and Fuji CR and GE DX images, was Re: VOI LUT issues
1451 Date: Sun, 06 Feb 2005 17:13:40 GMT
1452 From: David Clunie <dclunie@dclunie.com>
1453 Reply-To: dclunie@dclunie.com
1454 Newsgroups: comp.protocols.dicom
1455 References: <1107553502.040221.189550@o13g2000cwo.googlegroups.com>
1457 > THE LUT that comes with [my] image claims to be 16-bit, but none of the
1458 > values goes higher than 4095. That being said, though, none of my
1459 > original pixel values goes higher than that, either. I have read
1460 > elsewhere on this group that when that happens you are supposed to
1461 > adjust the LUT. Can someone be more specific? There was a thread from
1462 > 2002 where Marco and David were mentioning doing precisely that.
1469 You have encountered the well known "we know what the standard says but
1470 we are going to ignore it and do what we have been doing for almost
1471 a decade regardless" CR vendor bug. Agfa started this, but they are not
1472 the only vendor doing this now; GE and Fuji may have joined the club.
1474 Sadly, one needs to look at the LUT Data, figure out what the maximum
1475 value actually encoded is, and find the next highest power of 2 (e.g.
1476 212 in this case), to figure out what the range of the data is
1477 supposed to be. I have assumed that if the maximum value in the LUT
1478 data is less than a power of 2 minus 1 (e.g. 0xebc) then the intent
1479 of the vendor was not to use the maximum available grayscale range
1480 of the display (e.g. the maximum is 0xfff in this case). An alternative
1481 would be to scale to the actual maximum rather than a power of two.
1483 Very irritating, and in theory not totally reliable if one really
1484 intended the full 16 bits and only used, say 15, but that is extremely
1485 unlikely since everything would be too dark, and this heuristic
1488 There has never been anything in the standard that describes having
1489 to go through these convolutions. Since the only value in the
1490 standard that describes the bit depth of the LUT values is LUT
1491 Descriptor value 3 and that is (usually) always required to be
1492 either 8 or 16, it mystifies me how the creators' of these images
1493 imagine that the receiver is going to divine the range that is intended. Further, the standard is quite explicit that this 3rd
1494 value defines the range of LUT values, but as far as I am aware, all
1495 the vendors are ignoring the standard and indeed sending a third value
1498 This problem is not confined to CR, and is also seen with DX products.
1500 Typically I have seen:
1502 - Agfa CR, which usually (always ?) sends LUTs, values up to 0x0fff
1503 - Fuji CR, which occasionally send LUTs, values up to 0x03ff
1504 - GE DX, for presentation, which always have LUTs, up to 0x3fff
1506 Swissray, Siemens, Philips, Canon and Kodak never seem to send VOI LUTs
1507 at this point (which is a whole other problem). Note that the presence
1508 or absence of a VOI LUT as opposed to window values may be configurable
1509 on the modality in some cases, and I have just looked at what I happen
1510 to have received from a myriad of sites over whose configuration I have
1511 no control. This may be why the majority of Fuji images have no VOI LUTs,
1512 but a few do (or it may be the Siemens system that these Fuji images went
1513 through that perhaps added it). I do have some test Hologic DX images that
1514 are not from a clinical site that do actually get this right (a value
1515 of 12 for the third value and a max of 0xfff).
1517 Since almost every vendor that I have encountered that encodes LUTs
1518 makes this mistake, perhaps it is time to amend the standard to warn
1519 implementor's of receivers and/or sanction this bad behavior. We have
1520 talked about this in the past in WG 6 but so far everyone has been
1521 reluctant to write into the standard such a comment. Maybe it is time
1522 to try again, since if one is not aware of this problem, one cannot
1523 effectively implement display using VOI LUTs, and there is a vast
1524 installed base to contend with.
1526 I did not check presentation states, in which VOI LUTs could also be
1527 encountered, for the prevalence of this mistake, nor did I look at the
1528 encoding of Modality LUT's, which are unusual. Nor did I check digital
1529 mammography images. I would be interested to hear from anyone who has.
1533 PS. The following older thread in this newsgroup discusses this:
1535 "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"
1537 PPS. From a historical perspective, the following may be of interest.
1539 In the original standard in 1993, all that was said about this was a
1540 reference to the corresponding such where Modality LUTs are described
1543 "The third value specifies the number of bits for each entry in the
1544 LUT Data. It shall take the value 8 or 16. The LUT Data shall be stored
1545 in a format equivalent to 8 or 16 bits allocated and high bit equal
1548 Since the high bit hint was not apparently explicit enough, a very
1549 early CP, CP 15 (submitted by Agfa as it happens), replaced this with:
1551 "The third value conveys the range of LUT entry values. It shall take
1552 the value 8 or 16, corresponding with the LUT entry value range of
1555 Note: The third value is not required for describing the
1556 LUT data and is only included for informational usage
1557 and for maintaining compatibility with ACRNEMA 2.0.
1559 The LUT Data contains the LUT entry values."
1561 That is how it read in the 1996, 1998 and 1999 editions.
1563 By the 2000 edition, Supplement 33 that introduced presentation states
1564 extensively reworked this entire section and tried to explain this in
1567 "The output range is from 0 to 2^n-1 where n is the third value of LUT
1568 Descriptor. This range is always unsigned."
1570 and also added a note to spell out what the output range meant in the
1573 "9. The output of the Window Center/Width or VOI LUT transformation
1574 is either implicitly scaled to the full range of the display device
1575 if there is no succeeding transformation defined, or implicitly scaled
1576 to the full input range of the succeeding transformation step (such as
1577 the Presentation LUT), if present. See C.11.6.1."
1579 It still reads this way in the 2004 edition.
1581 Note that LUTs in other applications than the general VOI LUT allow for
1582 values other than 8 or 16 in the third value of LUT descriptor to permit
1583 ranges other than 0 to 255 or 65535.
1585 In addition, the DX Image Module specializes the VOI LUT
1586 attributes as follows, in PS 3.3 section C.8.11.3.1.5 (added in Sup 32):
1588 "The third value specifies the number of bits for each entry in the LUT
1589 Data (analogous to ìbits storedî). It shall be between 10-16. The LUT
1590 Data shall be stored in a format equivalent to 16 ìbits allocatedî and
1591 ìhigh bitî equal to ìbits storedî - 1. The third value conveys the range
1592 of LUT entry values. These unsigned LUT entry values shall range between
1593 0 and 2^n-1, where n is the third value of the LUT Descriptor."
1595 So in the case of the GE DX for presentation images, the third value of
1596 LUT descriptor is allowed to be and probably should be 14 rather than 16.