]> Creatis software - gdcm.git/blob - src/gdcmPixelReadConvert.cxx
Unnormalized 4th dimension is now dealt with.
[gdcm.git] / src / gdcmPixelReadConvert.cxx
1 /*=========================================================================
2  
3   Program:   gdcm
4   Module:    $RCSfile: gdcmPixelReadConvert.cxx,v $
5   Language:  C++
6   Date:      $Date: 2006/03/29 16:09:48 $
7   Version:   $Revision: 1.111 $
8                                                                                 
9   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10   l'Image). All rights reserved. See Doc/License.txt or
11   http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
12                                                                                 
13      This software is distributed WITHOUT ANY WARRANTY; without even
14      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15      PURPOSE.  See the above copyright notices for more information.
16                                                                                 
17 =========================================================================*/
18
19 #include "gdcmPixelReadConvert.h"
20 #include "gdcmDebug.h"
21 #include "gdcmFile.h"
22 #include "gdcmGlobal.h"
23 #include "gdcmTS.h"
24 #include "gdcmDocEntry.h"
25 #include "gdcmRLEFramesInfo.h"
26 #include "gdcmJPEGFragmentsInfo.h"
27
28 #include <fstream>
29 #include <stdio.h> //for sscanf
30
31 #if defined(__BORLANDC__)
32    #include <mem.h> // for memset
33 #endif 
34
35 namespace gdcm
36 {
37
38 //bool ReadMPEGFile (std::ifstream *fp, char *inputdata, size_t lenght); 
39 bool gdcm_read_JPEG2000_file (void* raw, 
40                               char *inputdata, size_t inputlength);
41 //-----------------------------------------------------------------------------
42 #define str2num(str, typeNum) *((typeNum *)(str))
43
44 //-----------------------------------------------------------------------------
45 // Constructor / Destructor
46 /// Constructor
47 PixelReadConvert::PixelReadConvert() 
48 {
49    RGB          = 0;
50    RGBSize      = 0;
51    Raw          = 0;
52    RawSize      = 0;
53    LutRGBA      = 0;
54    LutRedData   = 0;
55    LutGreenData = 0;
56    LutBlueData  = 0;
57    RLEInfo      = 0;
58    JPEGInfo     = 0;
59    UserFunction = 0;
60    FileInternal = 0;
61 }
62
63 /// Canonical Destructor
64 PixelReadConvert::~PixelReadConvert() 
65 {
66    Squeeze();
67 }
68
69 //-----------------------------------------------------------------------------
70 // Public
71 /**
72  * \brief Predicate to know whether the image[s] (once Raw) is RGB.
73  * \note See comments of \ref ConvertHandleColor
74  */
75 bool PixelReadConvert::IsRawRGB()
76 {
77    if (   IsMonochrome
78        || PlanarConfiguration == 2
79        || IsPaletteColor )
80    {
81       return false;
82    }
83    return true;
84 }
85 /**
86  * \brief Gets various usefull informations from the file header
87  * @param file gdcm::File pointer
88  */
89 void PixelReadConvert::GrabInformationsFromFile( File *file,
90                                                  FileHelper *fileHelper )
91 {
92    // Number of Bits Allocated for storing a Pixel is defaulted to 16
93    // when absent from the file.
94    BitsAllocated = file->GetBitsAllocated();
95    if ( BitsAllocated == 0 )
96    {
97       BitsAllocated = 16;
98    }
99
100    // Number of "Bits Stored", defaulted to number of "Bits Allocated"
101    // when absent from the file.
102    BitsStored = file->GetBitsStored();
103    if ( BitsStored == 0 )
104    {
105       BitsStored = BitsAllocated;
106    }
107
108    // High Bit Position, defaulted to "Bits Allocated" - 1
109    HighBitPosition = file->GetHighBitPosition();
110    if ( HighBitPosition == 0 )
111    {
112       HighBitPosition = BitsAllocated - 1;
113    }
114
115    XSize           = file->GetXSize();
116    YSize           = file->GetYSize();
117    ZSize           = file->GetZSize();
118    TSize           = file->GetTSize();   
119    SamplesPerPixel = file->GetSamplesPerPixel();
120    //PixelSize       = file->GetPixelSize();  Useless
121    PixelSign       = file->IsSignedPixelData();
122    SwapCode        = file->GetSwapCode();
123
124    IsPrivateGETransferSyntax = IsMPEG
125              = IsJPEG2000 = IsJPEGLS = IsJPEGLossy  
126              = IsJPEGLossless = IsRLELossless 
127              = false;
128
129    if (! file->IsDicomV3() )  // Should be ACR-NEMA file
130    {
131       IsRaw = true;
132    }
133    else
134    {
135       std::string ts = file->GetTransferSyntax();
136
137       IsRaw = false;
138       while (true) // shorter to write than 'if elseif elseif elseif' ...
139       {
140          // mind the order : check the most usual first.
141          if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRLittleEndian)         break;
142          if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRLittleEndian )        break;
143          if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRBigEndian)            break;
144          if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRBigEndianPrivateGE)   break;
145          // DeflatedExplicitVRLittleEndian syntax means the whole Dataset (Header + Pixels) is compressed !
146          // Not dealt with ! (Parser hangs)
147          //if( IsRaw = Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::DeflatedExplicitVRLittleEndian) break;
148          break;
149       }
150       // cache whether this is a strange GE transfer syntax (which uses
151       // a little endian transfer syntax for the header and a big endian
152       // transfer syntax for the pixel data). 
153       IsPrivateGETransferSyntax = 
154                 ( Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRBigEndianPrivateGE );
155
156       IsMPEG =  IsJPEG2000 =  IsJPEGLS =  IsJPEGLossy =  IsJPEGLossless = IsRLELossless = false;  
157       if (!IsRaw)
158       {     
159          while(true)
160          {
161             // mind the order : check the most usual first.
162             if( IsJPEGLossy     = Global::GetTS()->IsJPEGLossy(ts) )    break;
163             if( IsJPEGLossless  = Global::GetTS()->IsJPEGLossless(ts) ) break;
164             if( IsRLELossless   = Global::GetTS()->IsRLELossless(ts) )  break;
165             if( IsJPEG2000      = Global::GetTS()->IsJPEG2000(ts) )     break;
166             if( IsMPEG          = Global::GetTS()->IsMPEG(ts) )         break;
167             if( IsJPEGLS        = Global::GetTS()->IsJPEGLS(ts) )       break;
168             // DeflatedExplicitVRLittleEndian is considered as 'Unexpected' (we don't know yet haow to process !)
169             gdcmWarningMacro("Unexpected Transfer Syntax :[" << ts << "]");
170             break;
171          } 
172       }
173    }
174
175    PixelOffset     = file->GetPixelOffset();
176    PixelDataLength = file->GetPixelAreaLength();
177    RLEInfo         = file->GetRLEInfo();
178    JPEGInfo        = file->GetJPEGInfo();
179
180    IsMonochrome    = file->IsMonochrome();
181    IsMonochrome1   = file->IsMonochrome1();
182    IsPaletteColor  = file->IsPaletteColor();
183    IsYBRFull       = file->IsYBRFull();
184
185    PlanarConfiguration = file->GetPlanarConfiguration();
186
187    /////////////////////////////////////////////////////////////////
188    // LUT section:
189    HasLUT = file->HasLUT();
190    if ( HasLUT )
191    {
192       // Just in case some access to a File element requires disk access.
193       LutRedDescriptor   = file->GetEntryString( 0x0028, 0x1101 );
194       LutGreenDescriptor = file->GetEntryString( 0x0028, 0x1102 );
195       LutBlueDescriptor  = file->GetEntryString( 0x0028, 0x1103 );
196    
197       // FIXME : The following comment is probabely meaningless, since LUT are *always*
198       // loaded at parsing time, whatever their length is.
199          
200       // Depending on the value of Document::MAX_SIZE_LOAD_ELEMENT_VALUE
201       // [ refer to invocation of Document::SetMaxSizeLoadEntry() in
202       // Document::Document() ], the loading of the value (content) of a
203       // [Bin|Val]Entry occurence migth have been hindered (read simply NOT
204       // loaded). Hence, we first try to obtain the LUTs data from the file
205       // and when this fails we read the LUTs data directly from disk.
206       // \TODO Reading a [Bin|Val]Entry directly from disk is a kludge.
207       //       We should NOT bypass the [Bin|Val]Entry class. Instead
208       //       an access to an UNLOADED content of a [Bin|Val]Entry occurence
209       //       (e.g. DataEntry::GetBinArea()) should force disk access from
210       //       within the [Bin|Val]Entry class itself. The only problem
211       //       is that the [Bin|Val]Entry is unaware of the FILE* is was
212       //       parsed from. Fix that. FIXME.
213    
214       // //// Red round
215       file->LoadEntryBinArea(0x0028, 0x1201);
216       LutRedData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1201 );
217       if ( ! LutRedData )
218       {
219          gdcmWarningMacro("Unable to read Red Palette Color Lookup Table data");
220       }
221
222       // //// Green round:
223       file->LoadEntryBinArea(0x0028, 0x1202);
224       LutGreenData = (uint8_t*)file->GetEntryBinArea(0x0028, 0x1202 );
225       if ( ! LutGreenData)
226       {
227          gdcmWarningMacro("Unable to read Green Palette Color Lookup Table data");
228       }
229
230       // //// Blue round:
231       file->LoadEntryBinArea(0x0028, 0x1203);
232       LutBlueData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1203 );
233       if ( ! LutBlueData )
234       {
235          gdcmWarningMacro("Unable to read Blue Palette Color Lookup Table data");
236       }
237    }
238    FileInternal = file;   
239    FH = fileHelper;
240    ComputeRawAndRGBSizes();
241 }
242
243 /// \brief Reads from disk and decompresses Pixels
244 bool PixelReadConvert::ReadAndDecompressPixelData( std::ifstream *fp )
245 {
246    // ComputeRawAndRGBSizes is already made by 
247    // ::GrabInformationsFromfile. So, the structure sizes are
248    // correct
249    Squeeze();
250
251    //////////////////////////////////////////////////
252    //// First stage: get our hands on the Pixel Data.
253    if ( !fp )
254    {
255       gdcmWarningMacro( "Unavailable file pointer." );
256       return false;
257    }
258
259    fp->seekg( PixelOffset, std::ios::beg );
260    if ( fp->fail() || fp->eof() )
261    {
262       gdcmWarningMacro( "Unable to find PixelOffset in file." );
263       return false;
264    }
265
266    AllocateRaw();
267
268    //////////////////////////////////////////////////
269    
270    CallStartMethod(); // for progress bar
271    unsigned int count = 0;
272    unsigned int frameSize;
273    unsigned int bitsAllocated = BitsAllocated;
274    if(bitsAllocated == 12)
275       bitsAllocated = 16;
276    frameSize = XSize*YSize*SamplesPerPixel*bitsAllocated/8;
277    
278    //// Second stage: read from disk and decompress.
279    
280    if ( BitsAllocated == 12 ) // We suppose 'BitsAllocated' = 12 only exist for uncompressed files
281    {
282       ReadAndDecompress12BitsTo16Bits( fp);
283    }
284    else if ( IsRaw )
285    {
286       // This problem can be found when some obvious informations are found
287       // after the field containing the image data. In this case, these
288       // bad data are added to the size of the image (in the PixelDataLength
289       // variable). But RawSize is the right size of the image !
290       if ( PixelDataLength != RawSize )
291       {
292          gdcmWarningMacro( "Mismatch between PixelReadConvert : "
293                             << PixelDataLength << " and RawSize : " << RawSize );
294       }
295       
296       //todo : is it the right patch?
297       char *raw = (char*)Raw;
298       uint32_t remainingLength;
299       unsigned int i; 
300       unsigned int lengthToRead;
301        
302       if ( PixelDataLength > RawSize )
303         lengthToRead =  RawSize;
304       else
305         lengthToRead = PixelDataLength;
306  
307       // perform a frame by frame reading
308       remainingLength = lengthToRead;
309       unsigned int nbFrames = lengthToRead / frameSize;
310       for (i=0;i<nbFrames; i++)
311       {
312          Progress = (float)(count+1)/(float)nbFrames;
313          fp->read( raw, frameSize);
314          raw +=  frameSize;
315          remainingLength -=  frameSize;
316          count++;
317       }
318       if (remainingLength !=0 )
319         fp->read( raw, remainingLength);
320                  
321       if ( fp->fail() || fp->eof())
322       {
323          gdcmWarningMacro( "Reading of Raw pixel data failed." );
324          return false;
325       }
326    } 
327    else if ( IsRLELossless )
328    {
329       if ( ! RLEInfo->DecompressRLEFile
330                                ( fp, Raw, XSize, YSize, ZSize, TSize, BitsAllocated ) )
331       {
332          gdcmWarningMacro( "RLE decompressor failed." );
333          return false;
334       }
335    }
336    else if ( IsMPEG )
337    {
338       //gdcmWarningMacro( "Sorry, MPEG not yet taken into account" );
339       //return false;
340       // fp has already been seek to start of mpeg
341       //ReadMPEGFile(fp, (char*)Raw, PixelDataLength); 
342       return true;
343    }
344    else
345    {
346       // Default case concerns JPEG family
347       if ( ! ReadAndDecompressJPEGFile( fp ) )
348       {
349          gdcmWarningMacro( "JPEG decompressor ( ReadAndDecompressJPEGFile()"
350                               << " method ) failed." );
351          return false;
352       }
353    }
354
355    ////////////////////////////////////////////
356    //// Third stage: twigle the bytes and bits.
357    ConvertReorderEndianity();
358    ConvertReArrangeBits();
359    ConvertFixGreyLevels();
360    if (UserFunction) // user is allowed to Mirror, TopDown, Rotate,...the image
361       UserFunction( Raw, FileInternal);
362    ConvertHandleColor();
363
364    return true;
365 }
366
367 /// Deletes Pixels Area
368 void PixelReadConvert::Squeeze() 
369 {
370    if ( RGB )
371       delete [] RGB;
372    RGB = 0;
373
374    if ( Raw )
375       delete [] Raw;
376    Raw = 0;
377
378    if ( LutRGBA )
379       delete [] LutRGBA;
380    LutRGBA = 0;
381 }
382
383 /**
384  * \brief Build the RGB image from the Raw image and the LUTs.
385  */
386 bool PixelReadConvert::BuildRGBImage()
387 {
388    if ( RGB )
389    {
390       // The job is already done.
391       return true;
392    }
393
394    if ( ! Raw )
395    {
396       // The job can't be done
397       return false;
398    }
399
400    BuildLUTRGBA();
401    if ( ! LutRGBA )
402    {
403       // The job can't be done
404       return false;
405    }
406
407    gdcmDebugMacro( "--> BuildRGBImage" );
408                                                                                 
409    // Build RGB Pixels
410    AllocateRGB();
411    
412    int j;
413    if ( BitsAllocated <= 8 )
414    {
415       uint8_t *localRGB = RGB;
416       for (size_t i = 0; i < RawSize; ++i )
417       {
418          j  = Raw[i] * 4;
419          *localRGB++ = LutRGBA[j];
420          *localRGB++ = LutRGBA[j+1];
421          *localRGB++ = LutRGBA[j+2];
422       }
423     }
424  
425     else  // deal with 16 bits pixels and 16 bits Palette color
426     {
427       uint16_t *localRGB = (uint16_t *)RGB;
428       for (size_t i = 0; i < RawSize/2; ++i )
429       {
430          j  = ((uint16_t *)Raw)[i] * 4;
431          *localRGB++ = ((uint16_t *)LutRGBA)[j];
432          *localRGB++ = ((uint16_t *)LutRGBA)[j+1];
433          *localRGB++ = ((uint16_t *)LutRGBA)[j+2];
434       } 
435     }
436  
437    return true;
438 }
439
440 //-----------------------------------------------------------------------------
441 // Protected
442
443 //-----------------------------------------------------------------------------
444 // Private
445 /**
446  * \brief Read from file a 12 bits per pixel image and decompress it
447  *        into a 16 bits per pixel image.
448  */
449 void PixelReadConvert::ReadAndDecompress12BitsTo16Bits( std::ifstream *fp )
450                throw ( FormatError )
451 {
452    /// \todo Fix the 3D, 4D pb
453    int nbPixels = XSize * YSize * TSize;
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 * ZSize * 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    
1197    /// \todo : find an example to see how 3rd dim and 4th dim work together
1198    int l        = XSize * YSize * TSize;
1199    int nbFrames = ZSize;
1200
1201    uint8_t *a = copyRaw + 0;
1202    uint8_t *b = copyRaw + l;
1203    uint8_t *c = copyRaw + l+ l;
1204    int32_t R, G, B;
1205
1206    ///  We replaced easy to understand but time consuming floating point
1207    ///  computations by the 'well known' integer computation counterpart
1208    ///  Refer to :
1209    ///            http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf
1210    ///  for code optimisation.
1211
1212    for ( int i = 0; i < nbFrames; i++ )
1213    {
1214       for ( int j = 0; j < l; j++ )
1215       {
1216          R = 38142 *(*a-16) + 52298 *(*c -128);
1217          G = 38142 *(*a-16) - 26640 *(*c -128) - 12845 *(*b -128);
1218          B = 38142 *(*a-16) + 66093 *(*b -128);
1219
1220          R = (R+16384)>>15;
1221          G = (G+16384)>>15;
1222          B = (B+16384)>>15;
1223
1224          if (R < 0)   R = 0;
1225          if (G < 0)   G = 0;
1226          if (B < 0)   B = 0;
1227          if (R > 255) R = 255;
1228          if (G > 255) G = 255;
1229          if (B > 255) B = 255;
1230
1231          *(localRaw++) = (uint8_t)R;
1232          *(localRaw++) = (uint8_t)G;
1233          *(localRaw++) = (uint8_t)B;
1234          a++;
1235          b++;
1236          c++;
1237       }
1238    }
1239    delete[] copyRaw;
1240 }
1241
1242 /// \brief Deals with the color decoding i.e. handle:
1243 ///   - R, G, B planes (as opposed to RGB pixels)
1244 ///   - YBR (various) encodings.
1245 ///   - LUT[s] (or "PALETTE COLOR").
1246
1247 void PixelReadConvert::ConvertHandleColor()
1248 {
1249    //////////////////////////////////
1250    // Deal with the color decoding i.e. handle:
1251    //   - R, G, B planes (as opposed to RGB pixels)
1252    //   - YBR (various) encodings.
1253    //   - LUT[s] (or "PALETTE COLOR").
1254    //
1255    // The classification in the color decoding schema is based on the blending
1256    // of two Dicom tags values:
1257    // * "Photometric Interpretation" for which we have the cases:
1258    //  - [Photo A] MONOCHROME[1|2] pictures,
1259    //  - [Photo B] RGB or YBR_FULL_422 (which acts as RGB),
1260    //  - [Photo C] YBR_* (with the above exception of YBR_FULL_422)
1261    //  - [Photo D] "PALETTE COLOR" which indicates the presence of LUT[s].
1262    // * "Planar Configuration" for which we have the cases:
1263    //  - [Planar 0] 0 then Pixels are already RGB
1264    //  - [Planar 1] 1 then we have 3 planes : R, G, B,
1265    //  - [Planar 2] 2 then we have 1 gray Plane and 3 LUTs
1266    //
1267    // Now in theory, one could expect some coherence when blending the above
1268    // cases. For example we should not encounter files belonging at the
1269    // time to case [Planar 0] and case [Photo D].
1270    // Alas, this was only theory ! Because in practice some odd (read ill
1271    // formated Dicom) files (e.g. gdcmData/US-PAL-8-10x-echo.dcm) we encounter:
1272    //     - "Planar Configuration" = 0,
1273    //     - "Photometric Interpretation" = "PALETTE COLOR".
1274    // Hence gdcm will use the folowing "heuristic" in order to be tolerant
1275    // towards Dicom-non-conformant files:
1276    //   << whatever the "Planar Configuration" value might be, a
1277    //      "Photometric Interpretation" set to "PALETTE COLOR" forces
1278    //      a LUT intervention >>
1279    //
1280    // Now we are left with the following handling of the cases:
1281    // - [Planar 0] OR  [Photo A] no color decoding (since respectively
1282    //       Pixels are already RGB and monochrome pictures have no color :),
1283    // - [Planar 1] AND [Photo B] handled with ConvertRGBPlanesToRGBPixels()
1284    // - [Planar 1] AND [Photo C] handled with ConvertYcBcRPlanesToRGBPixels()
1285    // - [Planar 2] OR  [Photo D] requires LUT intervention.
1286
1287    gdcmDebugMacro("--> ConvertHandleColor "
1288                      << "Planar Configuration " << PlanarConfiguration );
1289
1290    if ( ! IsRawRGB() )
1291    {
1292       // [Planar 2] OR  [Photo D]: LUT intervention done outside
1293       gdcmDebugMacro("--> RawRGB : LUT intervention done outside");
1294       return;
1295    }
1296                                                                                 
1297    if ( PlanarConfiguration == 1 )
1298    {
1299       if ( IsYBRFull )
1300       {
1301          // [Planar 1] AND [Photo C] (remember YBR_FULL_422 acts as RGB)
1302          gdcmDebugMacro("--> YBRFull");
1303          ConvertYcBcRPlanesToRGBPixels();
1304       }
1305       else
1306       {
1307          // [Planar 1] AND [Photo C]
1308          gdcmDebugMacro("--> YBRFull");
1309          ConvertRGBPlanesToRGBPixels();
1310       }
1311       return;
1312    }
1313                                                                                 
1314    // When planarConf is 0, and RLELossless (forbidden by Dicom norm)
1315    // pixels need to be RGB-fyied anyway
1316
1317    if (IsRLELossless)
1318    { 
1319      gdcmDebugMacro("--> RLE Lossless");
1320      ConvertRGBPlanesToRGBPixels();
1321    }
1322
1323    // In *normal *case, when planarConf is 0, pixels are already in RGB
1324 }
1325
1326 /// Computes the Pixels Size
1327 void PixelReadConvert::ComputeRawAndRGBSizes()
1328 {
1329    int bitsAllocated = BitsAllocated;
1330    // Number of "Bits Allocated" is fixed to 16 when it's 12, since
1331    // in this case we will expand the image to 16 bits (see
1332    //    \ref ReadAndDecompress12BitsTo16Bits() )
1333    if (  BitsAllocated == 12 )
1334    {
1335       bitsAllocated = 16;
1336    }
1337                                                                                 
1338    RawSize =  XSize * YSize * ZSize * TSize
1339                      * ( bitsAllocated / 8 )
1340                      * SamplesPerPixel;
1341    if ( HasLUT )
1342    {
1343       RGBSize = 3 * RawSize; // works for 8 and 16 bits per Pixel
1344    }
1345    else
1346    {
1347       RGBSize = RawSize;
1348    }
1349 }
1350
1351 /// Allocates room for RGB Pixels
1352 void PixelReadConvert::AllocateRGB()
1353 {
1354   if ( RGB )
1355      delete [] RGB;
1356   RGB = new uint8_t[RGBSize];
1357 }
1358
1359 /// Allocates room for RAW Pixels
1360 void PixelReadConvert::AllocateRaw()
1361 {
1362   if ( Raw )
1363      delete [] Raw;
1364   Raw = new uint8_t[RawSize];
1365 }
1366
1367 //-----------------------------------------------------------------------------
1368 // Print
1369 /**
1370  * \brief        Print self.
1371  * @param indent Indentation string to be prepended during printing.
1372  * @param os     Stream to print to.
1373  */
1374 void PixelReadConvert::Print( std::ostream &os, std::string const &indent )
1375 {
1376    os << indent
1377       << "--- Pixel information -------------------------"
1378       << std::endl;
1379    os << indent
1380       << "Pixel Data: offset " << PixelOffset
1381       << " x(" << std::hex << PixelOffset << std::dec
1382       << ")   length " << PixelDataLength
1383       << " x(" << std::hex << PixelDataLength << std::dec
1384       << ")" << std::endl;
1385
1386    if ( IsRLELossless )
1387    {
1388       if ( RLEInfo )
1389       {
1390          RLEInfo->Print( os, indent );
1391       }
1392       else
1393       {
1394          gdcmWarningMacro("Set as RLE file but NO RLEinfo present.");
1395       }
1396    }
1397
1398    if ( IsJPEG2000 || IsJPEGLossless || IsJPEGLossy || IsJPEGLS )
1399    {
1400       if ( JPEGInfo )
1401       {
1402          JPEGInfo->Print( os, indent );
1403       }
1404       else
1405       {
1406          gdcmWarningMacro("Set as JPEG file but NO JPEGinfo present.");
1407       }
1408    }
1409 }
1410
1411 /**
1412  * \brief   CallStartMethod
1413  */
1414 void PixelReadConvert::CallStartMethod()
1415 {
1416    Progress = 0.0f;
1417    Abort    = false;
1418    CommandManager::ExecuteCommand(FH,CMD_STARTPROGRESS);
1419 }
1420
1421 /**
1422  * \brief   CallProgressMethod
1423  */
1424 void PixelReadConvert::CallProgressMethod()
1425 {
1426    CommandManager::ExecuteCommand(FH,CMD_PROGRESS);
1427 }
1428
1429 /**
1430  * \brief   CallEndMethod
1431  */
1432 void PixelReadConvert::CallEndMethod()
1433 {
1434    Progress = 1.0f;
1435    CommandManager::ExecuteCommand(FH,CMD_ENDPROGRESS);
1436 }
1437
1438
1439 //-----------------------------------------------------------------------------
1440 } // end namespace gdcm
1441
1442 // Note to developpers :
1443 // Here is a very detailled post from David Clunie, on the troubles caused 
1444 // 'non standard' LUT and LUT description
1445 // We shall have to take it into accound in our code.
1446 // Some day ...
1447
1448
1449 /*
1450 Subject: Problem with VOI LUTs in Agfa and Fuji CR and GE DX images, was Re: VOI LUT issues
1451 Date: Sun, 06 Feb 2005 17:13:40 GMT
1452 From: David Clunie <dclunie@dclunie.com>
1453 Reply-To: dclunie@dclunie.com
1454 Newsgroups: comp.protocols.dicom
1455 References: <1107553502.040221.189550@o13g2000cwo.googlegroups.com>
1456
1457 > THE LUT that comes with [my] image claims to be 16-bit, but none of the
1458 > values goes higher than 4095.  That being said, though, none of my
1459 > original pixel values goes higher than that, either.  I have read
1460 > elsewhere on this group that when that happens you are supposed to
1461 > adjust the LUT.  Can someone be more specific?  There was a thread from
1462 > 2002 where Marco and David were mentioning doing precisely that.
1463 >
1464 > Thanks
1465 >
1466 > -carlos rodriguez
1467
1468
1469 You have encountered the well known "we know what the standard says but
1470 we are going to ignore it and do what we have been doing for almost
1471 a decade regardless" CR vendor bug. Agfa started this, but they are not
1472 the only vendor doing this now; GE and Fuji may have joined the club.
1473
1474 Sadly, one needs to look at the LUT Data, figure out what the maximum
1475 value actually encoded is, and find the next highest power of 2 (e.g.
1476 212 in this case), to figure out what the range of the data is
1477 supposed to be. I have assumed that if the maximum value in the LUT
1478 data is less than a power of 2 minus 1 (e.g. 0xebc) then the intent
1479 of the vendor was not to use the maximum available grayscale range
1480 of the display (e.g. the maximum is 0xfff in this case). An alternative
1481 would be to scale to the actual maximum rather than a power of two.
1482
1483 Very irritating, and in theory not totally reliable if one really
1484 intended the full 16 bits and only used, say 15, but that is extremely
1485 unlikely since everything would be too dark, and this heuristic
1486 seems to work OK.
1487
1488 There has never been anything in the standard that describes having
1489 to go through these convolutions. Since the only value in the
1490 standard that describes the bit depth of the LUT values is LUT
1491 Descriptor value 3 and that is (usually) always required to be
1492 either 8 or 16, it mystifies me how the creators' of these images
1493 imagine that the receiver is going to divine the range that is intended. Further, the standard is quite explicit that this 3rd
1494 value defines the range of LUT values, but as far as I am aware, all
1495 the vendors are ignoring the standard and indeed sending a third value
1496 of 16 in all cases.
1497
1498 This problem is not confined to CR, and is also seen with DX products.
1499
1500 Typically I have seen:
1501
1502 - Agfa CR, which usually (always ?) sends LUTs, values up to 0x0fff
1503 - Fuji CR, which occasionally send LUTs, values up to 0x03ff
1504 - GE DX, for presentation, which always have LUTs, up to 0x3fff
1505
1506 Swissray, Siemens, Philips, Canon and Kodak never seem to send VOI LUTs
1507 at this point (which is a whole other problem). Note that the presence
1508 or absence of a VOI LUT as opposed to window values may be configurable
1509 on the modality in some cases, and I have just looked at what I happen
1510 to have received from a myriad of sites over whose configuration I have
1511 no control. This may be why the majority of Fuji images have no VOI LUTs,
1512 but a few do (or it may be the Siemens system that these Fuji images went
1513 through that perhaps added it). I do have some test Hologic DX images that
1514 are not from a clinical site that do actually get this right (a value
1515 of 12 for the third value and a max of 0xfff).
1516
1517 Since almost every vendor that I have encountered that encodes LUTs
1518 makes this mistake, perhaps it is time to amend the standard to warn
1519 implementor's of receivers and/or sanction this bad behavior. We have
1520 talked about this in the past in WG 6 but so far everyone has been
1521 reluctant to write into the standard such a comment. Maybe it is time
1522 to try again, since if one is not aware of this problem, one cannot
1523 effectively implement display using VOI LUTs, and there is a vast
1524 installed base to contend with.
1525
1526 I did not check presentation states, in which VOI LUTs could also be
1527 encountered, for the prevalence of this mistake, nor did I look at the
1528 encoding of Modality LUT's, which are unusual. Nor did I check digital
1529 mammography images. I would be interested to hear from anyone who has.
1530
1531 David
1532
1533 PS. The following older thread in this newsgroup discusses this:
1534
1535 "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"
1536
1537 PPS. From a historical perspective, the following may be of interest.
1538
1539 In the original standard in 1993, all that was said about this was a
1540 reference to the corresponding such where Modality LUTs are described
1541 that said:
1542
1543 "The third value specifies the number of bits for each entry in the
1544 LUT Data. It shall take the value 8 or 16. The LUT Data shall be stored
1545 in a format equivalent to 8 or 16 bits allocated and high bit equal
1546 1-bits allocated."
1547
1548 Since the high bit hint was not apparently explicit enough, a very
1549 early CP, CP 15 (submitted by Agfa as it happens), replaced this with:
1550
1551 "The third value conveys the range of LUT entry values. It shall take
1552 the value 8 or 16, corresponding with the LUT entry value range of
1553 256 or 65536.
1554
1555 Note:    The third value is not required for describing the
1556     LUT data and is only included for informational usage
1557     and for maintaining compatibility with ACRNEMA 2.0.
1558
1559 The LUT Data contains the LUT entry values."
1560
1561 That is how it read in the 1996, 1998 and 1999 editions.
1562
1563 By the 2000 edition, Supplement 33 that introduced presentation states
1564 extensively reworked this entire section and tried to explain this in
1565 different words:
1566
1567 "The output range is from 0 to 2^n-1 where n is the third value of LUT
1568 Descriptor. This range is always unsigned."
1569
1570 and also added a note to spell out what the output range meant in the
1571 VOI LUT section:
1572
1573 "9. The output of the Window Center/Width or VOI LUT transformation
1574 is either implicitly scaled to the full range of the display device
1575 if there is no succeeding transformation defined, or implicitly scaled
1576 to the full input range of the succeeding transformation step (such as
1577 the Presentation LUT), if present. See C.11.6.1."
1578
1579 It still reads this way in the 2004 edition.
1580
1581 Note that LUTs in other applications than the general VOI LUT allow for
1582 values other than 8 or 16 in the third value of LUT descriptor to permit
1583 ranges other than 0 to 255 or 65535.
1584
1585 In addition, the DX Image Module specializes the VOI LUT
1586 attributes as follows, in PS 3.3 section C.8.11.3.1.5 (added in Sup 32):
1587
1588 "The third value specifies the number of bits for each entry in the LUT
1589 Data (analogous to ìbits storedî). It shall be between 10-16. The LUT
1590 Data shall be stored in a format equivalent to 16 ìbits allocatedî and
1591 ìhigh bitî equal to ìbits storedî - 1. The third value conveys the range
1592 of LUT entry values. These unsigned LUT entry values shall range between
1593 0 and 2^n-1, where n is the third value of the LUT Descriptor."
1594
1595 So in the case of the GE DX for presentation images, the third value of
1596 LUT descriptor is allowed to be and probably should be 14 rather than 16.
1597
1598 */