1 /*=========================================================================
4 Module: $RCSfile: gdcmPixelReadConvert.cxx,v $
6 Date: $Date: 2006/01/27 10:01:34 $
7 Version: $Revision: 1.109 $
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 SamplesPerPixel = file->GetSamplesPerPixel();
119 //PixelSize = file->GetPixelSize(); Useless
120 PixelSign = file->IsSignedPixelData();
121 SwapCode = file->GetSwapCode();
123 IsPrivateGETransferSyntax = IsMPEG
124 = IsJPEG2000 = IsJPEGLS = IsJPEGLossy
125 = IsJPEGLossless = IsRLELossless
128 if (! file->IsDicomV3() ) // Should be ACR-NEMA file
134 std::string ts = file->GetTransferSyntax();
137 while (true) // shorter to write than 'if elseif elseif elseif' ...
139 // mind the order : check the most usual first.
140 if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRLittleEndian) break;
141 if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRLittleEndian ) break;
142 if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRBigEndian) break;
143 if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRBigEndianPrivateGE) break;
144 // DeflatedExplicitVRLittleEndian syntax means the whole Dataset (Header + Pixels) is compressed !
145 // Not dealt with ! (Parser hangs)
146 //if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::DeflatedExplicitVRLittleEndian) break;
149 // cache whether this is a strange GE transfer syntax (which uses
150 // a little endian transfer syntax for the header and a big endian
151 // transfer syntax for the pixel data).
152 IsPrivateGETransferSyntax =
153 ( Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRBigEndianPrivateGE );
155 IsMPEG = IsJPEG2000 = IsJPEGLS = IsJPEGLossy = IsJPEGLossless = IsRLELossless = false;
160 // mind the order : check the most usual first.
161 if( IsJPEGLossy = Global::GetTS()->IsJPEGLossy(ts) ) break;
162 if( IsJPEGLossless = Global::GetTS()->IsJPEGLossless(ts) ) break;
163 if( IsRLELossless = Global::GetTS()->IsRLELossless(ts) ) break;
164 if( IsJPEG2000 = Global::GetTS()->IsJPEG2000(ts) ) break;
165 if( IsMPEG = Global::GetTS()->IsMPEG(ts) ) break;
166 if( IsJPEGLS = Global::GetTS()->IsJPEGLS(ts) ) break;
167 // DeflatedExplicitVRLittleEndian is considered as 'Unexpected' (we don't know yet haow to process !)
168 gdcmWarningMacro("Unexpected Transfer Syntax :[" << ts << "]");
174 PixelOffset = file->GetPixelOffset();
175 PixelDataLength = file->GetPixelAreaLength();
176 RLEInfo = file->GetRLEInfo();
177 JPEGInfo = file->GetJPEGInfo();
179 IsMonochrome = file->IsMonochrome();
180 IsMonochrome1 = file->IsMonochrome1();
181 IsPaletteColor = file->IsPaletteColor();
182 IsYBRFull = file->IsYBRFull();
184 PlanarConfiguration = file->GetPlanarConfiguration();
186 /////////////////////////////////////////////////////////////////
188 HasLUT = file->HasLUT();
191 // Just in case some access to a File element requires disk access.
192 LutRedDescriptor = file->GetEntryString( 0x0028, 0x1101 );
193 LutGreenDescriptor = file->GetEntryString( 0x0028, 0x1102 );
194 LutBlueDescriptor = file->GetEntryString( 0x0028, 0x1103 );
196 // FIXME : The following comment is probabely meaningless, since LUT are *always*
197 // loaded at parsing time, whatever their length is.
199 // Depending on the value of Document::MAX_SIZE_LOAD_ELEMENT_VALUE
200 // [ refer to invocation of Document::SetMaxSizeLoadEntry() in
201 // Document::Document() ], the loading of the value (content) of a
202 // [Bin|Val]Entry occurence migth have been hindered (read simply NOT
203 // loaded). Hence, we first try to obtain the LUTs data from the file
204 // and when this fails we read the LUTs data directly from disk.
205 // \TODO Reading a [Bin|Val]Entry directly from disk is a kludge.
206 // We should NOT bypass the [Bin|Val]Entry class. Instead
207 // an access to an UNLOADED content of a [Bin|Val]Entry occurence
208 // (e.g. DataEntry::GetBinArea()) should force disk access from
209 // within the [Bin|Val]Entry class itself. The only problem
210 // is that the [Bin|Val]Entry is unaware of the FILE* is was
211 // parsed from. Fix that. FIXME.
214 file->LoadEntryBinArea(0x0028, 0x1201);
215 LutRedData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1201 );
218 gdcmWarningMacro("Unable to read Red Palette Color Lookup Table data");
222 file->LoadEntryBinArea(0x0028, 0x1202);
223 LutGreenData = (uint8_t*)file->GetEntryBinArea(0x0028, 0x1202 );
226 gdcmWarningMacro("Unable to read Green Palette Color Lookup Table data");
230 file->LoadEntryBinArea(0x0028, 0x1203);
231 LutBlueData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1203 );
234 gdcmWarningMacro("Unable to read Blue Palette Color Lookup Table data");
239 ComputeRawAndRGBSizes();
242 /// \brief Reads from disk and decompresses Pixels
243 bool PixelReadConvert::ReadAndDecompressPixelData( std::ifstream *fp )
245 // ComputeRawAndRGBSizes is already made by
246 // ::GrabInformationsFromfile. So, the structure sizes are
250 //////////////////////////////////////////////////
251 //// First stage: get our hands on the Pixel Data.
254 gdcmWarningMacro( "Unavailable file pointer." );
258 fp->seekg( PixelOffset, std::ios::beg );
259 if ( fp->fail() || fp->eof() )
261 gdcmWarningMacro( "Unable to find PixelOffset in file." );
267 //////////////////////////////////////////////////
269 CallStartMethod(); // for progress bar
270 unsigned int count = 0;
271 unsigned int frameSize;
272 unsigned int bitsAllocated = BitsAllocated;
273 if(bitsAllocated == 12)
275 frameSize = XSize*YSize*SamplesPerPixel*bitsAllocated/8;
277 //// Second stage: read from disk and decompress.
279 if ( BitsAllocated == 12 ) // We suppose 'BitsAllocated' = 12 only exist for uncompressed files
281 ReadAndDecompress12BitsTo16Bits( fp);
285 // This problem can be found when some obvious informations are found
286 // after the field containing the image data. In this case, these
287 // bad data are added to the size of the image (in the PixelDataLength
288 // variable). But RawSize is the right size of the image !
289 if ( PixelDataLength != RawSize )
291 gdcmWarningMacro( "Mismatch between PixelReadConvert : "
292 << PixelDataLength << " and RawSize : " << RawSize );
295 //todo : is it the right patch?
296 char *raw = (char*)Raw;
297 uint32_t remainingLength;
299 unsigned int lengthToRead;
301 if ( PixelDataLength > RawSize )
302 lengthToRead = RawSize;
304 lengthToRead = PixelDataLength;
306 // perform a frame by frame reading
307 remainingLength = lengthToRead;
308 unsigned int nbFrames = lengthToRead / frameSize;
309 for (i=0;i<nbFrames; i++)
311 Progress = (float)(count+1)/(float)nbFrames;
312 fp->read( raw, frameSize);
314 remainingLength -= frameSize;
317 if (remainingLength !=0 )
318 fp->read( raw, remainingLength);
320 //if ( PixelDataLength > RawSize )
322 // fp->read( (char*)Raw, RawSize); // Read all the frames with a single fread
326 // fp->read( (char*)Raw, PixelDataLength); // Read all the frames with a single fread
329 if ( fp->fail() || fp->eof())
331 gdcmWarningMacro( "Reading of Raw pixel data failed." );
335 else if ( IsRLELossless )
337 if ( ! RLEInfo->DecompressRLEFile
338 ( fp, Raw, XSize, YSize, ZSize, BitsAllocated ) )
340 gdcmWarningMacro( "RLE decompressor failed." );
346 //gdcmWarningMacro( "Sorry, MPEG not yet taken into account" );
348 // fp has already been seek to start of mpeg
349 //ReadMPEGFile(fp, (char*)Raw, PixelDataLength);
354 // Default case concerns JPEG family
355 if ( ! ReadAndDecompressJPEGFile( fp ) )
357 gdcmWarningMacro( "JPEG decompressor ( ReadAndDecompressJPEGFile()"
358 << " method ) failed." );
363 ////////////////////////////////////////////
364 //// Third stage: twigle the bytes and bits.
365 ConvertReorderEndianity();
366 ConvertReArrangeBits();
367 ConvertFixGreyLevels();
368 if (UserFunction) // user is allowed to Mirror, TopDown, Rotate,...the image
369 UserFunction( Raw, FileInternal);
370 ConvertHandleColor();
375 /// Deletes Pixels Area
376 void PixelReadConvert::Squeeze()
392 * \brief Build the RGB image from the Raw image and the LUTs.
394 bool PixelReadConvert::BuildRGBImage()
398 // The job is already done.
404 // The job can't be done
411 // The job can't be done
415 gdcmDebugMacro( "--> BuildRGBImage" );
421 if ( BitsAllocated <= 8 )
423 uint8_t *localRGB = RGB;
424 for (size_t i = 0; i < RawSize; ++i )
427 *localRGB++ = LutRGBA[j];
428 *localRGB++ = LutRGBA[j+1];
429 *localRGB++ = LutRGBA[j+2];
433 else // deal with 16 bits pixels and 16 bits Palette color
435 uint16_t *localRGB = (uint16_t *)RGB;
436 for (size_t i = 0; i < RawSize/2; ++i )
438 j = ((uint16_t *)Raw)[i] * 4;
439 *localRGB++ = ((uint16_t *)LutRGBA)[j];
440 *localRGB++ = ((uint16_t *)LutRGBA)[j+1];
441 *localRGB++ = ((uint16_t *)LutRGBA)[j+2];
448 //-----------------------------------------------------------------------------
451 //-----------------------------------------------------------------------------
454 * \brief Read from file a 12 bits per pixel image and decompress it
455 * into a 16 bits per pixel image.
457 void PixelReadConvert::ReadAndDecompress12BitsTo16Bits( std::ifstream *fp )
458 throw ( FormatError )
460 int nbPixels = XSize * YSize;
461 uint16_t *localDecompres = (uint16_t*)Raw;
463 for( int p = 0; p < nbPixels; p += 2 )
467 fp->read( (char*)&b0, 1);
468 if ( fp->fail() || fp->eof() )
470 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
471 "Unfound first block" );
474 fp->read( (char*)&b1, 1 );
475 if ( fp->fail() || fp->eof())
477 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
478 "Unfound second block" );
481 fp->read( (char*)&b2, 1 );
482 if ( fp->fail() || fp->eof())
484 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
485 "Unfound second block" );
488 // Two steps are necessary to please VC++
490 // 2 pixels 12bit = [0xABCDEF]
491 // 2 pixels 16bit = [0x0ABD] + [0x0FCE]
493 *localDecompres++ = ((b0 >> 4) << 8) + ((b0 & 0x0f) << 4) + (b1 & 0x0f);
495 *localDecompres++ = ((b2 & 0x0f) << 8) + ((b1 >> 4) << 4) + (b2 >> 4);
497 /// \todo JPR Troubles expected on Big-Endian processors ?
502 * \brief Reads from disk the Pixel Data of JPEG Dicom encapsulated
503 * file and decompress it.
504 * @param fp File Pointer
507 bool PixelReadConvert::ReadAndDecompressJPEGFile( std::ifstream *fp )
511 // make sure this is the right JPEG compression
512 assert( !IsJPEGLossless || !IsJPEGLossy || !IsJPEGLS );
513 // FIXME this is really ugly but it seems I have to load the complete
514 // jpeg2000 stream to use jasper:
515 // I don't think we'll ever be able to deal with multiple fragments properly
517 unsigned long inputlength = 0;
518 JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment();
521 inputlength += jpegfrag->GetLength();
522 jpegfrag = JPEGInfo->GetNextFragment();
524 gdcmAssertMacro( inputlength != 0);
525 uint8_t *inputdata = new uint8_t[inputlength];
526 char *pinputdata = (char*)inputdata;
527 jpegfrag = JPEGInfo->GetFirstFragment();
530 fp->seekg( jpegfrag->GetOffset(), std::ios::beg);
531 fp->read(pinputdata, jpegfrag->GetLength());
532 pinputdata += jpegfrag->GetLength();
533 jpegfrag = JPEGInfo->GetNextFragment();
535 // Warning the inputdata buffer is delete in the function
536 if ( ! gdcm_read_JPEG2000_file( Raw,
537 (char*)inputdata, inputlength ) )
541 // wow what happen, must be an error
542 gdcmWarningMacro( "gdcm_read_JPEG2000_file() failed ");
547 // make sure this is the right JPEG compression
548 assert( !IsJPEGLossless || !IsJPEGLossy || !IsJPEG2000 );
549 // WARNING : JPEG-LS is NOT the 'classical' Jpeg Lossless :
550 // [JPEG-LS is the basis for new lossless/near-lossless compression
551 // standard for continuous-tone images intended for JPEG2000. The standard
552 // is based on the LOCO-I algorithm (LOw COmplexity LOssless COmpression
553 // for Images) developed at Hewlett-Packard Laboratories]
555 // see http://datacompression.info/JPEGLS.shtml
558 std::cerr << "count:" << JPEGInfo->GetFragmentCount() << std::endl;
559 unsigned long inputlength = 0;
560 JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment();
563 inputlength += jpegfrag->GetLength();
564 jpegfrag = JPEGInfo->GetNextFragment();
566 gdcmAssertMacro( inputlength != 0);
567 uint8_t *inputdata = new uint8_t[inputlength];
568 char *pinputdata = (char*)inputdata;
569 jpegfrag = JPEGInfo->GetFirstFragment();
572 fp->seekg( jpegfrag->GetOffset(), std::ios::beg);
573 fp->read(pinputdata, jpegfrag->GetLength());
574 pinputdata += jpegfrag->GetLength();
575 jpegfrag = JPEGInfo->GetNextFragment();
578 //fp->read((char*)Raw, PixelDataLength);
580 std::ofstream out("/tmp/jpegls.jpg");
581 out.write((char*)inputdata, inputlength);
586 gdcmWarningMacro( "Sorry, JPEG-LS not yet taken into account" );
587 fp->seekg( JPEGInfo->GetFirstFragment()->GetOffset(), std::ios::beg);
588 // if ( ! gdcm_read_JPEGLS_file( fp,Raw ) )
593 // make sure this is the right JPEG compression
594 assert( !IsJPEGLS || !IsJPEG2000 );
595 // Precompute the offset localRaw will be shifted with
596 int length = XSize * YSize * SamplesPerPixel;
597 int numberBytes = BitsAllocated / 8;
599 JPEGInfo->DecompressFromFile(fp, Raw, BitsStored, numberBytes, length );
605 * \brief Build Red/Green/Blue/Alpha LUT from File when :
606 * - (0028,0004) : Photometric Interpretation == [PALETTE COLOR ]
608 * - (0028,1101),(0028,1102),(0028,1102)
609 * xxx Palette Color Lookup Table Descriptor are found
611 * - (0028,1201),(0028,1202),(0028,1202)
612 * xxx Palette Color Lookup Table Data - are found
613 * \warning does NOT deal with :
614 * - 0028 1100 Gray Lookup Table Descriptor (Retired)
615 * - 0028 1221 Segmented Red Palette Color Lookup Table Data
616 * - 0028 1222 Segmented Green Palette Color Lookup Table Data
617 * - 0028 1223 Segmented Blue Palette Color Lookup Table Data
618 * no known Dicom reader deals with them :-(
619 * @return a RGBA Lookup Table
621 void PixelReadConvert::BuildLUTRGBA()
624 // Note to code reviewers :
625 // The problem is *much more* complicated, since a lot of manufacturers
626 // Don't follow the norm :
627 // have a look at David Clunie's remark at the end of this .cxx file.
634 // http://www.barre.nom.fr/medical/dicom2/limitations.html#Color%20Lookup%20Tables
636 if ( ! IsPaletteColor )
641 if ( LutRedDescriptor == GDCM_UNFOUND
642 || LutGreenDescriptor == GDCM_UNFOUND
643 || LutBlueDescriptor == GDCM_UNFOUND )
645 gdcmWarningMacro( "(At least) a LUT Descriptor is missing" );
649 ////////////////////////////////////////////
650 // Extract the info from the LUT descriptors
651 int lengthR; // Red LUT length in Bytes
652 int debR; // Subscript of the first Lut Value
653 int nbitsR; // Lut item size (in Bits)
654 int nbRead; // nb of items in LUT descriptor (must be = 3)
656 nbRead = sscanf( LutRedDescriptor.c_str(),
658 &lengthR, &debR, &nbitsR );
661 gdcmWarningMacro( "Wrong Red LUT descriptor" );
663 int lengthG; // Green LUT length in Bytes
664 int debG; // Subscript of the first Lut Value
665 int nbitsG; // Lut item size (in Bits)
667 nbRead = sscanf( LutGreenDescriptor.c_str(),
669 &lengthG, &debG, &nbitsG );
672 gdcmWarningMacro( "Wrong Green LUT descriptor" );
675 int lengthB; // Blue LUT length in Bytes
676 int debB; // Subscript of the first Lut Value
677 int nbitsB; // Lut item size (in Bits)
678 nbRead = sscanf( LutRedDescriptor.c_str(),
680 &lengthB, &debB, &nbitsB );
683 gdcmWarningMacro( "Wrong Blue LUT descriptor" );
686 gdcmDebugMacro(" lengthR " << lengthR << " debR "
687 << debR << " nbitsR " << nbitsR);
688 gdcmDebugMacro(" lengthG " << lengthG << " debG "
689 << debG << " nbitsG " << nbitsG);
690 gdcmDebugMacro(" lengthB " << lengthB << " debB "
691 << debB << " nbitsB " << nbitsB);
693 if ( !lengthR ) // if = 2^16, this shall be 0 see : CP-143
695 if ( !lengthG ) // if = 2^16, this shall be 0
697 if ( !lengthB ) // if = 2^16, this shall be 0
700 ////////////////////////////////////////////////////////
702 if ( ( ! LutRedData ) || ( ! LutGreenData ) || ( ! LutBlueData ) )
704 gdcmWarningMacro( "(At least) a LUT is missing" );
708 // -------------------------------------------------------------
710 if ( BitsAllocated <= 8 )
712 // forge the 4 * 8 Bits Red/Green/Blue/Alpha LUT
713 LutRGBA = new uint8_t[ 1024 ]; // 256 * 4 (R, G, B, Alpha)
718 memset( LutRGBA, 0, 1024 );
721 if ( ( nbitsR == 16 ) && ( BitsAllocated == 8 ) )
723 // when LUT item size is different than pixel size
724 mult = 2; // high byte must be = low byte
728 // See PS 3.3-2003 C.11.1.1.2 p 619
732 // if we get a black image, let's just remove the '+1'
733 // from 'i*mult+1' and check again
734 // if it works, we shall have to check the 3 Palettes
735 // to see which byte is ==0 (first one, or second one)
737 // We give up the checking to avoid some (useless ?) overhead
738 // (optimistic asumption)
742 //take "Subscript of the first Lut Value" (debR,debG,debB) into account!
744 //FIXME : +1 : to get 'low value' byte
745 // Trouble expected on Big Endian Processors ?
746 // 16 BIts Per Pixel Palette Color to be swapped?
748 a = LutRGBA + 0 + debR;
749 for( i=0; i < lengthR; ++i )
751 *a = LutRedData[i*mult+1];
755 a = LutRGBA + 1 + debG;
756 for( i=0; i < lengthG; ++i)
758 *a = LutGreenData[i*mult+1];
762 a = LutRGBA + 2 + debB;
763 for(i=0; i < lengthB; ++i)
765 *a = LutBlueData[i*mult+1];
770 for(i=0; i < 256; ++i)
772 *a = 1; // Alpha component
778 // Probabely the same stuff is to be done for 16 Bits Pixels
779 // with 65536 entries LUT ?!?
780 // Still looking for accurate info on the web :-(
782 gdcmWarningMacro( "Sorry Palette Color Lookup Tables not yet dealt with"
783 << " for 16 Bits Per Pixel images" );
785 // forge the 4 * 16 Bits Red/Green/Blue/Alpha LUT
787 LutRGBA = (uint8_t *)new uint16_t[ 65536*4 ]; // 2^16 * 4 (R, G, B, Alpha)
790 memset( LutRGBA, 0, 65536*4*2 ); // 16 bits = 2 bytes ;-)
792 LutItemNumber = 65536;
798 //take "Subscript of the first Lut Value" (debR,debG,debB) into account!
800 a16 = (uint16_t*)LutRGBA + 0 + debR;
801 for( i=0; i < lengthR; ++i )
803 *a16 = ((uint16_t*)LutRedData)[i];
807 a16 = (uint16_t*)LutRGBA + 1 + debG;
808 for( i=0; i < lengthG; ++i)
810 *a16 = ((uint16_t*)LutGreenData)[i];
814 a16 = (uint16_t*)LutRGBA + 2 + debB;
815 for(i=0; i < lengthB; ++i)
817 *a16 = ((uint16_t*)LutBlueData)[i];
821 a16 = (uint16_t*)LutRGBA + 3 ;
822 for(i=0; i < 65536; ++i)
824 *a16 = 1; // Alpha component
827 /* Just to 'see' the LUT, at debug time
828 // Don't remove this commented out code.
830 a16=(uint16_t*)LutRGBA;
831 for (int j=0;j<65536;j++)
833 std::cout << *a16 << " " << *(a16+1) << " "
834 << *(a16+2) << " " << *(a16+3) << std::endl;
842 * \brief Swap the bytes, according to \ref SwapCode.
844 void PixelReadConvert::ConvertSwapZone()
848 // If this file is 'ImplicitVR BigEndian PrivateGE Transfer Syntax',
849 // then the header is in little endian format and the pixel data is in
850 // big endian format. When reading the header, GDCM has already established
851 // a byte swapping code suitable for this machine to read the
852 // header. In TS::ImplicitVRBigEndianPrivateGE, this code will need
853 // to be switched in order to read the pixel data. This must be
854 // done REGARDLESS of the processor endianess!
856 // Example: Assume we are on a little endian machine. When
857 // GDCM reads the header, the header will match the machine
858 // endianess and the swap code will be established as a no-op.
859 // When GDCM reaches the pixel data, it will need to switch the
860 // swap code to do big endian to little endian conversion.
862 // Now, assume we are on a big endian machine. When GDCM reads the
863 // header, the header will be recognized as a different endianess
864 // than the machine endianess, and a swap code will be established
865 // to convert from little endian to big endian. When GDCM readers
866 // the pixel data, the pixel data endianess will now match the
867 // machine endianess. But we currently have a swap code that
868 // converts from little endian to big endian. In this case, we
869 // need to switch the swap code to a no-op.
871 // Therefore, in either case, if the file is in
872 // 'ImplicitVR BigEndian PrivateGE Transfer Syntax', then GDCM needs to switch
873 // the byte swapping code when entering the pixel data.
875 int tempSwapCode = SwapCode;
876 if ( IsPrivateGETransferSyntax )
878 gdcmWarningMacro(" IsPrivateGETransferSyntax found; turn the SwapCode");
879 // PrivateGETransferSyntax only exists for 'true' Dicom images
880 // we assume there is no 'exotic' 32 bits endianess!
881 if (SwapCode == 1234)
885 else if (SwapCode == 4321)
891 if ( BitsAllocated == 16 )
893 uint16_t *im16 = (uint16_t*)Raw;
894 switch( tempSwapCode )
901 for( i = 0; i < RawSize / 2; i++ )
903 im16[i]= (im16[i] >> 8) | (im16[i] << 8 );
907 gdcmWarningMacro("SwapCode value (16 bits) not allowed."
911 else if ( BitsAllocated == 32 )
916 uint32_t *im32 = (uint32_t*)Raw;
917 switch ( tempSwapCode )
922 for( i = 0; i < RawSize / 4; i++ )
924 low = im32[i] & 0x0000ffff; // 4321
925 high = im32[i] >> 16;
926 high = ( high >> 8 ) | ( high << 8 );
927 low = ( low >> 8 ) | ( low << 8 );
929 im32[i] = ( s32 << 16 ) | high;
933 for( i = 0; i < RawSize / 4; i++ )
935 low = im32[i] & 0x0000ffff; // 2143
936 high = im32[i] >> 16;
937 high = ( high >> 8 ) | ( high << 8 );
938 low = ( low >> 8 ) | ( low << 8 );
940 im32[i] = ( s32 << 16 ) | low;
944 for( i = 0; i < RawSize / 4; i++ )
946 low = im32[i] & 0x0000ffff; // 3412
947 high = im32[i] >> 16;
949 im32[i] = ( s32 << 16 ) | high;
953 gdcmWarningMacro("SwapCode value (32 bits) not allowed." << tempSwapCode );
959 * \brief Deal with endianness i.e. re-arange bytes inside the integer
961 void PixelReadConvert::ConvertReorderEndianity()
963 if ( BitsAllocated != 8 )
968 // Special kludge in order to deal with xmedcon broken images:
969 if ( BitsAllocated == 16
970 && BitsStored < BitsAllocated
973 int l = (int)( RawSize / ( BitsAllocated / 8 ) );
974 uint16_t *deb = (uint16_t *)Raw;
975 for(int i = 0; i<l; i++)
977 if ( *deb == 0xffff )
987 * \brief Deal with Grey levels i.e. re-arange them
988 * to have low values = dark, high values = bright
990 void PixelReadConvert::ConvertFixGreyLevels()
995 uint32_t i; // to please M$VC6
1000 if ( BitsAllocated == 8 )
1002 uint8_t *deb = (uint8_t *)Raw;
1003 for (i=0; i<RawSize; i++)
1011 if ( BitsAllocated == 16 )
1014 for (j=0; j<BitsStored-1; j++)
1016 mask = (mask << 1) +1; // will be fff when BitsStored=12
1019 uint16_t *deb = (uint16_t *)Raw;
1020 for (i=0; i<RawSize/2; i++)
1030 if ( BitsAllocated == 8 )
1032 uint8_t smask8 = 255;
1033 uint8_t *deb = (uint8_t *)Raw;
1034 for (i=0; i<RawSize; i++)
1036 *deb = smask8 - *deb;
1041 if ( BitsAllocated == 16 )
1043 uint16_t smask16 = 65535;
1044 uint16_t *deb = (uint16_t *)Raw;
1045 for (i=0; i<RawSize/2; i++)
1047 *deb = smask16 - *deb;
1056 * \brief Re-arrange the bits within the bytes.
1057 * @return Boolean always true
1059 bool PixelReadConvert::ConvertReArrangeBits() throw ( FormatError )
1062 if ( BitsStored != BitsAllocated )
1064 int l = (int)( RawSize / ( BitsAllocated / 8 ) );
1065 if ( BitsAllocated == 16 )
1067 // pmask : to mask the 'unused bits' (may contain overlays)
1068 uint16_t pmask = 0xffff;
1069 pmask = pmask >> ( BitsAllocated - BitsStored );
1071 uint16_t *deb = (uint16_t*)Raw;
1073 if ( !PixelSign ) // Pixels are unsigned
1075 for(int i = 0; i<l; i++)
1077 *deb = (*deb >> (BitsStored - HighBitPosition - 1)) & pmask;
1081 else // Pixels are signed
1083 // smask : to check the 'sign' when BitsStored != BitsAllocated
1084 uint16_t smask = 0x0001;
1085 smask = smask << ( 16 - (BitsAllocated - BitsStored + 1) );
1086 // nmask : to propagate sign bit on negative values
1087 int16_t nmask = (int16_t)0x8000;
1088 nmask = nmask >> ( BitsAllocated - BitsStored - 1 );
1090 for(int i = 0; i<l; i++)
1092 *deb = *deb >> (BitsStored - HighBitPosition - 1);
1095 *deb = *deb | nmask;
1099 *deb = *deb & pmask;
1105 else if ( BitsAllocated == 32 )
1107 // pmask : to mask the 'unused bits' (may contain overlays)
1108 uint32_t pmask = 0xffffffff;
1109 pmask = pmask >> ( BitsAllocated - BitsStored );
1111 uint32_t *deb = (uint32_t*)Raw;
1115 for(int i = 0; i<l; i++)
1117 *deb = (*deb >> (BitsStored - HighBitPosition - 1)) & pmask;
1123 // smask : to check the 'sign' when BitsStored != BitsAllocated
1124 uint32_t smask = 0x00000001;
1125 smask = smask >> ( 32 - (BitsAllocated - BitsStored +1 ));
1126 // nmask : to propagate sign bit on negative values
1127 int32_t nmask = 0x80000000;
1128 nmask = nmask >> ( BitsAllocated - BitsStored -1 );
1130 for(int i = 0; i<l; i++)
1132 *deb = *deb >> (BitsStored - HighBitPosition - 1);
1134 *deb = *deb | nmask;
1136 *deb = *deb & pmask;
1143 gdcmWarningMacro("Weird image (BitsAllocated !=8, 12, 16, 32)");
1144 throw FormatError( "Weird image !?" );
1151 * \brief Convert (Red plane, Green plane, Blue plane) to RGB pixels
1152 * \warning Works on all the frames at a time
1154 void PixelReadConvert::ConvertRGBPlanesToRGBPixels()
1156 gdcmWarningMacro("--> ConvertRGBPlanesToRGBPixels");
1158 uint8_t *localRaw = Raw;
1159 uint8_t *copyRaw = new uint8_t[ RawSize ];
1160 memmove( copyRaw, localRaw, RawSize );
1162 int l = XSize * YSize * ZSize;
1164 uint8_t *a = copyRaw;
1165 uint8_t *b = copyRaw + l;
1166 uint8_t *c = copyRaw + l + l;
1168 for (int j = 0; j < l; j++)
1170 *(localRaw++) = *(a++);
1171 *(localRaw++) = *(b++);
1172 *(localRaw++) = *(c++);
1178 * \brief Convert (cY plane, cB plane, cR plane) to RGB pixels
1179 * \warning Works on all the frames at a time
1181 void PixelReadConvert::ConvertYcBcRPlanesToRGBPixels()
1183 // Remarks for YBR newbees :
1184 // YBR_FULL works very much like RGB, i.e. three samples per pixel,
1185 // just the color space is YCbCr instead of RGB. This is particularly useful
1186 // for doppler ultrasound where most of the image is grayscale
1187 // (i.e. only populates the Y components) and Cb and Cr are mostly zero,
1188 // except for the few patches of color on the image.
1189 // On such images, RLE achieves a compression ratio that is much better
1190 // than the compression ratio on an equivalent RGB image.
1192 gdcmWarningMacro("--> ConvertYcBcRPlanesToRGBPixels");
1194 uint8_t *localRaw = Raw;
1195 uint8_t *copyRaw = new uint8_t[ RawSize ];
1196 memmove( copyRaw, localRaw, RawSize );
1198 // to see the tricks about YBR_FULL, YBR_FULL_422,
1199 // YBR_PARTIAL_422, YBR_ICT, YBR_RCT have a look at :
1200 // ftp://medical.nema.org/medical/dicom/final/sup61_ft.pdf
1201 // and be *very* affraid
1203 int l = XSize * YSize;
1204 int nbFrames = ZSize;
1206 uint8_t *a = copyRaw + 0;
1207 uint8_t *b = copyRaw + l;
1208 uint8_t *c = copyRaw + l+ l;
1211 /// We replaced easy to understand but time consuming floating point
1212 /// computations by the 'well known' integer computation counterpart
1214 /// http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf
1215 /// for code optimisation.
1217 for ( int i = 0; i < nbFrames; i++ )
1219 for ( int j = 0; j < l; j++ )
1221 R = 38142 *(*a-16) + 52298 *(*c -128);
1222 G = 38142 *(*a-16) - 26640 *(*c -128) - 12845 *(*b -128);
1223 B = 38142 *(*a-16) + 66093 *(*b -128);
1232 if (R > 255) R = 255;
1233 if (G > 255) G = 255;
1234 if (B > 255) B = 255;
1236 *(localRaw++) = (uint8_t)R;
1237 *(localRaw++) = (uint8_t)G;
1238 *(localRaw++) = (uint8_t)B;
1247 /// \brief Deals with the color decoding i.e. handle:
1248 /// - R, G, B planes (as opposed to RGB pixels)
1249 /// - YBR (various) encodings.
1250 /// - LUT[s] (or "PALETTE COLOR").
1252 void PixelReadConvert::ConvertHandleColor()
1254 //////////////////////////////////
1255 // Deal with the color decoding i.e. handle:
1256 // - R, G, B planes (as opposed to RGB pixels)
1257 // - YBR (various) encodings.
1258 // - LUT[s] (or "PALETTE COLOR").
1260 // The classification in the color decoding schema is based on the blending
1261 // of two Dicom tags values:
1262 // * "Photometric Interpretation" for which we have the cases:
1263 // - [Photo A] MONOCHROME[1|2] pictures,
1264 // - [Photo B] RGB or YBR_FULL_422 (which acts as RGB),
1265 // - [Photo C] YBR_* (with the above exception of YBR_FULL_422)
1266 // - [Photo D] "PALETTE COLOR" which indicates the presence of LUT[s].
1267 // * "Planar Configuration" for which we have the cases:
1268 // - [Planar 0] 0 then Pixels are already RGB
1269 // - [Planar 1] 1 then we have 3 planes : R, G, B,
1270 // - [Planar 2] 2 then we have 1 gray Plane and 3 LUTs
1272 // Now in theory, one could expect some coherence when blending the above
1273 // cases. For example we should not encounter files belonging at the
1274 // time to case [Planar 0] and case [Photo D].
1275 // Alas, this was only theory ! Because in practice some odd (read ill
1276 // formated Dicom) files (e.g. gdcmData/US-PAL-8-10x-echo.dcm) we encounter:
1277 // - "Planar Configuration" = 0,
1278 // - "Photometric Interpretation" = "PALETTE COLOR".
1279 // Hence gdcm will use the folowing "heuristic" in order to be tolerant
1280 // towards Dicom-non-conformant files:
1281 // << whatever the "Planar Configuration" value might be, a
1282 // "Photometric Interpretation" set to "PALETTE COLOR" forces
1283 // a LUT intervention >>
1285 // Now we are left with the following handling of the cases:
1286 // - [Planar 0] OR [Photo A] no color decoding (since respectively
1287 // Pixels are already RGB and monochrome pictures have no color :),
1288 // - [Planar 1] AND [Photo B] handled with ConvertRGBPlanesToRGBPixels()
1289 // - [Planar 1] AND [Photo C] handled with ConvertYcBcRPlanesToRGBPixels()
1290 // - [Planar 2] OR [Photo D] requires LUT intervention.
1292 gdcmDebugMacro("--> ConvertHandleColor "
1293 << "Planar Configuration " << PlanarConfiguration );
1297 // [Planar 2] OR [Photo D]: LUT intervention done outside
1298 gdcmDebugMacro("--> RawRGB : LUT intervention done outside");
1302 if ( PlanarConfiguration == 1 )
1306 // [Planar 1] AND [Photo C] (remember YBR_FULL_422 acts as RGB)
1307 gdcmDebugMacro("--> YBRFull");
1308 ConvertYcBcRPlanesToRGBPixels();
1312 // [Planar 1] AND [Photo C]
1313 gdcmDebugMacro("--> YBRFull");
1314 ConvertRGBPlanesToRGBPixels();
1319 // When planarConf is 0, and RLELossless (forbidden by Dicom norm)
1320 // pixels need to be RGB-fyied anyway
1324 gdcmDebugMacro("--> RLE Lossless");
1325 ConvertRGBPlanesToRGBPixels();
1328 // In *normal *case, when planarConf is 0, pixels are already in RGB
1331 /// Computes the Pixels Size
1332 void PixelReadConvert::ComputeRawAndRGBSizes()
1334 int bitsAllocated = BitsAllocated;
1335 // Number of "Bits Allocated" is fixed to 16 when it's 12, since
1336 // in this case we will expand the image to 16 bits (see
1337 // \ref ReadAndDecompress12BitsTo16Bits() )
1338 if ( BitsAllocated == 12 )
1343 RawSize = XSize * YSize * ZSize
1344 * ( bitsAllocated / 8 )
1348 RGBSize = 3 * RawSize; // works for 8 and 16 bits per Pixel
1356 /// Allocates room for RGB Pixels
1357 void PixelReadConvert::AllocateRGB()
1361 RGB = new uint8_t[RGBSize];
1364 /// Allocates room for RAW Pixels
1365 void PixelReadConvert::AllocateRaw()
1369 Raw = new uint8_t[RawSize];
1372 //-----------------------------------------------------------------------------
1375 * \brief Print self.
1376 * @param indent Indentation string to be prepended during printing.
1377 * @param os Stream to print to.
1379 void PixelReadConvert::Print( std::ostream &os, std::string const &indent )
1382 << "--- Pixel information -------------------------"
1385 << "Pixel Data: offset " << PixelOffset
1386 << " x(" << std::hex << PixelOffset << std::dec
1387 << ") length " << PixelDataLength
1388 << " x(" << std::hex << PixelDataLength << std::dec
1389 << ")" << std::endl;
1391 if ( IsRLELossless )
1395 RLEInfo->Print( os, indent );
1399 gdcmWarningMacro("Set as RLE file but NO RLEinfo present.");
1403 if ( IsJPEG2000 || IsJPEGLossless || IsJPEGLossy || IsJPEGLS )
1407 JPEGInfo->Print( os, indent );
1411 gdcmWarningMacro("Set as JPEG file but NO JPEGinfo present.");
1417 * \brief CallStartMethod
1419 void PixelReadConvert::CallStartMethod()
1423 CommandManager::ExecuteCommand(FH,CMD_STARTPROGRESS);
1427 * \brief CallProgressMethod
1429 void PixelReadConvert::CallProgressMethod()
1431 CommandManager::ExecuteCommand(FH,CMD_PROGRESS);
1435 * \brief CallEndMethod
1437 void PixelReadConvert::CallEndMethod()
1440 CommandManager::ExecuteCommand(FH,CMD_ENDPROGRESS);
1444 //-----------------------------------------------------------------------------
1445 } // end namespace gdcm
1447 // Note to developpers :
1448 // Here is a very detailled post from David Clunie, on the troubles caused
1449 // 'non standard' LUT and LUT description
1450 // We shall have to take it into accound in our code.
1455 Subject: Problem with VOI LUTs in Agfa and Fuji CR and GE DX images, was Re: VOI LUT issues
1456 Date: Sun, 06 Feb 2005 17:13:40 GMT
1457 From: David Clunie <dclunie@dclunie.com>
1458 Reply-To: dclunie@dclunie.com
1459 Newsgroups: comp.protocols.dicom
1460 References: <1107553502.040221.189550@o13g2000cwo.googlegroups.com>
1462 > THE LUT that comes with [my] image claims to be 16-bit, but none of the
1463 > values goes higher than 4095. That being said, though, none of my
1464 > original pixel values goes higher than that, either. I have read
1465 > elsewhere on this group that when that happens you are supposed to
1466 > adjust the LUT. Can someone be more specific? There was a thread from
1467 > 2002 where Marco and David were mentioning doing precisely that.
1474 You have encountered the well known "we know what the standard says but
1475 we are going to ignore it and do what we have been doing for almost
1476 a decade regardless" CR vendor bug. Agfa started this, but they are not
1477 the only vendor doing this now; GE and Fuji may have joined the club.
1479 Sadly, one needs to look at the LUT Data, figure out what the maximum
1480 value actually encoded is, and find the next highest power of 2 (e.g.
1481 212 in this case), to figure out what the range of the data is
1482 supposed to be. I have assumed that if the maximum value in the LUT
1483 data is less than a power of 2 minus 1 (e.g. 0xebc) then the intent
1484 of the vendor was not to use the maximum available grayscale range
1485 of the display (e.g. the maximum is 0xfff in this case). An alternative
1486 would be to scale to the actual maximum rather than a power of two.
1488 Very irritating, and in theory not totally reliable if one really
1489 intended the full 16 bits and only used, say 15, but that is extremely
1490 unlikely since everything would be too dark, and this heuristic
1493 There has never been anything in the standard that describes having
1494 to go through these convolutions. Since the only value in the
1495 standard that describes the bit depth of the LUT values is LUT
1496 Descriptor value 3 and that is (usually) always required to be
1497 either 8 or 16, it mystifies me how the creators' of these images
1498 imagine that the receiver is going to divine the range that is intended. Further, the standard is quite explicit that this 3rd
1499 value defines the range of LUT values, but as far as I am aware, all
1500 the vendors are ignoring the standard and indeed sending a third value
1503 This problem is not confined to CR, and is also seen with DX products.
1505 Typically I have seen:
1507 - Agfa CR, which usually (always ?) sends LUTs, values up to 0x0fff
1508 - Fuji CR, which occasionally send LUTs, values up to 0x03ff
1509 - GE DX, for presentation, which always have LUTs, up to 0x3fff
1511 Swissray, Siemens, Philips, Canon and Kodak never seem to send VOI LUTs
1512 at this point (which is a whole other problem). Note that the presence
1513 or absence of a VOI LUT as opposed to window values may be configurable
1514 on the modality in some cases, and I have just looked at what I happen
1515 to have received from a myriad of sites over whose configuration I have
1516 no control. This may be why the majority of Fuji images have no VOI LUTs,
1517 but a few do (or it may be the Siemens system that these Fuji images went
1518 through that perhaps added it). I do have some test Hologic DX images that
1519 are not from a clinical site that do actually get this right (a value
1520 of 12 for the third value and a max of 0xfff).
1522 Since almost every vendor that I have encountered that encodes LUTs
1523 makes this mistake, perhaps it is time to amend the standard to warn
1524 implementor's of receivers and/or sanction this bad behavior. We have
1525 talked about this in the past in WG 6 but so far everyone has been
1526 reluctant to write into the standard such a comment. Maybe it is time
1527 to try again, since if one is not aware of this problem, one cannot
1528 effectively implement display using VOI LUTs, and there is a vast
1529 installed base to contend with.
1531 I did not check presentation states, in which VOI LUTs could also be
1532 encountered, for the prevalence of this mistake, nor did I look at the
1533 encoding of Modality LUT's, which are unusual. Nor did I check digital
1534 mammography images. I would be interested to hear from anyone who has.
1538 PS. The following older thread in this newsgroup discusses this:
1540 "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"
1542 PPS. From a historical perspective, the following may be of interest.
1544 In the original standard in 1993, all that was said about this was a
1545 reference to the corresponding such where Modality LUTs are described
1548 "The third value specifies the number of bits for each entry in the
1549 LUT Data. It shall take the value 8 or 16. The LUT Data shall be stored
1550 in a format equivalent to 8 or 16 bits allocated and high bit equal
1553 Since the high bit hint was not apparently explicit enough, a very
1554 early CP, CP 15 (submitted by Agfa as it happens), replaced this with:
1556 "The third value conveys the range of LUT entry values. It shall take
1557 the value 8 or 16, corresponding with the LUT entry value range of
1560 Note: The third value is not required for describing the
1561 LUT data and is only included for informational usage
1562 and for maintaining compatibility with ACRNEMA 2.0.
1564 The LUT Data contains the LUT entry values."
1566 That is how it read in the 1996, 1998 and 1999 editions.
1568 By the 2000 edition, Supplement 33 that introduced presentation states
1569 extensively reworked this entire section and tried to explain this in
1572 "The output range is from 0 to 2^n-1 where n is the third value of LUT
1573 Descriptor. This range is always unsigned."
1575 and also added a note to spell out what the output range meant in the
1578 "9. The output of the Window Center/Width or VOI LUT transformation
1579 is either implicitly scaled to the full range of the display device
1580 if there is no succeeding transformation defined, or implicitly scaled
1581 to the full input range of the succeeding transformation step (such as
1582 the Presentation LUT), if present. See C.11.6.1."
1584 It still reads this way in the 2004 edition.
1586 Note that LUTs in other applications than the general VOI LUT allow for
1587 values other than 8 or 16 in the third value of LUT descriptor to permit
1588 ranges other than 0 to 255 or 65535.
1590 In addition, the DX Image Module specializes the VOI LUT
1591 attributes as follows, in PS 3.3 section C.8.11.3.1.5 (added in Sup 32):
1593 "The third value specifies the number of bits for each entry in the LUT
1594 Data (analogous to ìbits storedî). It shall be between 10-16. The LUT
1595 Data shall be stored in a format equivalent to 16 ìbits allocatedî and
1596 ìhigh bitî equal to ìbits storedî - 1. The third value conveys the range
1597 of LUT entry values. These unsigned LUT entry values shall range between
1598 0 and 2^n-1, where n is the third value of the LUT Descriptor."
1600 So in the case of the GE DX for presentation images, the third value of
1601 LUT descriptor is allowed to be and probably should be 14 rather than 16.