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