]> Creatis software - gdcm.git/blob - src/gdcmPixelReadConvert.cxx
Solve (hope so!) the JPEG troubles when BitsStored == 8 && BitsAllocated==16
[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 13:14:33 $
7   Version:   $Revision: 1.119 $
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       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                }
1121                deb++;
1122             }
1123          }
1124       }
1125       else if ( BitsAllocated == 32 )
1126       { 
1127          // pmask : to mask the 'unused bits' (may contain overlays)
1128          uint32_t pmask = 0xffffffff;
1129          pmask = pmask >> ( BitsAllocated - BitsStored );
1130  
1131          uint32_t *deb = (uint32_t*)Raw;
1132
1133          if ( !PixelSign )
1134          {
1135             for(int i = 0; i<l; i++)
1136             {             
1137                *deb = (*deb >> (BitsStored - HighBitPosition - 1)) & pmask;
1138                deb++;
1139             }
1140          }
1141          else
1142          {
1143             // smask : to check the 'sign' when BitsStored != BitsAllocated
1144             uint32_t smask = 0x00000001;
1145             smask = smask >> ( 32 - (BitsAllocated - BitsStored +1 ));
1146             // nmask : to propagate sign bit on negative values
1147             int32_t nmask = 0x80000000;   
1148             nmask = nmask >> ( BitsAllocated - BitsStored -1 );
1149
1150             for(int i = 0; i<l; i++)
1151             {
1152                *deb = *deb >> (BitsStored - HighBitPosition - 1);
1153                if ( *deb & smask )
1154                   *deb = *deb | nmask;
1155                else                
1156                  *deb = *deb & pmask; 
1157                deb++;
1158             }
1159          }
1160       }
1161       else
1162       {
1163          gdcmWarningMacro("Weird image (BitsAllocated !=8, 12, 16, 32)");
1164          throw FormatError( "Weird image !?" );
1165       }
1166    }
1167    return true;
1168 }
1169
1170 /**
1171  * \brief   Convert (Red plane, Green plane, Blue plane) to RGB pixels
1172  * \warning Works on all the frames at a time
1173  */
1174 void PixelReadConvert::ConvertRGBPlanesToRGBPixels()
1175 {
1176    gdcmWarningMacro("--> ConvertRGBPlanesToRGBPixels");
1177
1178    uint8_t *localRaw = Raw;
1179    uint8_t *copyRaw = new uint8_t[ RawSize ];
1180    memmove( copyRaw, localRaw, RawSize );
1181
1182    int l = XSize * YSize * ZSize;
1183
1184    uint8_t *a = copyRaw;
1185    uint8_t *b = copyRaw + l;
1186    uint8_t *c = copyRaw + l + l;
1187
1188    for (int j = 0; j < l; j++)
1189    {
1190       *(localRaw++) = *(a++);
1191       *(localRaw++) = *(b++);
1192       *(localRaw++) = *(c++);
1193    }
1194    delete[] copyRaw;
1195 }
1196
1197 /**
1198  * \brief   Convert (cY plane, cB plane, cR plane) to RGB pixels
1199  * \warning Works on all the frames at a time
1200  */
1201 void PixelReadConvert::ConvertYcBcRPlanesToRGBPixels()
1202 {
1203   // Remarks for YBR newbees :
1204   // YBR_FULL works very much like RGB, i.e. three samples per pixel, 
1205   // just the color space is YCbCr instead of RGB. This is particularly useful
1206   // for doppler ultrasound where most of the image is grayscale 
1207   // (i.e. only populates the Y components) and Cb and Cr are mostly zero,
1208   // except for the few patches of color on the image.
1209   // On such images, RLE achieves a compression ratio that is much better 
1210   // than the compression ratio on an equivalent RGB image. 
1211  
1212    gdcmWarningMacro("--> ConvertYcBcRPlanesToRGBPixels");
1213    
1214    uint8_t *localRaw = Raw;
1215    uint8_t *copyRaw = new uint8_t[ RawSize ];
1216    memmove( copyRaw, localRaw, RawSize );
1217
1218    // to see the tricks about YBR_FULL, YBR_FULL_422,
1219    // YBR_PARTIAL_422, YBR_ICT, YBR_RCT have a look at :
1220    // ftp://medical.nema.org/medical/dicom/final/sup61_ft.pdf
1221    // and be *very* affraid
1222    //
1223    
1224    /// \todo : find an example to see how 3rd dim and 4th dim work together
1225    int l        = XSize * YSize * TSize;
1226    int nbFrames = ZSize;
1227
1228    uint8_t *a = copyRaw + 0;
1229    uint8_t *b = copyRaw + l;
1230    uint8_t *c = copyRaw + l+ l;
1231    int32_t R, G, B;
1232
1233    ///  We replaced easy to understand but time consuming floating point
1234    ///  computations by the 'well known' integer computation counterpart
1235    ///  Refer to :
1236    ///            http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf
1237    ///  for code optimisation.
1238
1239    for ( int i = 0; i < nbFrames; i++ )
1240    {
1241       for ( int j = 0; j < l; j++ )
1242       {
1243          R = 38142 *(*a-16) + 52298 *(*c -128);
1244          G = 38142 *(*a-16) - 26640 *(*c -128) - 12845 *(*b -128);
1245          B = 38142 *(*a-16) + 66093 *(*b -128);
1246
1247          R = (R+16384)>>15;
1248          G = (G+16384)>>15;
1249          B = (B+16384)>>15;
1250
1251          if (R < 0)   R = 0;
1252          if (G < 0)   G = 0;
1253          if (B < 0)   B = 0;
1254          if (R > 255) R = 255;
1255          if (G > 255) G = 255;
1256          if (B > 255) B = 255;
1257
1258          *(localRaw++) = (uint8_t)R;
1259          *(localRaw++) = (uint8_t)G;
1260          *(localRaw++) = (uint8_t)B;
1261          a++;
1262          b++;
1263          c++;
1264       }
1265    }
1266    delete[] copyRaw;
1267 }
1268
1269 /// \brief Deals with the color decoding i.e. handle:
1270 ///   - R, G, B planes (as opposed to RGB pixels)
1271 ///   - YBR (various) encodings.
1272 ///   - LUT[s] (or "PALETTE COLOR").
1273
1274 void PixelReadConvert::ConvertHandleColor()
1275 {
1276    //////////////////////////////////
1277    // Deal with the color decoding i.e. handle:
1278    //   - R, G, B planes (as opposed to RGB pixels)
1279    //   - YBR (various) encodings.
1280    //   - LUT[s] (or "PALETTE COLOR").
1281    //
1282    // The classification in the color decoding schema is based on the blending
1283    // of two Dicom tags values:
1284    // * "Photometric Interpretation" for which we have the cases:
1285    //  - [Photo A] MONOCHROME[1|2] pictures,
1286    //  - [Photo B] RGB or YBR_FULL_422 (which acts as RGB),
1287    //  - [Photo C] YBR_* (with the above exception of YBR_FULL_422)
1288    //  - [Photo D] "PALETTE COLOR" which indicates the presence of LUT[s].
1289    // * "Planar Configuration" for which we have the cases:
1290    //  - [Planar 0] 0 then Pixels are already RGB
1291    //  - [Planar 1] 1 then we have 3 planes : R, G, B,
1292    //  - [Planar 2] 2 then we have 1 gray Plane and 3 LUTs
1293    //
1294    // Now in theory, one could expect some coherence when blending the above
1295    // cases. For example we should not encounter files belonging at the
1296    // time to case [Planar 0] and case [Photo D].
1297    // Alas, this was only theory ! Because in practice some odd (read ill
1298    // formated Dicom) files (e.g. gdcmData/US-PAL-8-10x-echo.dcm) we encounter:
1299    //     - "Planar Configuration" = 0,
1300    //     - "Photometric Interpretation" = "PALETTE COLOR".
1301    // Hence gdcm will use the folowing "heuristic" in order to be tolerant
1302    // towards Dicom-non-conformant files:
1303    //   << whatever the "Planar Configuration" value might be, a
1304    //      "Photometric Interpretation" set to "PALETTE COLOR" forces
1305    //      a LUT intervention >>
1306    //
1307    // Now we are left with the following handling of the cases:
1308    // - [Planar 0] OR  [Photo A] no color decoding (since respectively
1309    //       Pixels are already RGB and monochrome pictures have no color :),
1310    // - [Planar 1] AND [Photo B] handled with ConvertRGBPlanesToRGBPixels()
1311    // - [Planar 1] AND [Photo C] handled with ConvertYcBcRPlanesToRGBPixels()
1312    // - [Planar 2] OR  [Photo D] requires LUT intervention.
1313
1314    gdcmDebugMacro("--> ConvertHandleColor "
1315                      << "Planar Configuration " << PlanarConfiguration );
1316
1317    if ( ! IsRawRGB() )
1318    {
1319       // [Planar 2] OR  [Photo D]: LUT intervention done outside
1320       gdcmDebugMacro("--> RawRGB : LUT intervention done outside");
1321       return;
1322    }
1323                                                                                 
1324    if ( PlanarConfiguration == 1 )
1325    {
1326       if ( IsYBRFull )
1327       {
1328          // [Planar 1] AND [Photo C] (remember YBR_FULL_422 acts as RGB)
1329          gdcmDebugMacro("--> YBRFull");
1330          ConvertYcBcRPlanesToRGBPixels();
1331       }
1332       else
1333       {
1334          // [Planar 1] AND [Photo C]
1335          gdcmDebugMacro("--> YBRFull");
1336          ConvertRGBPlanesToRGBPixels();
1337       }
1338       return;
1339    }
1340                                                                                 
1341    // When planarConf is 0, and RLELossless (forbidden by Dicom norm)
1342    // pixels need to be RGB-fyied anyway
1343
1344    if (IsRLELossless)
1345    { 
1346      gdcmDebugMacro("--> RLE Lossless");
1347      ConvertRGBPlanesToRGBPixels();
1348    }
1349
1350    // In *normal *case, when planarConf is 0, pixels are already in RGB
1351 }
1352
1353 /// Computes the Pixels Size
1354 void PixelReadConvert::ComputeRawAndRGBSizes()
1355 {
1356    int bitsAllocated = BitsAllocated;
1357    // Number of "Bits Allocated" is fixed to 16 when it's 12, since
1358    // in this case we will expand the image to 16 bits (see
1359    //    \ref ReadAndDecompress12BitsTo16Bits() )
1360    if (  BitsAllocated == 12 )
1361    {
1362       bitsAllocated = 16;
1363    }
1364                                                                                 
1365    RawSize =  XSize * YSize * ZSize * TSize
1366                      * ( bitsAllocated / 8 )
1367                      * SamplesPerPixel;
1368    if ( HasLUT )
1369    {
1370       RGBSize = 3 * RawSize; // works for 8 and 16 bits per Pixel
1371    }
1372    else
1373    {
1374       RGBSize = RawSize;
1375       
1376    }
1377    RawSize += RawSize%2;
1378    RGBSize += RGBSize%2;
1379 }
1380
1381 /// Allocates room for RGB Pixels
1382 void PixelReadConvert::AllocateRGB()
1383 {
1384   if ( RGB )
1385      delete [] RGB;
1386   RGB = new uint8_t[RGBSize];
1387 }
1388
1389 /// Allocates room for RAW Pixels
1390 void PixelReadConvert::AllocateRaw()
1391 {
1392   if ( Raw )
1393      delete [] Raw;
1394   Raw = new uint8_t[RawSize];
1395 }
1396
1397 //-----------------------------------------------------------------------------
1398 // Print
1399 /**
1400  * \brief        Print self.
1401  * @param indent Indentation string to be prepended during printing.
1402  * @param os     Stream to print to.
1403  */
1404 void PixelReadConvert::Print( std::ostream &os, std::string const &indent )
1405 {
1406    os << indent
1407       << "--- Pixel information -------------------------"
1408       << std::endl;
1409    os << indent
1410       << "Pixel Data: offset " << PixelOffset
1411       << " x(" << std::hex << PixelOffset << std::dec
1412       << ")   length " << PixelDataLength
1413       << " x(" << std::hex << PixelDataLength << std::dec
1414       << ")" << std::endl;
1415
1416    if ( IsRLELossless )
1417    {
1418       if ( RLEInfo )
1419       {
1420          RLEInfo->Print( os, indent );
1421       }
1422       else
1423       {
1424          gdcmWarningMacro("Set as RLE file but NO RLEinfo present.");
1425       }
1426    }
1427
1428    if ( IsJPEG2000 || IsJPEGLossless || IsJPEGLossy || IsJPEGLS )
1429    {
1430       if ( JPEGInfo )
1431       {
1432          JPEGInfo->Print( os, indent );
1433       }
1434       else
1435       {
1436          gdcmWarningMacro("Set as JPEG file but NO JPEGinfo present.");
1437       }
1438    }
1439 }
1440
1441 /**
1442  * \brief   CallStartMethod
1443  */
1444 void PixelReadConvert::CallStartMethod()
1445 {
1446    Progress = 0.0f;
1447    Abort    = false;
1448    CommandManager::ExecuteCommand(FH,CMD_STARTPROGRESS);
1449 }
1450
1451 /**
1452  * \brief   CallProgressMethod
1453  */
1454 void PixelReadConvert::CallProgressMethod()
1455 {
1456    CommandManager::ExecuteCommand(FH,CMD_PROGRESS);
1457 }
1458
1459 /**
1460  * \brief   CallEndMethod
1461  */
1462 void PixelReadConvert::CallEndMethod()
1463 {
1464    Progress = 1.0f;
1465    CommandManager::ExecuteCommand(FH,CMD_ENDPROGRESS);
1466 }
1467
1468
1469 //-----------------------------------------------------------------------------
1470 } // end namespace gdcm
1471
1472 // Note to developpers :
1473 // Here is a very detailled post from David Clunie, on the troubles caused 
1474 // 'non standard' LUT and LUT description
1475 // We shall have to take it into accound in our code.
1476 // Some day ...
1477
1478
1479 /*
1480 Subject: Problem with VOI LUTs in Agfa and Fuji CR and GE DX images, was Re: VOI LUT issues
1481 Date: Sun, 06 Feb 2005 17:13:40 GMT
1482 From: David Clunie <dclunie@dclunie.com>
1483 Reply-To: dclunie@dclunie.com
1484 Newsgroups: comp.protocols.dicom
1485 References: <1107553502.040221.189550@o13g2000cwo.googlegroups.com>
1486
1487 > THE LUT that comes with [my] image claims to be 16-bit, but none of the
1488 > values goes higher than 4095.  That being said, though, none of my
1489 > original pixel values goes higher than that, either.  I have read
1490 > elsewhere on this group that when that happens you are supposed to
1491 > adjust the LUT.  Can someone be more specific?  There was a thread from
1492 > 2002 where Marco and David were mentioning doing precisely that.
1493 >
1494 > Thanks
1495 >
1496 > -carlos rodriguez
1497
1498
1499 You have encountered the well known "we know what the standard says but
1500 we are going to ignore it and do what we have been doing for almost
1501 a decade regardless" CR vendor bug. Agfa started this, but they are not
1502 the only vendor doing this now; GE and Fuji may have joined the club.
1503
1504 Sadly, one needs to look at the LUT Data, figure out what the maximum
1505 value actually encoded is, and find the next highest power of 2 (e.g.
1506 212 in this case), to figure out what the range of the data is
1507 supposed to be. I have assumed that if the maximum value in the LUT
1508 data is less than a power of 2 minus 1 (e.g. 0xebc) then the intent
1509 of the vendor was not to use the maximum available grayscale range
1510 of the display (e.g. the maximum is 0xfff in this case). An alternative
1511 would be to scale to the actual maximum rather than a power of two.
1512
1513 Very irritating, and in theory not totally reliable if one really
1514 intended the full 16 bits and only used, say 15, but that is extremely
1515 unlikely since everything would be too dark, and this heuristic
1516 seems to work OK.
1517
1518 There has never been anything in the standard that describes having
1519 to go through these convolutions. Since the only value in the
1520 standard that describes the bit depth of the LUT values is LUT
1521 Descriptor value 3 and that is (usually) always required to be
1522 either 8 or 16, it mystifies me how the creators' of these images
1523 imagine that the receiver is going to divine the range that is intended. Further, the standard is quite explicit that this 3rd
1524 value defines the range of LUT values, but as far as I am aware, all
1525 the vendors are ignoring the standard and indeed sending a third value
1526 of 16 in all cases.
1527
1528 This problem is not confined to CR, and is also seen with DX products.
1529
1530 Typically I have seen:
1531
1532 - Agfa CR, which usually (always ?) sends LUTs, values up to 0x0fff
1533 - Fuji CR, which occasionally send LUTs, values up to 0x03ff
1534 - GE DX, for presentation, which always have LUTs, up to 0x3fff
1535
1536 Swissray, Siemens, Philips, Canon and Kodak never seem to send VOI LUTs
1537 at this point (which is a whole other problem). Note that the presence
1538 or absence of a VOI LUT as opposed to window values may be configurable
1539 on the modality in some cases, and I have just looked at what I happen
1540 to have received from a myriad of sites over whose configuration I have
1541 no control. This may be why the majority of Fuji images have no VOI LUTs,
1542 but a few do (or it may be the Siemens system that these Fuji images went
1543 through that perhaps added it). I do have some test Hologic DX images that
1544 are not from a clinical site that do actually get this right (a value
1545 of 12 for the third value and a max of 0xfff).
1546
1547 Since almost every vendor that I have encountered that encodes LUTs
1548 makes this mistake, perhaps it is time to amend the standard to warn
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 */