]> Creatis software - gdcm.git/blob - src/gdcmPixelReadConvert.cxx
Clean code
[gdcm.git] / src / gdcmPixelReadConvert.cxx
1 /*=========================================================================
2  
3   Program:   gdcm
4   Module:    $RCSfile: gdcmPixelReadConvert.cxx,v $
5   Language:  C++
6   Date:      $Date: 2007/09/04 15:43:38 $
7   Version:   $Revision: 1.121 $
8                                                                                 
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.
12                                                                                 
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.
16                                                                                 
17 =========================================================================*/
18
19 #include "gdcmPixelReadConvert.h"
20 #include "gdcmDebug.h"
21 #include "gdcmFile.h"
22 #include "gdcmGlobal.h"
23 #include "gdcmTS.h"
24 #include "gdcmDocEntry.h"
25 #include "gdcmRLEFramesInfo.h"
26 #include "gdcmJPEGFragmentsInfo.h"
27
28 #include <fstream>
29 #include <stdio.h> //for sscanf
30
31 #if defined(__BORLANDC__)
32    #include <mem.h> // for memset
33 #endif 
34
35 namespace GDCM_NAME_SPACE
36 {
37
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))
43
44 //-----------------------------------------------------------------------------
45 // Constructor / Destructor
46 /// Constructor
47 PixelReadConvert::PixelReadConvert() 
48 {
49    RGB          = 0;
50    RGBSize      = 0;
51    Raw          = 0;
52    RawSize      = 0;
53    LutRGBA      = 0;
54    LutRedData   = 0;
55    LutGreenData = 0;
56    LutBlueData  = 0;
57    RLEInfo      = 0;
58    JPEGInfo     = 0;
59    UserFunction = 0;
60    FileInternal = 0;
61 }
62
63 /// Canonical Destructor
64 PixelReadConvert::~PixelReadConvert() 
65 {
66    Squeeze();
67 }
68
69 //-----------------------------------------------------------------------------
70 // Public
71 /**
72  * \brief Predicate to know whether the image[s] (once Raw) is RGB.
73  * \note See comments of \ref ConvertHandleColor
74  */
75 bool PixelReadConvert::IsRawRGB()
76 {
77    if (   IsMonochrome
78        || PlanarConfiguration == 2
79        || IsPaletteColor )
80    {
81       return false;
82    }
83    return true;
84 }
85 /**
86  * \brief Gets various usefull informations from the file header
87  * @param file gdcm::File pointer
88  * @param fileHelper gdcm::FileHelper pointer 
89  */
90 void PixelReadConvert::GrabInformationsFromFile( File *file,
91                                                  FileHelper *fileHelper )
92 {
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 )
97    {
98       BitsAllocated = 16;
99    }
100
101    else if (BitsAllocated > 8 && BitsAllocated < 16 && BitsAllocated != 12)
102    {
103       BitsAllocated = 16;
104    }   
105    // Number of "Bits Stored", defaulted to number of "Bits Allocated"
106    // when absent from the file.
107    BitsStored = file->GetBitsStored();
108    if ( BitsStored == 0 )
109    {
110       BitsStored = BitsAllocated;
111    }
112
113    // High Bit Position, defaulted to "Bits Allocated" - 1
114    HighBitPosition = file->GetHighBitPosition();
115    if ( HighBitPosition == 0 )
116    {
117       HighBitPosition = BitsAllocated - 1;
118    }
119
120    XSize           = file->GetXSize();
121    YSize           = file->GetYSize();
122    ZSize           = file->GetZSize();
123    TSize           = file->GetTSize();   
124    SamplesPerPixel = file->GetSamplesPerPixel();
125    //PixelSize       = file->GetPixelSize();  Useless
126    PixelSign       = file->IsSignedPixelData();
127    SwapCode        = file->GetSwapCode();
128
129    IsPrivateGETransferSyntax = IsMPEG
130              = IsJPEG2000 = IsJPEGLS = IsJPEGLossy  
131              = IsJPEGLossless = IsRLELossless 
132              = false;
133
134    if (! file->IsDicomV3() )  // Should be ACR-NEMA file
135    {
136       IsRaw = true;
137    }
138    else
139    {
140       std::string ts = file->GetTransferSyntax();
141
142       IsRaw = false;
143       while (true) // shorter to write than 'if elseif elseif elseif' ...
144       {
145          // mind the order : check the most usual first.
146          if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRLittleEndian)         break;
147          if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRLittleEndian )        break;
148          if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRBigEndian)            break;
149          if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRBigEndianPrivateGE)   break;
150          // DeflatedExplicitVRLittleEndian syntax means the whole Dataset (Header + Pixels) is compressed !
151          // Not dealt with ! (Parser hangs)
152          //if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::DeflatedExplicitVRLittleEndian) break;
153          break;
154       }
155       // cache whether this is a strange GE transfer syntax (which uses
156       // a little endian transfer syntax for the header and a big endian
157       // transfer syntax for the pixel data). 
158       IsPrivateGETransferSyntax = 
159                 ( Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRBigEndianPrivateGE );
160
161       IsMPEG =  IsJPEG2000 =  IsJPEGLS =  IsJPEGLossy =  IsJPEGLossless = IsRLELossless = false;  
162       if (!IsRaw)
163       {     
164          while(true)
165          {
166             // mind the order : check the most usual first.
167             if( IsJPEGLossy     = Global::GetTS()->IsJPEGLossy(ts) )    break;
168             if( IsJPEGLossless  = Global::GetTS()->IsJPEGLossless(ts) ) break;
169             if( IsRLELossless   = Global::GetTS()->IsRLELossless(ts) )  break;
170             if( IsJPEG2000      = Global::GetTS()->IsJPEG2000(ts) )     break;
171             if( IsMPEG          = Global::GetTS()->IsMPEG(ts) )         break;
172             if( IsJPEGLS        = Global::GetTS()->IsJPEGLS(ts) )       break;
173             // DeflatedExplicitVRLittleEndian is considered as 'Unexpected' (we don't know yet how to process !)
174             gdcmWarningMacro("Unexpected Transfer Syntax :[" << ts << "]");
175             break;
176          } 
177       }
178    }
179
180    PixelOffset     = file->GetPixelOffset();
181    PixelDataLength = file->GetPixelAreaLength();
182    RLEInfo         = file->GetRLEInfo();
183    JPEGInfo        = file->GetJPEGInfo();
184
185    IsMonochrome    = file->IsMonochrome();
186    IsMonochrome1   = file->IsMonochrome1();
187    IsPaletteColor  = file->IsPaletteColor();
188    IsYBRFull       = file->IsYBRFull();
189
190    PlanarConfiguration = file->GetPlanarConfiguration();
191
192    /////////////////////////////////////////////////////////////////
193    // LUT section:
194    HasLUT = file->HasLUT();
195    if ( HasLUT )
196    {
197       // Just in case some access to a File element requires disk access.
198       LutRedDescriptor   = file->GetEntryString( 0x0028, 0x1101 );
199       LutGreenDescriptor = file->GetEntryString( 0x0028, 0x1102 );
200       LutBlueDescriptor  = file->GetEntryString( 0x0028, 0x1103 );
201    
202       // FIXME : The following comment is probabely meaningless, since LUT are *always*
203       // loaded at parsing time, whatever their length is.
204          
205       // Depending on the value of Document::MAX_SIZE_LOAD_ELEMENT_VALUE
206       // [ refer to invocation of Document::SetMaxSizeLoadEntry() in
207       // Document::Document() ], the loading of the value (content) of a
208       // [Bin|Val]Entry occurence migth have been hindered (read simply NOT
209       // loaded). Hence, we first try to obtain the LUTs data from the file
210       // and when this fails we read the LUTs data directly from disk.
211       // \TODO Reading a [Bin|Val]Entry directly from disk is a kludge.
212       //       We should NOT bypass the [Bin|Val]Entry class. Instead
213       //       an access to an UNLOADED content of a [Bin|Val]Entry occurence
214       //       (e.g. DataEntry::GetBinArea()) should force disk access from
215       //       within the [Bin|Val]Entry class itself. The only problem
216       //       is that the [Bin|Val]Entry is unaware of the FILE* is was
217       //       parsed from. Fix that. FIXME.
218    
219       // //// Red round
220       file->LoadEntryBinArea(0x0028, 0x1201);
221       LutRedData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1201 );
222       if ( ! LutRedData )
223       {
224          gdcmWarningMacro("Unable to read Red Palette Color Lookup Table data");
225       }
226
227       // //// Green round:
228       file->LoadEntryBinArea(0x0028, 0x1202);
229       LutGreenData = (uint8_t*)file->GetEntryBinArea(0x0028, 0x1202 );
230       if ( ! LutGreenData)
231       {
232          gdcmWarningMacro("Unable to read Green Palette Color Lookup Table data");
233       }
234
235       // //// Blue round:
236       file->LoadEntryBinArea(0x0028, 0x1203);
237       LutBlueData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1203 );
238       if ( ! LutBlueData )
239       {
240          gdcmWarningMacro("Unable to read Blue Palette Color Lookup Table data");
241       }
242    }
243    FileInternal = file;   
244    FH = fileHelper;
245    ComputeRawAndRGBSizes();
246 }
247
248 /// \brief Reads from disk and decompresses Pixels
249 bool PixelReadConvert::ReadAndDecompressPixelData( std::ifstream *fp )
250 {
251    // ComputeRawAndRGBSizes is already made by 
252    // ::GrabInformationsFromfile. So, the structure sizes are
253    // correct
254    Squeeze();
255
256    //////////////////////////////////////////////////
257    //// First stage: get our hands on the Pixel Data.
258    if ( !fp )
259    {
260       gdcmWarningMacro( "Unavailable file pointer." );
261       return false;
262    }
263
264    fp->seekg( PixelOffset, std::ios::beg );
265    if ( fp->fail() || fp->eof() )
266    {
267       gdcmWarningMacro( "Unable to find PixelOffset in file." );
268       return false;
269    }
270
271    AllocateRaw();
272
273    //////////////////////////////////////////////////
274    
275    CallStartMethod(); // for progress bar
276    unsigned int count = 0;
277    unsigned int frameSize;
278    unsigned int bitsAllocated = BitsAllocated;
279    //if(bitsAllocated == 12)
280    if(bitsAllocated > 8 && bitsAllocated < 16)
281       bitsAllocated = 16;
282    frameSize = XSize*YSize*SamplesPerPixel*bitsAllocated/8;
283    
284    //// Second stage: read from disk and decompress.
285    
286    if ( BitsAllocated == 12 ) // We suppose 'BitsAllocated' = 12 only exist for uncompressed files
287    {
288       ReadAndDecompress12BitsTo16Bits( fp);
289    }
290    else if ( IsRaw )
291    {
292       // This problem can be found when some obvious informations are found
293       // after the field containing the image data. In this case, these
294       // bad data are added to the size of the image (in the PixelDataLength
295       // variable). But RawSize is the right size of the image !
296       if ( PixelDataLength != RawSize )
297       {
298          gdcmWarningMacro( "Mismatch between PixelReadConvert : "
299                             << PixelDataLength << " and RawSize : " << RawSize );
300       }
301       
302       //todo : is it the right patch?
303       char *raw = (char*)Raw;
304       uint32_t remainingLength;
305       unsigned int i; 
306       unsigned int lengthToRead;
307        
308       if ( PixelDataLength > RawSize )
309         lengthToRead =  RawSize;
310       else
311         lengthToRead = PixelDataLength;
312  
313       // perform a frame by frame reading
314       remainingLength = lengthToRead;
315       unsigned int nbFrames = lengthToRead / frameSize;
316       for (i=0;i<nbFrames; i++)
317       {
318          Progress = (float)(count+1)/(float)nbFrames;
319          fp->read( raw, frameSize);
320          raw +=  frameSize;
321          remainingLength -=  frameSize;
322          count++;
323       }
324       if (remainingLength !=0 )
325         fp->read( raw, remainingLength);
326                  
327       if ( fp->fail() || fp->eof())
328       {
329          gdcmWarningMacro( "Reading of Raw pixel data failed." );
330          return false;
331       }
332    } 
333    else if ( IsRLELossless )
334    {
335       if ( ! RLEInfo->DecompressRLEFile
336                                ( fp, Raw, XSize, YSize, ZSize, TSize, BitsAllocated ) )
337       {
338          gdcmWarningMacro( "RLE decompressor failed." );
339          return false;
340       }
341    }
342    else if ( IsMPEG )
343    {
344       //gdcmWarningMacro( "Sorry, MPEG not yet taken into account" );
345       //return false;
346       // fp has already been seek to start of mpeg
347       //ReadMPEGFile(fp, (char*)Raw, PixelDataLength); 
348       return true;
349    }
350    else
351    {
352       // Default case concerns JPEG family
353       if ( ! ReadAndDecompressJPEGFile( fp ) )
354       {
355          gdcmWarningMacro( "JPEG decompressor ( ReadAndDecompressJPEGFile()"
356                               << " method ) failed." );
357          return false;
358       }
359    }
360
361    ////////////////////////////////////////////
362    //// Third stage: twigle the bytes and bits.
363    ConvertReorderEndianity();
364    ConvertReArrangeBits();
365    ConvertFixGreyLevels();
366    if (UserFunction) // user is allowed to Mirror, TopDown, Rotate,...the image
367       UserFunction( Raw, FileInternal);
368    ConvertHandleColor();
369
370    return true;
371 }
372
373 /// Deletes Pixels Area
374 void PixelReadConvert::Squeeze() 
375 {
376    if ( RGB )
377       delete [] RGB;
378    RGB = 0;
379
380    if ( Raw )
381       delete [] Raw;
382    Raw = 0;
383
384    if ( LutRGBA )
385       delete [] LutRGBA;
386    LutRGBA = 0;
387 }
388
389 /**
390  * \brief Build the RGB image from the Raw image and the LUTs.
391  */
392 bool PixelReadConvert::BuildRGBImage()
393 {
394    if ( RGB )
395    {
396       // The job is already done.
397       return true;
398    }
399
400    if ( ! Raw )
401    {
402       // The job can't be done
403       return false;
404    }
405
406    BuildLUTRGBA();
407    if ( ! LutRGBA )
408    {
409       // The job can't be done
410       return false;
411    }
412
413    gdcmDebugMacro( "--> BuildRGBImage" );
414                                                                                 
415    // Build RGB Pixels
416    AllocateRGB();
417    
418    int j;
419    if ( BitsAllocated <= 8 )
420    {
421       uint8_t *localRGB = RGB;
422       for (size_t i = 0; i < RawSize; ++i )
423       {
424          j  = Raw[i] * 4;
425          *localRGB++ = LutRGBA[j];
426          *localRGB++ = LutRGBA[j+1];
427          *localRGB++ = LutRGBA[j+2];
428       }
429     }
430  
431     else  // deal with 16 bits pixels and 16 bits Palette color
432     {
433       uint16_t *localRGB = (uint16_t *)RGB;
434       for (size_t i = 0; i < RawSize/2; ++i )
435       {
436          j  = ((uint16_t *)Raw)[i] * 4;
437          *localRGB++ = ((uint16_t *)LutRGBA)[j];
438          *localRGB++ = ((uint16_t *)LutRGBA)[j+1];
439          *localRGB++ = ((uint16_t *)LutRGBA)[j+2];
440       } 
441     }
442  
443    return true;
444 }
445
446 //-----------------------------------------------------------------------------
447 // Protected
448
449 //-----------------------------------------------------------------------------
450 // Private
451 /**
452  * \brief Read from file a 12 bits per pixel image and decompress it
453  *        into a 16 bits per pixel image.
454  */
455 void PixelReadConvert::ReadAndDecompress12BitsTo16Bits( std::ifstream *fp )
456                throw ( FormatError )
457 {
458    /// \todo Fix the 3D, 4D pb
459    int nbPixels = XSize * YSize * TSize;
460    uint16_t *localDecompres = (uint16_t*)Raw;
461
462    for( int p = 0; p < nbPixels; p += 2 )
463    {
464       uint8_t b0, b1, b2;
465
466       fp->read( (char*)&b0, 1);
467       if ( fp->fail() || fp->eof() )
468       {
469          throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
470                                 "Unfound first block" );
471       }
472
473       fp->read( (char*)&b1, 1 );
474       if ( fp->fail() || fp->eof())
475       {
476          throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
477                                 "Unfound second block" );
478       }
479
480       fp->read( (char*)&b2, 1 );
481       if ( fp->fail() || fp->eof())
482       {
483          throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
484                                 "Unfound second block" );
485       }
486
487       // Two steps are necessary to please VC++
488       //
489       // 2 pixels 12bit =     [0xABCDEF]
490       // 2 pixels 16bit = [0x0ABD] + [0x0FCE]
491       //                        A                     B                 D
492       *localDecompres++ =  ((b0 >> 4) << 8) + ((b0 & 0x0f) << 4) + (b1 & 0x0f);
493       //                        F                     C                 E
494       *localDecompres++ =  ((b2 & 0x0f) << 8) + ((b1 >> 4) << 4) + (b2 >> 4);
495
496       /// \todo JPR Troubles expected on Big-Endian processors ?
497    }
498 }
499
500 /**
501  * \brief     Reads from disk the Pixel Data of JPEG Dicom encapsulated
502  *            file and decompress it.
503  * @param     fp File Pointer
504  * @return    Boolean
505  */
506 bool PixelReadConvert::ReadAndDecompressJPEGFile( std::ifstream *fp )
507 {
508    if ( IsJPEG2000 )
509    {
510      // make sure this is the right JPEG compression
511      assert( !IsJPEGLossless || !IsJPEGLossy || !IsJPEGLS );
512      // FIXME this is really ugly but it seems I have to load the complete
513      // jpeg2000 stream to use jasper:
514      // I don't think we'll ever be able to deal with multiple fragments properly
515
516       unsigned long inputlength = 0;
517       JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment();
518       while( jpegfrag )
519       {
520          inputlength += jpegfrag->GetLength();
521          jpegfrag = JPEGInfo->GetNextFragment();
522       }
523       gdcmAssertMacro( inputlength != 0);
524       uint8_t *inputdata = new uint8_t[inputlength];
525       char *pinputdata = (char*)inputdata;
526       jpegfrag = JPEGInfo->GetFirstFragment();
527       while( jpegfrag )
528       {
529          fp->seekg( jpegfrag->GetOffset(), std::ios::beg);
530          fp->read(pinputdata, jpegfrag->GetLength());
531          pinputdata += jpegfrag->GetLength();
532          jpegfrag = JPEGInfo->GetNextFragment();
533       }
534       // Warning the inputdata buffer is delete in the function
535       if ( ! gdcm_read_JPEG2000_file( Raw, 
536           (char*)inputdata, inputlength ) )
537       {
538          return true;
539       }
540       // wow what happen, must be an error
541       gdcmWarningMacro( "gdcm_read_JPEG2000_file() failed "); 
542       return false;
543    }
544    else if ( IsJPEGLS )
545    {
546      // make sure this is the right JPEG compression
547      assert( !IsJPEGLossless || !IsJPEGLossy || !IsJPEG2000 );
548    // WARNING : JPEG-LS is NOT the 'classical' Jpeg Lossless : 
549    // [JPEG-LS is the basis for new lossless/near-lossless compression
550    // standard for continuous-tone images intended for JPEG2000. The standard
551    // is based on the LOCO-I algorithm (LOw COmplexity LOssless COmpression
552    // for Images) developed at Hewlett-Packard Laboratories]
553    //
554    // see http://datacompression.info/JPEGLS.shtml
555    //
556 #if 0
557    std::cerr << "count:" << JPEGInfo->GetFragmentCount() << std::endl;
558       unsigned long inputlength = 0;
559       JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment();
560       while( jpegfrag )
561       {
562          inputlength += jpegfrag->GetLength();
563          jpegfrag = JPEGInfo->GetNextFragment();
564       }
565       gdcmAssertMacro( inputlength != 0);
566       uint8_t *inputdata = new uint8_t[inputlength];
567       char *pinputdata = (char*)inputdata;
568       jpegfrag = JPEGInfo->GetFirstFragment();
569       while( jpegfrag )
570       {
571          fp->seekg( jpegfrag->GetOffset(), std::ios::beg);
572          fp->read(pinputdata, jpegfrag->GetLength());
573          pinputdata += jpegfrag->GetLength();
574          jpegfrag = JPEGInfo->GetNextFragment();
575       }  
576       
577   //fp->read((char*)Raw, PixelDataLength);
578
579   std::ofstream out("/tmp/jpegls.jpg");
580   out.write((char*)inputdata, inputlength);
581   out.close();
582   delete[] inputdata;
583 #endif
584
585       gdcmWarningMacro( "Sorry, JPEG-LS not yet taken into account" );
586       fp->seekg( JPEGInfo->GetFirstFragment()->GetOffset(), std::ios::beg);
587 //    if ( ! gdcm_read_JPEGLS_file( fp,Raw ) )
588          return false;
589    }
590    else
591    {
592      // make sure this is the right JPEG compression
593      assert( !IsJPEGLS || !IsJPEG2000 );
594      // Precompute the offset localRaw will be shifted with
595      int length = XSize * YSize * ZSize * SamplesPerPixel;
596      int numberBytes = BitsAllocated / 8;
597       
598       // to avoid major troubles when BitsStored == 8 && BitsAllocated==16 !
599      int dummy;
600      if (BitsStored == 8 && BitsAllocated==16)
601         dummy = 16;
602      else
603         dummy = BitsStored;
604      
605      JPEGInfo->DecompressFromFile(fp, Raw, /*BitsStored*/ dummy , numberBytes, length );
606      return true;
607    }
608 }
609
610 /**
611  * \brief Build Red/Green/Blue/Alpha LUT from File when :
612  *         - (0028,0004) : Photometric Interpretation == [PALETTE COLOR ]
613  *         and
614  *         - (0028,1101),(0028,1102),(0028,1102)
615  *            xxx Palette Color Lookup Table Descriptor are found
616  *          and
617  *         - (0028,1201),(0028,1202),(0028,1202)
618  *           xxx Palette Color Lookup Table Data - are found
619  * \warning does NOT deal with :
620  *   - 0028 1100 Gray Lookup Table Descriptor (Retired)
621  *   - 0028 1221 Segmented Red Palette Color Lookup Table Data
622  *   - 0028 1222 Segmented Green Palette Color Lookup Table Data
623  *   - 0028 1223 Segmented Blue Palette Color Lookup Table Data
624  *   no known Dicom reader deals with them :-(
625  * @return a RGBA Lookup Table
626  */
627 void PixelReadConvert::BuildLUTRGBA()
628 {
629
630    // Note to code reviewers :
631    // The problem is *much more* complicated, since a lot of manufacturers
632    // Don't follow the norm :
633    // have a look at David Clunie's remark at the end of this .cxx file.
634    if ( LutRGBA )
635    
636    {
637       return;
638    }
639    // Not so easy : see
640    // http://www.barre.nom.fr/medical/dicom2/limitations.html#Color%20Lookup%20Tables
641                                                                                 
642    if ( ! IsPaletteColor )
643    {
644       return;
645    }
646                                                                                 
647    if (   LutRedDescriptor   == GDCM_UNFOUND
648        || LutGreenDescriptor == GDCM_UNFOUND
649        || LutBlueDescriptor  == GDCM_UNFOUND )
650    {
651       gdcmWarningMacro( "(At least) a LUT Descriptor is missing" );
652       return;
653    }
654
655    ////////////////////////////////////////////
656    // Extract the info from the LUT descriptors
657    int lengthR;   // Red LUT length in Bytes
658    int debR;      // Subscript of the first Lut Value
659    int nbitsR;    // Lut item size (in Bits)
660    int nbRead;    // nb of items in LUT descriptor (must be = 3)
661
662    nbRead = sscanf( LutRedDescriptor.c_str(),
663                         "%d\\%d\\%d",
664                         &lengthR, &debR, &nbitsR );
665    if ( nbRead != 3 )
666    {
667       gdcmWarningMacro( "Wrong Red LUT descriptor" );
668    }                                                                                
669    int lengthG;  // Green LUT length in Bytes
670    int debG;     // Subscript of the first Lut Value
671    int nbitsG;   // Lut item size (in Bits)
672
673    nbRead = sscanf( LutGreenDescriptor.c_str(),
674                     "%d\\%d\\%d",
675                     &lengthG, &debG, &nbitsG );  
676    if ( nbRead != 3 )
677    {
678       gdcmWarningMacro( "Wrong Green LUT descriptor" );
679    }
680                                                                                 
681    int lengthB;  // Blue LUT length in Bytes
682    int debB;     // Subscript of the first Lut Value
683    int nbitsB;   // Lut item size (in Bits)
684    nbRead = sscanf( LutRedDescriptor.c_str(),
685                     "%d\\%d\\%d",
686                     &lengthB, &debB, &nbitsB );
687    if ( nbRead != 3 )
688    {
689       gdcmWarningMacro( "Wrong Blue LUT descriptor" );
690    }
691  
692    gdcmDebugMacro(" lengthR " << lengthR << " debR " 
693                 << debR << " nbitsR " << nbitsR);
694    gdcmDebugMacro(" lengthG " << lengthG << " debG " 
695                 << debG << " nbitsG " << nbitsG);
696    gdcmDebugMacro(" lengthB " << lengthB << " debB " 
697                 << debB << " nbitsB " << nbitsB);
698
699    if ( !lengthR ) // if = 2^16, this shall be 0 see : CP-143
700       lengthR=65536;
701    if ( !lengthG ) // if = 2^16, this shall be 0
702       lengthG=65536;
703    if ( !lengthB ) // if = 2^16, this shall be 0
704       lengthB=65536; 
705                                                                                 
706    ////////////////////////////////////////////////////////
707
708    if ( ( ! LutRedData ) || ( ! LutGreenData ) || ( ! LutBlueData ) )
709    {
710       gdcmWarningMacro( "(At least) a LUT is missing" );
711       return;
712    }
713
714    // -------------------------------------------------------------
715    
716    if ( BitsAllocated <= 8 )
717    {
718       // forge the 4 * 8 Bits Red/Green/Blue/Alpha LUT
719       LutRGBA = new uint8_t[ 1024 ]; // 256 * 4 (R, G, B, Alpha)
720       if ( !LutRGBA )
721          return;
722       LutItemNumber = 256;
723       LutItemSize   = 8;
724       memset( LutRGBA, 0, 1024 );
725                                                                                 
726       int mult;
727       if ( ( nbitsR == 16 ) && ( BitsAllocated == 8 ) )
728       {
729          // when LUT item size is different than pixel size
730          mult = 2; // high byte must be = low byte
731       }
732       else
733       {
734          // See PS 3.3-2003 C.11.1.1.2 p 619
735          mult = 1;
736       }
737                                                                                 
738       // if we get a black image, let's just remove the '+1'
739       // from 'i*mult+1' and check again
740       // if it works, we shall have to check the 3 Palettes
741       // to see which byte is ==0 (first one, or second one)
742       // and fix the code
743       // We give up the checking to avoid some (useless ?) overhead
744       // (optimistic asumption)
745       int i;
746       uint8_t *a;
747
748       //take "Subscript of the first Lut Value" (debR,debG,debB) into account!
749
750       //FIXME :  +1 : to get 'low value' byte
751       //         Trouble expected on Big Endian Processors ?
752       //         16 BIts Per Pixel Palette Color to be swapped?
753
754       a = LutRGBA + 0 + debR;
755       for( i=0; i < lengthR; ++i )
756       {
757          *a = LutRedData[i*mult+1]; 
758          a += 4;
759       }
760                                                                                 
761       a = LutRGBA + 1 + debG;
762       for( i=0; i < lengthG; ++i)
763       {
764          *a = LutGreenData[i*mult+1];
765          a += 4;
766       }
767                                                                                 
768       a = LutRGBA + 2 + debB;
769       for(i=0; i < lengthB; ++i)
770       {
771          *a = LutBlueData[i*mult+1];
772          a += 4;
773       }
774                                     
775       a = LutRGBA + 3 ;
776       for(i=0; i < 256; ++i)
777       {
778          *a = 1; // Alpha component
779          a += 4;
780       }
781    }
782    else
783    {
784       // Probabely the same stuff is to be done for 16 Bits Pixels
785       // with 65536 entries LUT ?!?
786       // Still looking for accurate info on the web :-(
787
788       gdcmWarningMacro( "Sorry Palette Color Lookup Tables not yet dealt with"
789                          << " for 16 Bits Per Pixel images" );
790
791       // forge the 4 * 16 Bits Red/Green/Blue/Alpha LUT
792
793       LutRGBA = (uint8_t *)new uint16_t[ 65536*4 ]; // 2^16 * 4 (R, G, B, Alpha)
794       if ( !LutRGBA )
795          return;
796       memset( LutRGBA, 0, 65536*4*2 );  // 16 bits = 2 bytes ;-)
797
798       LutItemNumber = 65536;
799       LutItemSize   = 16;
800
801       int i;
802       uint16_t *a16;
803
804       //take "Subscript of the first Lut Value" (debR,debG,debB) into account!
805
806       a16 = (uint16_t*)LutRGBA + 0 + debR;
807       for( i=0; i < lengthR; ++i )
808       {
809          *a16 = ((uint16_t*)LutRedData)[i];
810          a16 += 4;
811       }
812                                                                               
813       a16 = (uint16_t*)LutRGBA + 1 + debG;
814       for( i=0; i < lengthG; ++i)
815       {
816          *a16 = ((uint16_t*)LutGreenData)[i];
817          a16 += 4;
818       }
819                                                                                 
820       a16 = (uint16_t*)LutRGBA + 2 + debB;
821       for(i=0; i < lengthB; ++i)
822       {
823          *a16 = ((uint16_t*)LutBlueData)[i];
824          a16 += 4;
825       }
826                                                                              
827       a16 = (uint16_t*)LutRGBA + 3 ;
828       for(i=0; i < 65536; ++i)
829       {
830          *a16 = 1; // Alpha component
831          a16 += 4;
832       }
833 /* Just to 'see' the LUT, at debug time
834 // Don't remove this commented out code.
835
836       a16=(uint16_t*)LutRGBA;
837       for (int j=0;j<65536;j++)
838       {
839          std::cout << *a16     << " " << *(a16+1) << " "
840                    << *(a16+2) << " " << *(a16+3) << std::endl;
841          a16+=4;
842       }
843 */
844    }
845 }
846
847 /**
848  * \brief Swap the bytes, according to \ref SwapCode.
849  */
850 void PixelReadConvert::ConvertSwapZone()
851 {
852    unsigned int i;
853
854    // If this file is 'ImplicitVR BigEndian PrivateGE Transfer Syntax', 
855    // then the header is in little endian format and the pixel data is in 
856    // big endian format.  When reading the header, GDCM has already established
857    // a byte swapping code suitable for this machine to read the
858    // header. In TS::ImplicitVRBigEndianPrivateGE, this code will need
859    // to be switched in order to read the pixel data.  This must be
860    // done REGARDLESS of the processor endianess!
861    //
862    // Example:  Assume we are on a little endian machine.  When
863    // GDCM reads the header, the header will match the machine
864    // endianess and the swap code will be established as a no-op.
865    // When GDCM reaches the pixel data, it will need to switch the
866    // swap code to do big endian to little endian conversion.
867    //
868    // Now, assume we are on a big endian machine.  When GDCM reads the
869    // header, the header will be recognized as a different endianess
870    // than the machine endianess, and a swap code will be established
871    // to convert from little endian to big endian.  When GDCM readers
872    // the pixel data, the pixel data endianess will now match the
873    // machine endianess.  But we currently have a swap code that
874    // converts from little endian to big endian.  In this case, we
875    // need to switch the swap code to a no-op.
876    //
877    // Therefore, in either case, if the file is in
878    // 'ImplicitVR BigEndian PrivateGE Transfer Syntax', then GDCM needs to switch
879    // the byte swapping code when entering the pixel data.
880    
881    int tempSwapCode = SwapCode;
882    if ( IsPrivateGETransferSyntax )
883    {
884       gdcmWarningMacro(" IsPrivateGETransferSyntax found; turn the SwapCode"); 
885       // PrivateGETransferSyntax only exists for 'true' Dicom images
886       // we assume there is no 'exotic' 32 bits endianess!
887       if (SwapCode == 1234) 
888       {
889          tempSwapCode = 4321;
890       }
891       else if (SwapCode == 4321)
892       {
893          tempSwapCode = 1234;
894       }
895    }
896     
897    if ( BitsAllocated == 16 )
898    {
899       uint16_t *im16 = (uint16_t*)Raw;
900       switch( tempSwapCode )
901       {
902          case 1234:
903             break;
904          case 3412:
905          case 2143:
906          case 4321:
907             for( i = 0; i < RawSize / 2; i++ )
908             {
909                im16[i]= (im16[i] >> 8) | (im16[i] << 8 );
910             }
911             break;
912          default:
913             gdcmWarningMacro("SwapCode value (16 bits) not allowed." 
914                         << tempSwapCode);
915       }
916    }
917    else if ( BitsAllocated == 32 )
918    {
919       uint32_t s32;
920       uint16_t high;
921       uint16_t low;
922       uint32_t *im32 = (uint32_t*)Raw;
923       switch ( tempSwapCode )
924       {
925          case 1234:
926             break;
927          case 4321:
928             for( i = 0; i < RawSize / 4; i++ )
929             {
930                low     = im32[i] & 0x0000ffff;  // 4321
931                high    = im32[i] >> 16;
932                high    = ( high >> 8 ) | ( high << 8 );
933                low     = ( low  >> 8 ) | ( low  << 8 );
934                s32     = low;
935                im32[i] = ( s32 << 16 ) | high;
936             }
937             break;
938          case 2143:
939             for( i = 0; i < RawSize / 4; i++ )
940             {
941                low     = im32[i] & 0x0000ffff;   // 2143
942                high    = im32[i] >> 16;
943                high    = ( high >> 8 ) | ( high << 8 );
944                low     = ( low  >> 8 ) | ( low  << 8 );
945                s32     = high;
946                im32[i] = ( s32 << 16 ) | low;
947             }
948             break;
949          case 3412:
950             for( i = 0; i < RawSize / 4; i++ )
951             {
952                low     = im32[i] & 0x0000ffff; // 3412
953                high    = im32[i] >> 16;
954                s32     = low;
955                im32[i] = ( s32 << 16 ) | high;
956             }
957             break;
958          default:
959             gdcmWarningMacro("SwapCode value (32 bits) not allowed." << tempSwapCode );
960       }
961    }
962 }
963
964 /**
965  * \brief Deal with endianness i.e. re-arange bytes inside the integer
966  */
967 void PixelReadConvert::ConvertReorderEndianity()
968 {
969    if ( BitsAllocated != 8 )
970    {
971       ConvertSwapZone();
972    }
973
974    // Special kludge in order to deal with xmedcon broken images:
975    if ( BitsAllocated == 16
976      && BitsStored < BitsAllocated
977      && !PixelSign )
978    {
979       int l = (int)( RawSize / ( BitsAllocated / 8 ) );
980       uint16_t *deb = (uint16_t *)Raw;
981       for(int i = 0; i<l; i++)
982       {
983          if ( *deb == 0xffff )
984          {
985            *deb = 0;
986          }
987          deb++;
988       }
989    }
990 }
991
992 /**
993  * \brief Deal with Grey levels i.e. re-arange them
994  *        to have low values = dark, high values = bright
995  */
996 void PixelReadConvert::ConvertFixGreyLevels()
997 {
998    if (!IsMonochrome1)
999       return;
1000
1001    uint32_t i; // to please M$VC6
1002    int16_t j;
1003
1004    if (!PixelSign)
1005    {
1006       if ( BitsAllocated == 8 )
1007       {
1008          uint8_t *deb = (uint8_t *)Raw;
1009          for (i=0; i<RawSize; i++)      
1010          {
1011             *deb = 255 - *deb;
1012             deb++;
1013          }
1014          return;
1015       }
1016
1017       if ( BitsAllocated == 16 )
1018       {
1019          uint16_t mask =1;
1020          for (j=0; j<BitsStored-1; j++)
1021          {
1022             mask = (mask << 1) +1; // will be fff when BitsStored=12
1023          }
1024
1025          uint16_t *deb = (uint16_t *)Raw;
1026          for (i=0; i<RawSize/2; i++)      
1027          {
1028             *deb = mask - *deb;
1029             deb++;
1030          }
1031          return;
1032        }
1033    }
1034    else
1035    {
1036       if ( BitsAllocated == 8 )
1037       {
1038          uint8_t smask8 = 255;
1039          uint8_t *deb = (uint8_t *)Raw;
1040          for (i=0; i<RawSize; i++)      
1041          {
1042             *deb = smask8 - *deb;
1043             deb++;
1044          }
1045          return;
1046       }
1047       if ( BitsAllocated == 16 )
1048       {
1049          uint16_t smask16 = 65535;
1050          uint16_t *deb = (uint16_t *)Raw;
1051          for (i=0; i<RawSize/2; i++)      
1052          {
1053             *deb = smask16 - *deb;
1054             deb++;
1055          }
1056          return;
1057       }
1058    }
1059 }
1060
1061 /**
1062  * \brief  Re-arrange the bits within the bytes.
1063  * @return Boolean always true
1064  */
1065 bool PixelReadConvert::ConvertReArrangeBits() throw ( FormatError )
1066 {
1067
1068    if ( BitsStored != BitsAllocated )
1069    {
1070       int l = (int)( RawSize / ( BitsAllocated / 8 ) );
1071       if ( BitsAllocated == 16 )
1072       {
1073          // pmask : to mask the 'unused bits' (may contain overlays)
1074          uint16_t pmask = 0xffff;
1075  
1076          // It's up to the user to decide if he wants to ignore overlays (if any),
1077          // not to gdcm, without asking.
1078          // default is NOT TO LOAD, in order not to confuse ITK users (and others!).
1079
1080          if ( !FH->GetKeepOverlays() ) // mask spurious bits ! (overlay are NOT loaded!)
1081          {
1082             pmask = pmask >> ( BitsAllocated - BitsStored );
1083          }
1084          // else : it's up to the user to manage the 'pixels + overlays' he just loaded!
1085
1086          uint16_t *deb = (uint16_t*)Raw;
1087
1088          if ( !PixelSign )  // Pixels are unsigned
1089          {
1090             for(int i = 0; i<l; i++)
1091             {  
1092                *deb = (*deb >> (BitsStored - HighBitPosition - 1)) & pmask ;
1093                deb++;
1094             }
1095          }
1096          else // Pixels are signed
1097          {
1098             // Hope there is never ACR-NEMA-like overlays within signed pixels (?!?)
1099
1100             // smask : to check the 'sign' when BitsStored != BitsAllocated
1101             uint16_t smask = 0x0001;
1102             smask = smask << ( 16 - (BitsAllocated - BitsStored + 1) );
1103             // nmask : to propagate sign bit on negative values
1104             int16_t nmask = (int16_t)0x8000;  
1105             nmask = nmask >> ( BitsAllocated - BitsStored - 1 );
1106
1107             for(int i = 0; i<l; i++)
1108             {
1109                *deb = *deb >> (BitsStored - HighBitPosition - 1);
1110                if ( *deb & smask )
1111                {
1112                   *deb = *deb | nmask;
1113                }
1114                else
1115                {
1116                   *deb = *deb & pmask;
1117                }
1118                deb++;
1119             }
1120          }
1121       }
1122       else if ( BitsAllocated == 32 )
1123       { 
1124          // pmask : to mask the 'unused bits' (may contain overlays)
1125          uint32_t pmask = 0xffffffff;
1126          pmask = pmask >> ( BitsAllocated - BitsStored );
1127
1128          uint32_t *deb = (uint32_t*)Raw;
1129
1130          if ( !PixelSign )
1131          {
1132             for(int i = 0; i<l; i++)
1133             {             
1134                *deb = (*deb >> (BitsStored - HighBitPosition - 1)) & pmask;
1135                deb++;
1136             }
1137          }
1138          else
1139          {
1140             // smask : to check the 'sign' when BitsStored != BitsAllocated
1141             uint32_t smask = 0x00000001;
1142             smask = smask >> ( 32 - (BitsAllocated - BitsStored +1 ));
1143             // nmask : to propagate sign bit on negative values
1144             int32_t nmask = 0x80000000;   
1145             nmask = nmask >> ( BitsAllocated - BitsStored -1 );
1146
1147             for(int i = 0; i<l; i++)
1148             {
1149                *deb = *deb >> (BitsStored - HighBitPosition - 1);
1150                if ( *deb & smask )
1151                   *deb = *deb | nmask;
1152                else                
1153                  *deb = *deb & pmask; 
1154                deb++;
1155             }
1156          }
1157       }
1158       else
1159       {
1160          gdcmWarningMacro("Weird image (BitsAllocated !=8, 12, 16, 32)");
1161          throw FormatError( "Weird image !?" );
1162       }
1163    }
1164    return true;
1165 }
1166
1167 /**
1168  * \brief   Convert (Red plane, Green plane, Blue plane) to RGB pixels
1169  * \warning Works on all the frames at a time
1170  */
1171 void PixelReadConvert::ConvertRGBPlanesToRGBPixels()
1172 {
1173    gdcmWarningMacro("--> ConvertRGBPlanesToRGBPixels");
1174
1175    uint8_t *localRaw = Raw;
1176    uint8_t *copyRaw = new uint8_t[ RawSize ];
1177    memmove( copyRaw, localRaw, RawSize );
1178
1179    int l = XSize * YSize * ZSize;
1180
1181    uint8_t *a = copyRaw;
1182    uint8_t *b = copyRaw + l;
1183    uint8_t *c = copyRaw + l + l;
1184
1185    for (int j = 0; j < l; j++)
1186    {
1187       *(localRaw++) = *(a++);
1188       *(localRaw++) = *(b++);
1189       *(localRaw++) = *(c++);
1190    }
1191    delete[] copyRaw;
1192 }
1193
1194 /**
1195  * \brief   Convert (cY plane, cB plane, cR plane) to RGB pixels
1196  * \warning Works on all the frames at a time
1197  */
1198 void PixelReadConvert::ConvertYcBcRPlanesToRGBPixels()
1199 {
1200   // Remarks for YBR newbees :
1201   // YBR_FULL works very much like RGB, i.e. three samples per pixel, 
1202   // just the color space is YCbCr instead of RGB. This is particularly useful
1203   // for doppler ultrasound where most of the image is grayscale 
1204   // (i.e. only populates the Y components) and Cb and Cr are mostly zero,
1205   // except for the few patches of color on the image.
1206   // On such images, RLE achieves a compression ratio that is much better 
1207   // than the compression ratio on an equivalent RGB image. 
1208
1209    gdcmWarningMacro("--> ConvertYcBcRPlanesToRGBPixels");
1210
1211    uint8_t *localRaw = Raw;
1212    uint8_t *copyRaw = new uint8_t[ RawSize ];
1213    memmove( copyRaw, localRaw, RawSize );
1214
1215    // to see the tricks about YBR_FULL, YBR_FULL_422,
1216    // YBR_PARTIAL_422, YBR_ICT, YBR_RCT have a look at :
1217    // ftp://medical.nema.org/medical/dicom/final/sup61_ft.pdf
1218    // and be *very* affraid
1219    //
1220
1221    /// \todo : find an example to see how 3rd dim and 4th dim work together
1222    int l        = XSize * YSize * TSize;
1223    int nbFrames = ZSize;
1224
1225    uint8_t *a = copyRaw + 0;
1226    uint8_t *b = copyRaw + l;
1227    uint8_t *c = copyRaw + l+ l;
1228    int32_t R, G, B;
1229
1230    ///  We replaced easy to understand but time consuming floating point
1231    ///  computations by the 'well known' integer computation counterpart
1232    ///  Refer to :
1233    ///            http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf
1234    ///  for code optimisation.
1235
1236    for ( int i = 0; i < nbFrames; i++ )
1237    {
1238       for ( int j = 0; j < l; j++ )
1239       {
1240          R = 38142 *(*a-16) + 52298 *(*c -128);
1241          G = 38142 *(*a-16) - 26640 *(*c -128) - 12845 *(*b -128);
1242          B = 38142 *(*a-16) + 66093 *(*b -128);
1243
1244          R = (R+16384)>>15;
1245          G = (G+16384)>>15;
1246          B = (B+16384)>>15;
1247
1248          if (R < 0)   R = 0;
1249          if (G < 0)   G = 0;
1250          if (B < 0)   B = 0;
1251          if (R > 255) R = 255;
1252          if (G > 255) G = 255;
1253          if (B > 255) B = 255;
1254
1255          *(localRaw++) = (uint8_t)R;
1256          *(localRaw++) = (uint8_t)G;
1257          *(localRaw++) = (uint8_t)B;
1258          a++;
1259          b++;
1260          c++;
1261       }
1262    }
1263    delete[] copyRaw;
1264 }
1265
1266 /// \brief Deals with the color decoding i.e. handle:
1267 ///   - R, G, B planes (as opposed to RGB pixels)
1268 ///   - YBR (various) encodings.
1269 ///   - LUT[s] (or "PALETTE COLOR").
1270
1271 void PixelReadConvert::ConvertHandleColor()
1272 {
1273    //////////////////////////////////
1274    // Deal with the color decoding i.e. handle:
1275    //   - R, G, B planes (as opposed to RGB pixels)
1276    //   - YBR (various) encodings.
1277    //   - LUT[s] (or "PALETTE COLOR").
1278    //
1279    // The classification in the color decoding schema is based on the blending
1280    // of two Dicom tags values:
1281    // * "Photometric Interpretation" for which we have the cases:
1282    //  - [Photo A] MONOCHROME[1|2] pictures,
1283    //  - [Photo B] RGB or YBR_FULL_422 (which acts as RGB),
1284    //  - [Photo C] YBR_* (with the above exception of YBR_FULL_422)
1285    //  - [Photo D] "PALETTE COLOR" which indicates the presence of LUT[s].
1286    // * "Planar Configuration" for which we have the cases:
1287    //  - [Planar 0] 0 then Pixels are already RGB
1288    //  - [Planar 1] 1 then we have 3 planes : R, G, B,
1289    //  - [Planar 2] 2 then we have 1 gray Plane and 3 LUTs
1290    //
1291    // Now in theory, one could expect some coherence when blending the above
1292    // cases. For example we should not encounter files belonging at the
1293    // time to case [Planar 0] and case [Photo D].
1294    // Alas, this was only theory ! Because in practice some odd (read ill
1295    // formated Dicom) files (e.g. gdcmData/US-PAL-8-10x-echo.dcm) we encounter:
1296    //     - "Planar Configuration" = 0,
1297    //     - "Photometric Interpretation" = "PALETTE COLOR".
1298    // Hence gdcm will use the folowing "heuristic" in order to be tolerant
1299    // towards Dicom-non-conformant files:
1300    //   << whatever the "Planar Configuration" value might be, a
1301    //      "Photometric Interpretation" set to "PALETTE COLOR" forces
1302    //      a LUT intervention >>
1303    //
1304    // Now we are left with the following handling of the cases:
1305    // - [Planar 0] OR  [Photo A] no color decoding (since respectively
1306    //       Pixels are already RGB and monochrome pictures have no color :),
1307    // - [Planar 1] AND [Photo B] handled with ConvertRGBPlanesToRGBPixels()
1308    // - [Planar 1] AND [Photo C] handled with ConvertYcBcRPlanesToRGBPixels()
1309    // - [Planar 2] OR  [Photo D] requires LUT intervention.
1310
1311    gdcmDebugMacro("--> ConvertHandleColor "
1312                      << "Planar Configuration " << PlanarConfiguration );
1313
1314    if ( ! IsRawRGB() )
1315    {
1316       // [Planar 2] OR  [Photo D]: LUT intervention done outside
1317       gdcmDebugMacro("--> RawRGB : LUT intervention done outside");
1318       return;
1319    }
1320                                                                                 
1321    if ( PlanarConfiguration == 1 )
1322    {
1323       if ( IsYBRFull )
1324       {
1325          // [Planar 1] AND [Photo C] (remember YBR_FULL_422 acts as RGB)
1326          gdcmDebugMacro("--> YBRFull");
1327          ConvertYcBcRPlanesToRGBPixels();
1328       }
1329       else
1330       {
1331          // [Planar 1] AND [Photo C]
1332          gdcmDebugMacro("--> YBRFull");
1333          ConvertRGBPlanesToRGBPixels();
1334       }
1335       return;
1336    }
1337                                                                                 
1338    // When planarConf is 0, and RLELossless (forbidden by Dicom norm)
1339    // pixels need to be RGB-fyied anyway
1340
1341    if (IsRLELossless)
1342    { 
1343      gdcmDebugMacro("--> RLE Lossless");
1344      ConvertRGBPlanesToRGBPixels();
1345    }
1346
1347    // In *normal *case, when planarConf is 0, pixels are already in RGB
1348 }
1349
1350 /// Computes the Pixels Size
1351 void PixelReadConvert::ComputeRawAndRGBSizes()
1352 {
1353    int bitsAllocated = BitsAllocated;
1354    // Number of "Bits Allocated" is fixed to 16 when it's 12, since
1355    // in this case we will expand the image to 16 bits (see
1356    //    \ref ReadAndDecompress12BitsTo16Bits() )
1357    if (  BitsAllocated == 12 )
1358    {
1359       bitsAllocated = 16;
1360    }
1361                                                                                 
1362    RawSize =  XSize * YSize * ZSize * TSize
1363                      * ( bitsAllocated / 8 )
1364                      * SamplesPerPixel;
1365    if ( HasLUT )
1366    {
1367       RGBSize = 3 * RawSize; // works for 8 and 16 bits per Pixel
1368    }
1369    else
1370    {
1371       RGBSize = RawSize;
1372       
1373    }
1374    RawSize += RawSize%2;
1375    RGBSize += RGBSize%2;
1376 }
1377
1378 /// Allocates room for RGB Pixels
1379 void PixelReadConvert::AllocateRGB()
1380 {
1381   if ( RGB )
1382      delete [] RGB;
1383   RGB = new uint8_t[RGBSize];
1384 }
1385
1386 /// Allocates room for RAW Pixels
1387 void PixelReadConvert::AllocateRaw()
1388 {
1389   if ( Raw )
1390      delete [] Raw;
1391   Raw = new uint8_t[RawSize];
1392 }
1393
1394 //-----------------------------------------------------------------------------
1395 // Print
1396 /**
1397  * \brief        Print self.
1398  * @param indent Indentation string to be prepended during printing.
1399  * @param os     Stream to print to.
1400  */
1401 void PixelReadConvert::Print( std::ostream &os, std::string const &indent )
1402 {
1403    os << indent
1404       << "--- Pixel information -------------------------"
1405       << std::endl;
1406    os << indent
1407       << "Pixel Data: offset " << PixelOffset
1408       << " x(" << std::hex << PixelOffset << std::dec
1409       << ")   length " << PixelDataLength
1410       << " x(" << std::hex << PixelDataLength << std::dec
1411       << ")" << std::endl;
1412
1413    if ( IsRLELossless )
1414    {
1415       if ( RLEInfo )
1416       {
1417          RLEInfo->Print( os, indent );
1418       }
1419       else
1420       {
1421          gdcmWarningMacro("Set as RLE file but NO RLEinfo present.");
1422       }
1423    }
1424
1425    if ( IsJPEG2000 || IsJPEGLossless || IsJPEGLossy || IsJPEGLS )
1426    {
1427       if ( JPEGInfo )
1428       {
1429          JPEGInfo->Print( os, indent );
1430       }
1431       else
1432       {
1433          gdcmWarningMacro("Set as JPEG file but NO JPEGinfo present.");
1434       }
1435    }
1436 }
1437
1438 /**
1439  * \brief   CallStartMethod
1440  */
1441 void PixelReadConvert::CallStartMethod()
1442 {
1443    Progress = 0.0f;
1444    Abort    = false;
1445    CommandManager::ExecuteCommand(FH,CMD_STARTPROGRESS);
1446 }
1447
1448 /**
1449  * \brief   CallProgressMethod
1450  */
1451 void PixelReadConvert::CallProgressMethod()
1452 {
1453    CommandManager::ExecuteCommand(FH,CMD_PROGRESS);
1454 }
1455
1456 /**
1457  * \brief   CallEndMethod
1458  */
1459 void PixelReadConvert::CallEndMethod()
1460 {
1461    Progress = 1.0f;
1462    CommandManager::ExecuteCommand(FH,CMD_ENDPROGRESS);
1463 }
1464
1465
1466 //-----------------------------------------------------------------------------
1467 } // end namespace gdcm
1468
1469 // Note to developpers :
1470 // Here is a very detailled post from David Clunie, on the troubles caused 
1471 // 'non standard' LUT and LUT description
1472 // We shall have to take it into accound in our code.
1473 // Some day ...
1474
1475
1476 /*
1477 Subject: Problem with VOI LUTs in Agfa and Fuji CR and GE DX images, was Re: VOI LUT issues
1478 Date: Sun, 06 Feb 2005 17:13:40 GMT
1479 From: David Clunie <dclunie@dclunie.com>
1480 Reply-To: dclunie@dclunie.com
1481 Newsgroups: comp.protocols.dicom
1482 References: <1107553502.040221.189550@o13g2000cwo.googlegroups.com>
1483
1484 > THE LUT that comes with [my] image claims to be 16-bit, but none of the
1485 > values goes higher than 4095.  That being said, though, none of my
1486 > original pixel values goes higher than that, either.  I have read
1487 > elsewhere on this group that when that happens you are supposed to
1488 > adjust the LUT.  Can someone be more specific?  There was a thread from
1489 > 2002 where Marco and David were mentioning doing precisely that.
1490 >
1491 > Thanks
1492 >
1493 > -carlos rodriguez
1494
1495
1496 You have encountered the well known "we know what the standard says but
1497 we are going to ignore it and do what we have been doing for almost
1498 a decade regardless" CR vendor bug. Agfa started this, but they are not
1499 the only vendor doing this now; GE and Fuji may have joined the club.
1500
1501 Sadly, one needs to look at the LUT Data, figure out what the maximum
1502 value actually encoded is, and find the next highest power of 2 (e.g.
1503 212 in this case), to figure out what the range of the data is
1504 supposed to be. I have assumed that if the maximum value in the LUT
1505 data is less than a power of 2 minus 1 (e.g. 0xebc) then the intent
1506 of the vendor was not to use the maximum available grayscale range
1507 of the display (e.g. the maximum is 0xfff in this case). An alternative
1508 would be to scale to the actual maximum rather than a power of two.
1509
1510 Very irritating, and in theory not totally reliable if one really
1511 intended the full 16 bits and only used, say 15, but that is extremely
1512 unlikely since everything would be too dark, and this heuristic
1513 seems to work OK.
1514
1515 There has never been anything in the standard that describes having
1516 to go through these convolutions. Since the only value in the
1517 standard that describes the bit depth of the LUT values is LUT
1518 Descriptor value 3 and that is (usually) always required to be
1519 either 8 or 16, it mystifies me how the creators' of these images
1520 imagine that the receiver is going to divine the range that is intended. Further, the standard is quite explicit that this 3rd
1521 value defines the range of LUT values, but as far as I am aware, all
1522 the vendors are ignoring the standard and indeed sending a third value
1523 of 16 in all cases.
1524
1525 This problem is not confined to CR, and is also seen with DX products.
1526
1527 Typically I have seen:
1528
1529 - Agfa CR, which usually (always ?) sends LUTs, values up to 0x0fff
1530 - Fuji CR, which occasionally send LUTs, values up to 0x03ff
1531 - GE DX, for presentation, which always have LUTs, up to 0x3fff
1532
1533 Swissray, Siemens, Philips, Canon and Kodak never seem to send VOI LUTs
1534 at this point (which is a whole other problem). Note that the presence
1535 or absence of a VOI LUT as opposed to window values may be configurable
1536 on the modality in some cases, and I have just looked at what I happen
1537 to have received from a myriad of sites over whose configuration I have
1538 no control. This may be why the majority of Fuji images have no VOI LUTs,
1539 but a few do (or it may be the Siemens system that these Fuji images went
1540 through that perhaps added it). I do have some test Hologic DX images that
1541 are not from a clinical site that do actually get this right (a value
1542 of 12 for the third value and a max of 0xfff).
1543
1544 Since almost every vendor that I have encountered that encodes LUTs
1545 makes this mistake, perhaps it is time to amend the standard to warn
1546 implementor's of receivers and/or sanction this bad behavior. We have
1547 talked about this in the past in WG 6 but so far everyone has been
1548 reluctant to write into the standard such a comment. Maybe it is time
1549 to try again, since if one is not aware of this problem, one cannot
1550 effectively implement display using VOI LUTs, and there is a vast
1551 installed base to contend with.
1552
1553 I did not check presentation states, in which VOI LUTs could also be
1554 encountered, for the prevalence of this mistake, nor did I look at the
1555 encoding of Modality LUT's, which are unusual. Nor did I check digital
1556 mammography images. I would be interested to hear from anyone who has.
1557
1558 David
1559
1560 PS. The following older thread in this newsgroup discusses this:
1561
1562 "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"
1563
1564 PPS. From a historical perspective, the following may be of interest.
1565
1566 In the original standard in 1993, all that was said about this was a
1567 reference to the corresponding such where Modality LUTs are described
1568 that said:
1569
1570 "The third value specifies the number of bits for each entry in the
1571 LUT Data. It shall take the value 8 or 16. The LUT Data shall be stored
1572 in a format equivalent to 8 or 16 bits allocated and high bit equal
1573 1-bits allocated."
1574
1575 Since the high bit hint was not apparently explicit enough, a very
1576 early CP, CP 15 (submitted by Agfa as it happens), replaced this with:
1577
1578 "The third value conveys the range of LUT entry values. It shall take
1579 the value 8 or 16, corresponding with the LUT entry value range of
1580 256 or 65536.
1581
1582 Note:    The third value is not required for describing the
1583     LUT data and is only included for informational usage
1584     and for maintaining compatibility with ACRNEMA 2.0.
1585
1586 The LUT Data contains the LUT entry values."
1587
1588 That is how it read in the 1996, 1998 and 1999 editions.
1589
1590 By the 2000 edition, Supplement 33 that introduced presentation states
1591 extensively reworked this entire section and tried to explain this in
1592 different words:
1593
1594 "The output range is from 0 to 2^n-1 where n is the third value of LUT
1595 Descriptor. This range is always unsigned."
1596
1597 and also added a note to spell out what the output range meant in the
1598 VOI LUT section:
1599
1600 "9. The output of the Window Center/Width or VOI LUT transformation
1601 is either implicitly scaled to the full range of the display device
1602 if there is no succeeding transformation defined, or implicitly scaled
1603 to the full input range of the succeeding transformation step (such as
1604 the Presentation LUT), if present. See C.11.6.1."
1605
1606 It still reads this way in the 2004 edition.
1607
1608 Note that LUTs in other applications than the general VOI LUT allow for
1609 values other than 8 or 16 in the third value of LUT descriptor to permit
1610 ranges other than 0 to 255 or 65535.
1611
1612 In addition, the DX Image Module specializes the VOI LUT
1613 attributes as follows, in PS 3.3 section C.8.11.3.1.5 (added in Sup 32):
1614
1615 "The third value specifies the number of bits for each entry in the LUT
1616 Data (analogous to ìbits storedî). It shall be between 10-16. The LUT
1617 Data shall be stored in a format equivalent to 16 ìbits allocatedî and
1618 ìhigh bitî equal to ìbits storedî - 1. The third value conveys the range
1619 of LUT entry values. These unsigned LUT entry values shall range between
1620 0 and 2^n-1, where n is the third value of the LUT Descriptor."
1621
1622 So in the case of the GE DX for presentation images, the third value of
1623 LUT descriptor is allowed to be and probably should be 14 rather than 16.
1624
1625 */