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