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