]> Creatis software - gdcm.git/blob - src/gdcmPixelReadConvert.cxx
Fix to be able to read Jpeg images 16/8.
[gdcm.git] / src / gdcmPixelReadConvert.cxx
1 /*=========================================================================
2  
3   Program:   gdcm
4   Module:    $RCSfile: gdcmPixelReadConvert.cxx,v $
5   Language:  C++
6   Date:      $Date: 2007/09/03 16:34:58 $
7   Version:   $Revision: 1.118 $
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      int dummy;
599      if (BitsStored == 8 && BitsAllocated==16)
600         dummy = 16;
601      else
602         dummy = BitsStored;
603      
604      JPEGInfo->DecompressFromFile(fp, Raw, /*BitsStored*/ dummy , numberBytes, length );
605      return true;
606    }
607 }
608
609 /**
610  * \brief Build Red/Green/Blue/Alpha LUT from File when :
611  *         - (0028,0004) : Photometric Interpretation == [PALETTE COLOR ]
612  *         and
613  *         - (0028,1101),(0028,1102),(0028,1102)
614  *            xxx Palette Color Lookup Table Descriptor are found
615  *          and
616  *         - (0028,1201),(0028,1202),(0028,1202)
617  *           xxx Palette Color Lookup Table Data - are found
618  * \warning does NOT deal with :
619  *   - 0028 1100 Gray Lookup Table Descriptor (Retired)
620  *   - 0028 1221 Segmented Red Palette Color Lookup Table Data
621  *   - 0028 1222 Segmented Green Palette Color Lookup Table Data
622  *   - 0028 1223 Segmented Blue Palette Color Lookup Table Data
623  *   no known Dicom reader deals with them :-(
624  * @return a RGBA Lookup Table
625  */
626 void PixelReadConvert::BuildLUTRGBA()
627 {
628
629    // Note to code reviewers :
630    // The problem is *much more* complicated, since a lot of manufacturers
631    // Don't follow the norm :
632    // have a look at David Clunie's remark at the end of this .cxx file.
633    if ( LutRGBA )
634    
635    {
636       return;
637    }
638    // Not so easy : see
639    // http://www.barre.nom.fr/medical/dicom2/limitations.html#Color%20Lookup%20Tables
640                                                                                 
641    if ( ! IsPaletteColor )
642    {
643       return;
644    }
645                                                                                 
646    if (   LutRedDescriptor   == GDCM_UNFOUND
647        || LutGreenDescriptor == GDCM_UNFOUND
648        || LutBlueDescriptor  == GDCM_UNFOUND )
649    {
650       gdcmWarningMacro( "(At least) a LUT Descriptor is missing" );
651       return;
652    }
653
654    ////////////////////////////////////////////
655    // Extract the info from the LUT descriptors
656    int lengthR;   // Red LUT length in Bytes
657    int debR;      // Subscript of the first Lut Value
658    int nbitsR;    // Lut item size (in Bits)
659    int nbRead;    // nb of items in LUT descriptor (must be = 3)
660
661    nbRead = sscanf( LutRedDescriptor.c_str(),
662                         "%d\\%d\\%d",
663                         &lengthR, &debR, &nbitsR );
664    if ( nbRead != 3 )
665    {
666       gdcmWarningMacro( "Wrong Red LUT descriptor" );
667    }                                                                                
668    int lengthG;  // Green LUT length in Bytes
669    int debG;     // Subscript of the first Lut Value
670    int nbitsG;   // Lut item size (in Bits)
671
672    nbRead = sscanf( LutGreenDescriptor.c_str(),
673                     "%d\\%d\\%d",
674                     &lengthG, &debG, &nbitsG );  
675    if ( nbRead != 3 )
676    {
677       gdcmWarningMacro( "Wrong Green LUT descriptor" );
678    }
679                                                                                 
680    int lengthB;  // Blue LUT length in Bytes
681    int debB;     // Subscript of the first Lut Value
682    int nbitsB;   // Lut item size (in Bits)
683    nbRead = sscanf( LutRedDescriptor.c_str(),
684                     "%d\\%d\\%d",
685                     &lengthB, &debB, &nbitsB );
686    if ( nbRead != 3 )
687    {
688       gdcmWarningMacro( "Wrong Blue LUT descriptor" );
689    }
690  
691    gdcmDebugMacro(" lengthR " << lengthR << " debR " 
692                 << debR << " nbitsR " << nbitsR);
693    gdcmDebugMacro(" lengthG " << lengthG << " debG " 
694                 << debG << " nbitsG " << nbitsG);
695    gdcmDebugMacro(" lengthB " << lengthB << " debB " 
696                 << debB << " nbitsB " << nbitsB);
697
698    if ( !lengthR ) // if = 2^16, this shall be 0 see : CP-143
699       lengthR=65536;
700    if ( !lengthG ) // if = 2^16, this shall be 0
701       lengthG=65536;
702    if ( !lengthB ) // if = 2^16, this shall be 0
703       lengthB=65536; 
704                                                                                 
705    ////////////////////////////////////////////////////////
706
707    if ( ( ! LutRedData ) || ( ! LutGreenData ) || ( ! LutBlueData ) )
708    {
709       gdcmWarningMacro( "(At least) a LUT is missing" );
710       return;
711    }
712
713    // -------------------------------------------------------------
714    
715    if ( BitsAllocated <= 8 )
716    {
717       // forge the 4 * 8 Bits Red/Green/Blue/Alpha LUT
718       LutRGBA = new uint8_t[ 1024 ]; // 256 * 4 (R, G, B, Alpha)
719       if ( !LutRGBA )
720          return;
721       LutItemNumber = 256;
722       LutItemSize   = 8;
723       memset( LutRGBA, 0, 1024 );
724                                                                                 
725       int mult;
726       if ( ( nbitsR == 16 ) && ( BitsAllocated == 8 ) )
727       {
728          // when LUT item size is different than pixel size
729          mult = 2; // high byte must be = low byte
730       }
731       else
732       {
733          // See PS 3.3-2003 C.11.1.1.2 p 619
734          mult = 1;
735       }
736                                                                                 
737       // if we get a black image, let's just remove the '+1'
738       // from 'i*mult+1' and check again
739       // if it works, we shall have to check the 3 Palettes
740       // to see which byte is ==0 (first one, or second one)
741       // and fix the code
742       // We give up the checking to avoid some (useless ?) overhead
743       // (optimistic asumption)
744       int i;
745       uint8_t *a;
746
747       //take "Subscript of the first Lut Value" (debR,debG,debB) into account!
748
749       //FIXME :  +1 : to get 'low value' byte
750       //         Trouble expected on Big Endian Processors ?
751       //         16 BIts Per Pixel Palette Color to be swapped?
752
753       a = LutRGBA + 0 + debR;
754       for( i=0; i < lengthR; ++i )
755       {
756          *a = LutRedData[i*mult+1]; 
757          a += 4;
758       }
759                                                                                 
760       a = LutRGBA + 1 + debG;
761       for( i=0; i < lengthG; ++i)
762       {
763          *a = LutGreenData[i*mult+1];
764          a += 4;
765       }
766                                                                                 
767       a = LutRGBA + 2 + debB;
768       for(i=0; i < lengthB; ++i)
769       {
770          *a = LutBlueData[i*mult+1];
771          a += 4;
772       }
773                                     
774       a = LutRGBA + 3 ;
775       for(i=0; i < 256; ++i)
776       {
777          *a = 1; // Alpha component
778          a += 4;
779       }
780    }
781    else
782    {
783       // Probabely the same stuff is to be done for 16 Bits Pixels
784       // with 65536 entries LUT ?!?
785       // Still looking for accurate info on the web :-(
786
787       gdcmWarningMacro( "Sorry Palette Color Lookup Tables not yet dealt with"
788                          << " for 16 Bits Per Pixel images" );
789
790       // forge the 4 * 16 Bits Red/Green/Blue/Alpha LUT
791
792       LutRGBA = (uint8_t *)new uint16_t[ 65536*4 ]; // 2^16 * 4 (R, G, B, Alpha)
793       if ( !LutRGBA )
794          return;
795       memset( LutRGBA, 0, 65536*4*2 );  // 16 bits = 2 bytes ;-)
796
797       LutItemNumber = 65536;
798       LutItemSize   = 16;
799
800       int i;
801       uint16_t *a16;
802
803       //take "Subscript of the first Lut Value" (debR,debG,debB) into account!
804
805       a16 = (uint16_t*)LutRGBA + 0 + debR;
806       for( i=0; i < lengthR; ++i )
807       {
808          *a16 = ((uint16_t*)LutRedData)[i];
809          a16 += 4;
810       }
811                                                                               
812       a16 = (uint16_t*)LutRGBA + 1 + debG;
813       for( i=0; i < lengthG; ++i)
814       {
815          *a16 = ((uint16_t*)LutGreenData)[i];
816          a16 += 4;
817       }
818                                                                                 
819       a16 = (uint16_t*)LutRGBA + 2 + debB;
820       for(i=0; i < lengthB; ++i)
821       {
822          *a16 = ((uint16_t*)LutBlueData)[i];
823          a16 += 4;
824       }
825                                                                              
826       a16 = (uint16_t*)LutRGBA + 3 ;
827       for(i=0; i < 65536; ++i)
828       {
829          *a16 = 1; // Alpha component
830          a16 += 4;
831       }
832 /* Just to 'see' the LUT, at debug time
833 // Don't remove this commented out code.
834
835       a16=(uint16_t*)LutRGBA;
836       for (int j=0;j<65536;j++)
837       {
838          std::cout << *a16     << " " << *(a16+1) << " "
839                    << *(a16+2) << " " << *(a16+3) << std::endl;
840          a16+=4;
841       }
842 */
843    }
844 }
845
846 /**
847  * \brief Swap the bytes, according to \ref SwapCode.
848  */
849 void PixelReadConvert::ConvertSwapZone()
850 {
851    unsigned int i;
852
853    // If this file is 'ImplicitVR BigEndian PrivateGE Transfer Syntax', 
854    // then the header is in little endian format and the pixel data is in 
855    // big endian format.  When reading the header, GDCM has already established
856    // a byte swapping code suitable for this machine to read the
857    // header. In TS::ImplicitVRBigEndianPrivateGE, this code will need
858    // to be switched in order to read the pixel data.  This must be
859    // done REGARDLESS of the processor endianess!
860    //
861    // Example:  Assume we are on a little endian machine.  When
862    // GDCM reads the header, the header will match the machine
863    // endianess and the swap code will be established as a no-op.
864    // When GDCM reaches the pixel data, it will need to switch the
865    // swap code to do big endian to little endian conversion.
866    //
867    // Now, assume we are on a big endian machine.  When GDCM reads the
868    // header, the header will be recognized as a different endianess
869    // than the machine endianess, and a swap code will be established
870    // to convert from little endian to big endian.  When GDCM readers
871    // the pixel data, the pixel data endianess will now match the
872    // machine endianess.  But we currently have a swap code that
873    // converts from little endian to big endian.  In this case, we
874    // need to switch the swap code to a no-op.
875    //
876    // Therefore, in either case, if the file is in
877    // 'ImplicitVR BigEndian PrivateGE Transfer Syntax', then GDCM needs to switch
878    // the byte swapping code when entering the pixel data.
879    
880    int tempSwapCode = SwapCode;
881    if ( IsPrivateGETransferSyntax )
882    {
883       gdcmWarningMacro(" IsPrivateGETransferSyntax found; turn the SwapCode"); 
884       // PrivateGETransferSyntax only exists for 'true' Dicom images
885       // we assume there is no 'exotic' 32 bits endianess!
886       if (SwapCode == 1234) 
887       {
888          tempSwapCode = 4321;
889       }
890       else if (SwapCode == 4321)
891       {
892          tempSwapCode = 1234;
893       }
894    }
895     
896    if ( BitsAllocated == 16 )
897    {
898       uint16_t *im16 = (uint16_t*)Raw;
899       switch( tempSwapCode )
900       {
901          case 1234:
902             break;
903          case 3412:
904          case 2143:
905          case 4321:
906             for( i = 0; i < RawSize / 2; i++ )
907             {
908                im16[i]= (im16[i] >> 8) | (im16[i] << 8 );
909             }
910             break;
911          default:
912             gdcmWarningMacro("SwapCode value (16 bits) not allowed." 
913                         << tempSwapCode);
914       }
915    }
916    else if ( BitsAllocated == 32 )
917    {
918       uint32_t s32;
919       uint16_t high;
920       uint16_t low;
921       uint32_t *im32 = (uint32_t*)Raw;
922       switch ( tempSwapCode )
923       {
924          case 1234:
925             break;
926          case 4321:
927             for( i = 0; i < RawSize / 4; i++ )
928             {
929                low     = im32[i] & 0x0000ffff;  // 4321
930                high    = im32[i] >> 16;
931                high    = ( high >> 8 ) | ( high << 8 );
932                low     = ( low  >> 8 ) | ( low  << 8 );
933                s32     = low;
934                im32[i] = ( s32 << 16 ) | high;
935             }
936             break;
937          case 2143:
938             for( i = 0; i < RawSize / 4; i++ )
939             {
940                low     = im32[i] & 0x0000ffff;   // 2143
941                high    = im32[i] >> 16;
942                high    = ( high >> 8 ) | ( high << 8 );
943                low     = ( low  >> 8 ) | ( low  << 8 );
944                s32     = high;
945                im32[i] = ( s32 << 16 ) | low;
946             }
947             break;
948          case 3412:
949             for( i = 0; i < RawSize / 4; i++ )
950             {
951                low     = im32[i] & 0x0000ffff; // 3412
952                high    = im32[i] >> 16;
953                s32     = low;
954                im32[i] = ( s32 << 16 ) | high;
955             }
956             break;
957          default:
958             gdcmWarningMacro("SwapCode value (32 bits) not allowed." << tempSwapCode );
959       }
960    }
961 }
962
963 /**
964  * \brief Deal with endianness i.e. re-arange bytes inside the integer
965  */
966 void PixelReadConvert::ConvertReorderEndianity()
967 {
968    if ( BitsAllocated != 8 )
969    {
970       ConvertSwapZone();
971    }
972
973    // Special kludge in order to deal with xmedcon broken images:
974    if ( BitsAllocated == 16
975      && BitsStored < BitsAllocated
976      && !PixelSign )
977    {
978       int l = (int)( RawSize / ( BitsAllocated / 8 ) );
979       uint16_t *deb = (uint16_t *)Raw;
980       int l = (int)( RawSize / ( BitsAllocated / 8 ) );
981       uint16_t *deb = (uint16_t *)Raw;
982       for(int i = 0; i<l; i++)
983       {
984          if ( *deb == 0xffff )
985          {
986            *deb = 0;
987          }
988          deb++;
989       }
990    }
991 }
992
993 /**
994  * \brief Deal with Grey levels i.e. re-arange them
995  *        to have low values = dark, high values = bright
996  */
997 void PixelReadConvert::ConvertFixGreyLevels()
998 {
999    if (!IsMonochrome1)
1000       return;
1001
1002    uint32_t i; // to please M$VC6
1003    int16_t j;
1004
1005    if (!PixelSign)
1006    {
1007       if ( BitsAllocated == 8 )
1008       {
1009          uint8_t *deb = (uint8_t *)Raw;
1010          for (i=0; i<RawSize; i++)      
1011          {
1012             *deb = 255 - *deb;
1013             deb++;
1014          }
1015          return;
1016       }
1017
1018       if ( BitsAllocated == 16 )
1019       {
1020          uint16_t mask =1;
1021          for (j=0; j<BitsStored-1; j++)
1022          {
1023             mask = (mask << 1) +1; // will be fff when BitsStored=12
1024          }
1025
1026          uint16_t *deb = (uint16_t *)Raw;
1027          for (i=0; i<RawSize/2; i++)      
1028          {
1029             *deb = mask - *deb;
1030             deb++;
1031          }
1032          return;
1033        }
1034    }
1035    else
1036    {
1037       if ( BitsAllocated == 8 )
1038       {
1039          uint8_t smask8 = 255;
1040          uint8_t *deb = (uint8_t *)Raw;
1041          for (i=0; i<RawSize; i++)      
1042          {
1043             *deb = smask8 - *deb;
1044             deb++;
1045          }
1046          return;
1047       }
1048       if ( BitsAllocated == 16 )
1049       {
1050          uint16_t smask16 = 65535;
1051          uint16_t *deb = (uint16_t *)Raw;
1052          for (i=0; i<RawSize/2; i++)      
1053          {
1054             *deb = smask16 - *deb;
1055             deb++;
1056          }
1057          return;
1058       }
1059    }
1060 }
1061
1062 /**
1063  * \brief  Re-arrange the bits within the bytes.
1064  * @return Boolean always true
1065  */
1066 bool PixelReadConvert::ConvertReArrangeBits() throw ( FormatError )
1067 {
1068
1069    if ( BitsStored != BitsAllocated )
1070    {
1071       int l = (int)( RawSize / ( BitsAllocated / 8 ) );
1072       if ( BitsAllocated == 16 )
1073       {
1074          // pmask : to mask the 'unused bits' (may contain overlays)
1075          uint16_t pmask = 0xffff;
1076  
1077          // It's up to the user to remove overlays if any),
1078          // not to gdcm, witout asking !
1079          //pmask = pmask >> ( BitsAllocated - BitsStored );
1080
1081          uint16_t *deb = (uint16_t*)Raw;
1082
1083          if ( !PixelSign )  // Pixels are unsigned
1084          {
1085             for(int i = 0; i<l; i++)
1086             {  
1087               //                                                save CPU time
1088                *deb = (*deb >> (BitsStored - HighBitPosition - 1))/* & pmask */;
1089                deb++;
1090             }
1091          }
1092          else // Pixels are signed
1093          {
1094             // Hope there is never A
1095  
1096             // smask : to check the 'sign' when BitsStored != BitsAllocated
1097             uint16_t smask = 0x0001;
1098             smask = smask << ( 16 - (BitsAllocated - BitsStored + 1) );
1099             // nmask : to propagate sign bit on negative values
1100             int16_t nmask = (int16_t)0x8000;  
1101             nmask = nmask >> ( BitsAllocated - BitsStored - 1 );
1102  
1103             for(int i = 0; i<l; i++)
1104             {
1105                *deb = *deb >> (BitsStored - HighBitPosition - 1);
1106                if ( *deb & smask )
1107                {
1108                   *deb = *deb | nmask;
1109                }
1110                else
1111                {
1112                   *deb = *deb & pmask;
1113                }
1114                deb++;
1115             }
1116          }
1117       }
1118       else if ( BitsAllocated == 32 )
1119       {
1120          uint32_t *deb = (uint32_t*)Raw;
1121
1122          if ( !PixelSign )
1123          {
1124             for(int i = 0; i<l; i++)
1125             {             
1126                *deb = (*deb >> (BitsStored - HighBitPosition - 1)) & pmask;
1127                deb++;
1128             }
1129          }
1130          else
1131          {
1132             // smask : to check the 'sign' when BitsStored != BitsAllocated
1133             uint32_t smask = 0x00000001;
1134             smask = smask >> ( 32 - (BitsAllocated - BitsStored +1 ));
1135             // nmask : to propagate sign bit on negative values
1136             int32_t nmask = 0x80000000;   
1137             nmask = nmask >> ( BitsAllocated - BitsStored -1 );
1138
1139             for(int i = 0; i<l; i++)
1140             {
1141                *deb = *deb >> (BitsStored - HighBitPosition - 1);
1142                if ( *deb & smask )
1143                   *deb = *deb | nmask;
1144                else
1145                   *deb = *deb & pmask;
1146                deb++;
1147             }
1148          }
1149       }
1150       else
1151       {
1152          gdcmWarningMacro("Weird image (BitsAllocated !=8, 12, 16, 32)");
1153          throw FormatError( "Weird image !?" );
1154       }
1155    }
1156    return true;
1157 }
1158
1159 /**
1160  * \brief   Convert (Red plane, Green plane, Blue plane) to RGB pixels
1161  * \warning Works on all the frames at a time
1162  */
1163 void PixelReadConvert::ConvertRGBPlanesToRGBPixels()
1164 {
1165    gdcmWarningMacro("--> ConvertRGBPlanesToRGBPixels");
1166
1167    uint8_t *localRaw = Raw;
1168    uint8_t *copyRaw = new uint8_t[ RawSize ];
1169    memmove( copyRaw, localRaw, RawSize );
1170
1171    int l = XSize * YSize * ZSize;
1172
1173    uint8_t *a = copyRaw;
1174    uint8_t *b = copyRaw + l;
1175    uint8_t *c = copyRaw + l + l;
1176
1177    for (int j = 0; j < l; j++)
1178    {
1179       *(localRaw++) = *(a++);
1180       *(localRaw++) = *(b++);
1181       *(localRaw++) = *(c++);
1182    }
1183    delete[] copyRaw;
1184 }
1185
1186 /**
1187  * \brief   Convert (cY plane, cB plane, cR plane) to RGB pixels
1188  * \warning Works on all the frames at a time
1189  */
1190 void PixelReadConvert::ConvertYcBcRPlanesToRGBPixels()
1191 {
1192   // Remarks for YBR newbees :
1193   // YBR_FULL works very much like RGB, i.e. three samples per pixel, 
1194   // just the color space is YCbCr instead of RGB. This is particularly useful
1195   // for doppler ultrasound where most of the image is grayscale 
1196   // (i.e. only populates the Y components) and Cb and Cr are mostly zero,
1197   // except for the few patches of color on the image.
1198   // On such images, RLE achieves a compression ratio that is much better 
1199   // than the compression ratio on an equivalent RGB image. 
1200  
1201    gdcmWarningMacro("--> ConvertYcBcRPlanesToRGBPixels");
1202    
1203    uint8_t *localRaw = Raw;
1204    uint8_t *copyRaw = new uint8_t[ RawSize ];
1205    memmove( copyRaw, localRaw, RawSize );
1206
1207    // to see the tricks about YBR_FULL, YBR_FULL_422,
1208    // YBR_PARTIAL_422, YBR_ICT, YBR_RCT have a look at :
1209    // ftp://medical.nema.org/medical/dicom/final/sup61_ft.pdf
1210    // and be *very* affraid
1211    //
1212    
1213    /// \todo : find an example to see how 3rd dim and 4th dim work together
1214    int l        = XSize * YSize * TSize;
1215    int nbFrames = ZSize;
1216
1217    uint8_t *a = copyRaw + 0;
1218    uint8_t *b = copyRaw + l;
1219    uint8_t *c = copyRaw + l+ l;
1220    int32_t R, G, B;
1221
1222    ///  We replaced easy to understand but time consuming floating point
1223    ///  computations by the 'well known' integer computation counterpart
1224    ///  Refer to :
1225    ///            http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf
1226    ///  for code optimisation.
1227
1228    for ( int i = 0; i < nbFrames; i++ )
1229    {
1230       for ( int j = 0; j < l; j++ )
1231       {
1232          R = 38142 *(*a-16) + 52298 *(*c -128);
1233          G = 38142 *(*a-16) - 26640 *(*c -128) - 12845 *(*b -128);
1234          B = 38142 *(*a-16) + 66093 *(*b -128);
1235
1236          R = (R+16384)>>15;
1237          G = (G+16384)>>15;
1238          B = (B+16384)>>15;
1239
1240          if (R < 0)   R = 0;
1241          if (G < 0)   G = 0;
1242          if (B < 0)   B = 0;
1243          if (R > 255) R = 255;
1244          if (G > 255) G = 255;
1245          if (B > 255) B = 255;
1246
1247          *(localRaw++) = (uint8_t)R;
1248          *(localRaw++) = (uint8_t)G;
1249          *(localRaw++) = (uint8_t)B;
1250          a++;
1251          b++;
1252          c++;
1253       }
1254    }
1255    delete[] copyRaw;
1256 }
1257
1258 /// \brief Deals with the color decoding i.e. handle:
1259 ///   - R, G, B planes (as opposed to RGB pixels)
1260 ///   - YBR (various) encodings.
1261 ///   - LUT[s] (or "PALETTE COLOR").
1262
1263 void PixelReadConvert::ConvertHandleColor()
1264 {
1265    //////////////////////////////////
1266    // Deal 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    // The classification in the color decoding schema is based on the blending
1272    // of two Dicom tags values:
1273    // * "Photometric Interpretation" for which we have the cases:
1274    //  - [Photo A] MONOCHROME[1|2] pictures,
1275    //  - [Photo B] RGB or YBR_FULL_422 (which acts as RGB),
1276    //  - [Photo C] YBR_* (with the above exception of YBR_FULL_422)
1277    //  - [Photo D] "PALETTE COLOR" which indicates the presence of LUT[s].
1278    // * "Planar Configuration" for which we have the cases:
1279    //  - [Planar 0] 0 then Pixels are already RGB
1280    //  - [Planar 1] 1 then we have 3 planes : R, G, B,
1281    //  - [Planar 2] 2 then we have 1 gray Plane and 3 LUTs
1282    //
1283    // Now in theory, one could expect some coherence when blending the above
1284    // cases. For example we should not encounter files belonging at the
1285    // time to case [Planar 0] and case [Photo D].
1286    // Alas, this was only theory ! Because in practice some odd (read ill
1287    // formated Dicom) files (e.g. gdcmData/US-PAL-8-10x-echo.dcm) we encounter:
1288    //     - "Planar Configuration" = 0,
1289    //     - "Photometric Interpretation" = "PALETTE COLOR".
1290    // Hence gdcm will use the folowing "heuristic" in order to be tolerant
1291    // towards Dicom-non-conformant files:
1292    //   << whatever the "Planar Configuration" value might be, a
1293    //      "Photometric Interpretation" set to "PALETTE COLOR" forces
1294    //      a LUT intervention >>
1295    //
1296    // Now we are left with the following handling of the cases:
1297    // - [Planar 0] OR  [Photo A] no color decoding (since respectively
1298    //       Pixels are already RGB and monochrome pictures have no color :),
1299    // - [Planar 1] AND [Photo B] handled with ConvertRGBPlanesToRGBPixels()
1300    // - [Planar 1] AND [Photo C] handled with ConvertYcBcRPlanesToRGBPixels()
1301    // - [Planar 2] OR  [Photo D] requires LUT intervention.
1302
1303    gdcmDebugMacro("--> ConvertHandleColor "
1304                      << "Planar Configuration " << PlanarConfiguration );
1305
1306    if ( ! IsRawRGB() )
1307    {
1308       // [Planar 2] OR  [Photo D]: LUT intervention done outside
1309       gdcmDebugMacro("--> RawRGB : LUT intervention done outside");
1310       return;
1311    }
1312                                                                                 
1313    if ( PlanarConfiguration == 1 )
1314    {
1315       if ( IsYBRFull )
1316       {
1317          // [Planar 1] AND [Photo C] (remember YBR_FULL_422 acts as RGB)
1318          gdcmDebugMacro("--> YBRFull");
1319          ConvertYcBcRPlanesToRGBPixels();
1320       }
1321       else
1322       {
1323          // [Planar 1] AND [Photo C]
1324          gdcmDebugMacro("--> YBRFull");
1325          ConvertRGBPlanesToRGBPixels();
1326       }
1327       return;
1328    }
1329                                                                                 
1330    // When planarConf is 0, and RLELossless (forbidden by Dicom norm)
1331    // pixels need to be RGB-fyied anyway
1332
1333    if (IsRLELossless)
1334    { 
1335      gdcmDebugMacro("--> RLE Lossless");
1336      ConvertRGBPlanesToRGBPixels();
1337    }
1338
1339    // In *normal *case, when planarConf is 0, pixels are already in RGB
1340 }
1341
1342 /// Computes the Pixels Size
1343 void PixelReadConvert::ComputeRawAndRGBSizes()
1344 {
1345    int bitsAllocated = BitsAllocated;
1346    // Number of "Bits Allocated" is fixed to 16 when it's 12, since
1347    // in this case we will expand the image to 16 bits (see
1348    //    \ref ReadAndDecompress12BitsTo16Bits() )
1349    if (  BitsAllocated == 12 )
1350    {
1351       bitsAllocated = 16;
1352    }
1353                                                                                 
1354    RawSize =  XSize * YSize * ZSize * TSize
1355                      * ( bitsAllocated / 8 )
1356                      * SamplesPerPixel;
1357    if ( HasLUT )
1358    {
1359       RGBSize = 3 * RawSize; // works for 8 and 16 bits per Pixel
1360    }
1361    else
1362    {
1363       RGBSize = RawSize;
1364       
1365    }
1366    RawSize += RawSize%2;
1367    RGBSize += RGBSize%2;
1368 }
1369
1370 /// Allocates room for RGB Pixels
1371 void PixelReadConvert::AllocateRGB()
1372 {
1373   if ( RGB )
1374      delete [] RGB;
1375   RGB = new uint8_t[RGBSize];
1376 }
1377
1378 /// Allocates room for RAW Pixels
1379 void PixelReadConvert::AllocateRaw()
1380 {
1381   if ( Raw )
1382      delete [] Raw;
1383   Raw = new uint8_t[RawSize];
1384 }
1385
1386 //-----------------------------------------------------------------------------
1387 // Print
1388 /**
1389  * \brief        Print self.
1390  * @param indent Indentation string to be prepended during printing.
1391  * @param os     Stream to print to.
1392  */
1393 void PixelReadConvert::Print( std::ostream &os, std::string const &indent )
1394 {
1395    os << indent
1396       << "--- Pixel information -------------------------"
1397       << std::endl;
1398    os << indent
1399       << "Pixel Data: offset " << PixelOffset
1400       << " x(" << std::hex << PixelOffset << std::dec
1401       << ")   length " << PixelDataLength
1402       << " x(" << std::hex << PixelDataLength << std::dec
1403       << ")" << std::endl;
1404
1405    if ( IsRLELossless )
1406    {
1407       if ( RLEInfo )
1408       {
1409          RLEInfo->Print( os, indent );
1410       }
1411       else
1412       {
1413          gdcmWarningMacro("Set as RLE file but NO RLEinfo present.");
1414       }
1415    }
1416
1417    if ( IsJPEG2000 || IsJPEGLossless || IsJPEGLossy || IsJPEGLS )
1418    {
1419       if ( JPEGInfo )
1420       {
1421          JPEGInfo->Print( os, indent );
1422       }
1423       else
1424       {
1425          gdcmWarningMacro("Set as JPEG file but NO JPEGinfo present.");
1426       }
1427    }
1428 }
1429
1430 /**
1431  * \brief   CallStartMethod
1432  */
1433 void PixelReadConvert::CallStartMethod()
1434 {
1435    Progress = 0.0f;
1436    Abort    = false;
1437    CommandManager::ExecuteCommand(FH,CMD_STARTPROGRESS);
1438 }
1439
1440 /**
1441  * \brief   CallProgressMethod
1442  */
1443 void PixelReadConvert::CallProgressMethod()
1444 {
1445    CommandManager::ExecuteCommand(FH,CMD_PROGRESS);
1446 }
1447
1448 /**
1449  * \brief   CallEndMethod
1450  */
1451 void PixelReadConvert::CallEndMethod()
1452 {
1453    Progress = 1.0f;
1454    CommandManager::ExecuteCommand(FH,CMD_ENDPROGRESS);
1455 }
1456
1457
1458 //-----------------------------------------------------------------------------
1459 } // end namespace gdcm
1460
1461 // Note to developpers :
1462 // Here is a very detailled post from David Clunie, on the troubles caused 
1463 // 'non standard' LUT and LUT description
1464 // We shall have to take it into accound in our code.
1465 // Some day ...
1466
1467
1468 /*
1469 Subject: Problem with VOI LUTs in Agfa and Fuji CR and GE DX images, was Re: VOI LUT issues
1470 Date: Sun, 06 Feb 2005 17:13:40 GMT
1471 From: David Clunie <dclunie@dclunie.com>
1472 Reply-To: dclunie@dclunie.com
1473 Newsgroups: comp.protocols.dicom
1474 References: <1107553502.040221.189550@o13g2000cwo.googlegroups.com>
1475
1476 > THE LUT that comes with [my] image claims to be 16-bit, but none of the
1477 > values goes higher than 4095.  That being said, though, none of my
1478 > original pixel values goes higher than that, either.  I have read
1479 > elsewhere on this group that when that happens you are supposed to
1480 > adjust the LUT.  Can someone be more specific?  There was a thread from
1481 > 2002 where Marco and David were mentioning doing precisely that.
1482 >
1483 > Thanks
1484 >
1485 > -carlos rodriguez
1486
1487
1488 You have encountered the well known "we know what the standard says but
1489 we are going to ignore it and do what we have been doing for almost
1490 a decade regardless" CR vendor bug. Agfa started this, but they are not
1491 the only vendor doing this now; GE and Fuji may have joined the club.
1492
1493 Sadly, one needs to look at the LUT Data, figure out what the maximum
1494 value actually encoded is, and find the next highest power of 2 (e.g.
1495 212 in this case), to figure out what the range of the data is
1496 supposed to be. I have assumed that if the maximum value in the LUT
1497 data is less than a power of 2 minus 1 (e.g. 0xebc) then the intent
1498 of the vendor was not to use the maximum available grayscale range
1499 of the display (e.g. the maximum is 0xfff in this case). An alternative
1500 would be to scale to the actual maximum rather than a power of two.
1501
1502 Very irritating, and in theory not totally reliable if one really
1503 intended the full 16 bits and only used, say 15, but that is extremely
1504 unlikely since everything would be too dark, and this heuristic
1505 seems to work OK.
1506
1507 There has never been anything in the standard that describes having
1508 to go through these convolutions. Since the only value in the
1509 standard that describes the bit depth of the LUT values is LUT
1510 Descriptor value 3 and that is (usually) always required to be
1511 either 8 or 16, it mystifies me how the creators' of these images
1512 imagine that the receiver is going to divine the range that is intended. Further, the standard is quite explicit that this 3rd
1513 value defines the range of LUT values, but as far as I am aware, all
1514 the vendors are ignoring the standard and indeed sending a third value
1515 of 16 in all cases.
1516
1517 This problem is not confined to CR, and is also seen with DX products.
1518
1519 Typically I have seen:
1520
1521 - Agfa CR, which usually (always ?) sends LUTs, values up to 0x0fff
1522 - Fuji CR, which occasionally send LUTs, values up to 0x03ff
1523 - GE DX, for presentation, which always have LUTs, up to 0x3fff
1524
1525 Swissray, Siemens, Philips, Canon and Kodak never seem to send VOI LUTs
1526 at this point (which is a whole other problem). Note that the presence
1527 or absence of a VOI LUT as opposed to window values may be configurable
1528 on the modality in some cases, and I have just looked at what I happen
1529 to have received from a myriad of sites over whose configuration I have
1530 no control. This may be why the majority of Fuji images have no VOI LUTs,
1531 but a few do (or it may be the Siemens system that these Fuji images went
1532 through that perhaps added it). I do have some test Hologic DX images that
1533 are not from a clinical site that do actually get this right (a value
1534 of 12 for the third value and a max of 0xfff).
1535
1536 Since almost every vendor that I have encountered that encodes LUTs
1537 makes this mistake, perhaps it is time to amend the standard to warn
1538 implementor's of receivers and/or sanction this bad behavior. We have
1539 talked about this in the past in WG 6 but so far everyone has been
1540 reluctant to write into the standard such a comment. Maybe it is time
1541 to try again, since if one is not aware of this problem, one cannot
1542 effectively implement display using VOI LUTs, and there is a vast
1543 installed base to contend with.
1544
1545 I did not check presentation states, in which VOI LUTs could also be
1546 encountered, for the prevalence of this mistake, nor did I look at the
1547 encoding of Modality LUT's, which are unusual. Nor did I check digital
1548 mammography images. I would be interested to hear from anyone who has.
1549 I did not check presentation states, in which VOI LUTs could also be
1550 encountered, for the prevalence of this mistake, nor did I look at the
1551 encoding of Modality LUT's, which are unusual. Nor did I check digital
1552 mammography images. I would be interested to hear from anyone who has.
1553
1554 David
1555
1556 PS. The following older thread in this newsgroup discusses this:
1557
1558 "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"
1559
1560 PPS. From a historical perspective, the following may be of interest.
1561
1562 In the original standard in 1993, all that was said about this was a
1563 reference to the corresponding such where Modality LUTs are described
1564 that said:
1565
1566 "The third value specifies the number of bits for each entry in the
1567 LUT Data. It shall take the value 8 or 16. The LUT Data shall be stored
1568 in a format equivalent to 8 or 16 bits allocated and high bit equal
1569 1-bits allocated."
1570
1571 Since the high bit hint was not apparently explicit enough, a very
1572 early CP, CP 15 (submitted by Agfa as it happens), replaced this with:
1573
1574 "The third value conveys the range of LUT entry values. It shall take
1575 the value 8 or 16, corresponding with the LUT entry value range of
1576 256 or 65536.
1577
1578 Note:    The third value is not required for describing the
1579     LUT data and is only included for informational usage
1580     and for maintaining compatibility with ACRNEMA 2.0.
1581
1582 The LUT Data contains the LUT entry values."
1583
1584 That is how it read in the 1996, 1998 and 1999 editions.
1585
1586 By the 2000 edition, Supplement 33 that introduced presentation states
1587 extensively reworked this entire section and tried to explain this in
1588 different words:
1589
1590 "The output range is from 0 to 2^n-1 where n is the third value of LUT
1591 Descriptor. This range is always unsigned."
1592
1593 and also added a note to spell out what the output range meant in the
1594 VOI LUT section:
1595
1596 "9. The output of the Window Center/Width or VOI LUT transformation
1597 is either implicitly scaled to the full range of the display device
1598 if there is no succeeding transformation defined, or implicitly scaled
1599 to the full input range of the succeeding transformation step (such as
1600 the Presentation LUT), if present. See C.11.6.1."
1601
1602 It still reads this way in the 2004 edition.
1603
1604 Note that LUTs in other applications than the general VOI LUT allow for
1605 values other than 8 or 16 in the third value of LUT descriptor to permit
1606 ranges other than 0 to 255 or 65535.
1607
1608 In addition, the DX Image Module specializes the VOI LUT
1609 attributes as follows, in PS 3.3 section C.8.11.3.1.5 (added in Sup 32):
1610
1611 "The third value specifies the number of bits for each entry in the LUT
1612 Data (analogous to ìbits storedî). It shall be between 10-16. The LUT
1613 Data shall be stored in a format equivalent to 16 ìbits allocatedî and
1614 ìhigh bitî equal to ìbits storedî - 1. The third value conveys the range
1615 of LUT entry values. These unsigned LUT entry values shall range between
1616 0 and 2^n-1, where n is the third value of the LUT Descriptor."
1617
1618 So in the case of the GE DX for presentation images, the third value of
1619 LUT descriptor is allowed to be and probably should be 14 rather than 16.
1620
1621 */