]> Creatis software - gdcm.git/blob - src/gdcmHeader.cxx
024862ddd77b5e9eec4d304630d8900f5b872216
[gdcm.git] / src / gdcmHeader.cxx
1 // gdcmHeader.cxx
2 //-----------------------------------------------------------------------------
3 #include "gdcmHeader.h"
4
5 #include <stdio.h>
6 #include <cerrno>
7 /*// For nthos:
8 #ifdef _MSC_VER
9    #include <winsock.h>
10 #else
11    #include <netinet/in.h>
12 #endif*/
13 #include <cctype>    // for isalpha
14
15 /*#ifdef GDCM_NO_ANSI_STRING_STREAM
16 #  include <strstream>
17 #  define  ostringstream ostrstream
18 # else
19 #  include <sstream>
20 #endif*/
21
22 #include "gdcmUtil.h"
23 #include "gdcmTS.h"
24
25 //-----------------------------------------------------------------------------
26 // Refer to gdcmHeader::CheckSwap()
27 //const unsigned int gdcmHeader::HEADER_LENGTH_TO_READ = 256;
28
29 // Refer to gdcmHeader::SetMaxSizeLoadEntry()
30 //const unsigned int gdcmHeader::MAX_SIZE_LOAD_ELEMENT_VALUE = 4096;
31
32 //-----------------------------------------------------------------------------
33 // Constructor / Destructor
34 /**
35  * \ingroup gdcmHeader
36  * \brief   
37  * @param   InFilename
38  * @param   exception_on_error
39  * @param   enable_sequences = true to allow the header 
40  *          to be parsed *inside* the SeQuences, 
41  *          when they have an actual length 
42  *\TODO : may be we need one more bool, 
43  *         to allow skipping the private elements while parsing the header
44  *         in order to save space         
45  */
46 gdcmHeader::gdcmHeader(const char *InFilename, 
47                        bool exception_on_error,
48                        bool enable_sequences ):
49    gdcmParser(InFilename,exception_on_error,enable_sequences)
50 {
51 }
52
53 /**
54  * \ingroup gdcmHeader
55  * \brief   
56  * @param   exception_on_error
57  */
58 gdcmHeader::gdcmHeader(bool exception_on_error) :
59    gdcmParser(exception_on_error)
60 {
61 }
62
63 /**
64  * \ingroup gdcmHeader
65  * \brief   Canonical destructor.
66  */
67 gdcmHeader::~gdcmHeader (void) {
68 }
69
70 //-----------------------------------------------------------------------------
71 // Print
72
73 //-----------------------------------------------------------------------------
74 // Public
75 /**
76  * \ingroup gdcmHeader
77  * \brief   Determines if the Transfer Syntax was already encountered
78  *          and if it corresponds to a JPEGBaseLineProcess1 one.
79  *
80  * @return  True when JPEGBaseLineProcess1found. False in all other cases.
81  */
82 bool gdcmHeader::IsJPEGBaseLineProcess1TransferSyntax(void) {
83    gdcmHeaderEntry* Element = GetHeaderEntryByNumber(0x0002, 0x0010);
84    if ( !Element )
85       return false;
86    LoadHeaderEntrySafe(Element);
87
88    std::string Transfer = Element->GetValue();
89    if ( Transfer == "1.2.840.10008.1.2.4.50" )
90       return true;
91    return false;
92 }
93
94 /**
95  * \ingroup gdcmHeader
96  * \brief   Determines if the Transfer Syntax was already encountered
97  *          and if it corresponds to a JPEGExtendedProcess2-4 one.
98  *
99  * @return  True when JPEGExtendedProcess2-4 found. False in all other cases.
100  */
101 bool gdcmHeader::IsJPEGExtendedProcess2_4TransferSyntax(void) {
102    gdcmHeaderEntry* Element = GetHeaderEntryByNumber(0x0002, 0x0010);
103    if ( !Element )
104       return false;
105    LoadHeaderEntrySafe(Element);
106
107    std::string Transfer = Element->GetValue();
108    if ( Transfer == "1.2.840.10008.1.2.4.51" )
109       return true;
110    return false;
111 }
112
113 /**
114  * \ingroup gdcmHeader
115  * \brief   Determines if the Transfer Syntax was already encountered
116  *          and if it corresponds to a JPEGExtendeProcess3-5 one.
117  *
118  * @return  True when JPEGExtendedProcess3-5 found. False in all other cases.
119  */
120 bool gdcmHeader::IsJPEGExtendedProcess3_5TransferSyntax(void) {
121    gdcmHeaderEntry* Element = GetHeaderEntryByNumber(0x0002, 0x0010);
122    if ( !Element )
123       return false;
124    LoadHeaderEntrySafe(Element);
125
126    std::string Transfer = Element->GetValue();
127    if ( Transfer == "1.2.840.10008.1.2.4.52" )
128       return true;
129    return false;
130 }
131
132 /**
133  * \ingroup gdcmHeader
134  * \brief   Determines if the Transfer Syntax was already encountered
135  *          and if it corresponds to a JPEGSpectralSelectionProcess6-8 one.
136  *
137  * @return  True when JPEGSpectralSelectionProcess6-8 found. False in all
138  *          other cases.
139  */
140 bool gdcmHeader::IsJPEGSpectralSelectionProcess6_8TransferSyntax(void) {
141    gdcmHeaderEntry* Element = GetHeaderEntryByNumber(0x0002, 0x0010);
142    if ( !Element )
143       return false;
144    LoadHeaderEntrySafe(Element);
145
146    std::string Transfer = Element->GetValue();
147    if ( Transfer == "1.2.840.10008.1.2.4.53" )
148       return true;
149    return false;
150 }
151
152 /**
153  * \ingroup gdcmHeader
154  * \brief   Determines if the Transfer Syntax was already encountered
155  *          and if it corresponds to a RLE Lossless one.
156  *
157  * @return  True when RLE Lossless found. False in all
158  *          other cases.
159  */
160 bool gdcmHeader::IsRLELossLessTransferSyntax(void) {
161    gdcmHeaderEntry* Element = GetHeaderEntryByNumber(0x0002, 0x0010);
162    if ( !Element )
163       return false;
164    LoadHeaderEntrySafe(Element);
165
166    std::string Transfer = Element->GetValue();
167    if ( Transfer == "1.2.840.10008.1.2.5" )
168       return true;
169    return false;
170 }
171
172 /**
173  * \ingroup gdcmHeader
174  * \brief  Determines if Transfer Syntax was already encountered
175  *          and if it corresponds to a JPEG Lossless one. 
176  *
177  * @return  True when RLE Lossless found. False in all
178  *          other cases. 
179  */
180 bool gdcmHeader::IsJPEGLossless(void) {
181    gdcmHeaderEntry* Element = GetHeaderEntryByNumber(0x0002, 0x0010);
182     // faire qq chose d'intelligent a la place de ça
183    if ( !Element )
184       return false;
185    LoadHeaderEntrySafe(Element);
186
187    const char * Transfert = Element->GetValue().c_str();
188    if ( memcmp(Transfert+strlen(Transfert)-2 ,"70",2)==0) return true;
189    if ( memcmp(Transfert+strlen(Transfert)-2 ,"55",2)==0) return true;
190    if (Element->GetValue() == "1.2.840.10008.1.2.4.57")   return true;
191
192    return false;
193 }
194
195 /**
196  * \ingroup gdcmHeader
197  * \brief   Determines if the Transfer Syntax was already encountered
198  *          and if it corresponds to a JPEG200 one.0
199  *
200  * @return  True when JPEG2000 (Lossly or LossLess) found. False in all
201  *          other cases.
202  */
203 bool gdcmHeader::IsJPEG2000(void) {
204    gdcmHeaderEntry* Element = GetHeaderEntryByNumber(0x0002, 0x0010);
205    if ( !Element )
206       return false;
207    LoadHeaderEntrySafe(Element);
208
209    std::string Transfer = Element->GetValue();
210    if (    (Transfer == "1.2.840.10008.1.2.4.90") 
211         || (Transfer == "1.2.840.10008.1.2.4.91") )
212       return true;
213    return false;
214 }
215
216 /**
217  * \ingroup gdcmHeader
218  * \brief   Predicate for dicom version 3 file.
219  * @return  True when the file is a dicom version 3.
220  */
221 bool gdcmHeader::IsDicomV3(void) {
222    // Checking if Transfert Syntax exists is enough
223    return (GetHeaderEntryByNumber(0x0002, 0x0010) != NULL);
224 }
225
226 /**
227  * \ingroup gdcmHeader
228  * \brief   Retrieve the number of columns of image.
229  * @return  The encountered size when found, 0 by default.
230  *          0 means the file is NOT USABLE. The caller will have to check
231  */
232 int gdcmHeader::GetXSize(void) {
233    // We cannot check for "Columns" because the "Columns" tag is present
234    // both in IMG (0028,0011) and OLY (6000,0011) sections of the dictionary.
235    std::string StrSize = GetEntryByNumber(0x0028,0x0011);
236    if (StrSize == GDCM_UNFOUND)
237       return 0;
238    return atoi(StrSize.c_str());
239 }
240
241 /**
242  * \ingroup gdcmHeader
243  * \brief   Retrieve the number of lines of image.
244  * \warning The defaulted value is 1 as opposed to gdcmHeader::GetXSize()
245  * @return  The encountered size when found, 1 by default 
246  *          (The file contains a Signal, not an Image).
247  */
248 int gdcmHeader::GetYSize(void) {
249    // We cannot check for "Rows" because the "Rows" tag is present
250    // both in IMG (0028,0010) and OLY (6000,0010) sections of the dictionary.
251    std::string StrSize = GetEntryByNumber(0x0028,0x0010);
252    if (StrSize != GDCM_UNFOUND)
253       return atoi(StrSize.c_str());
254    if ( IsDicomV3() )
255       return 0;
256    else
257       // The Rows (0028,0010) entry was optional for ACR/NEMA. It might
258       // hence be a signal (1d image). So we default to 1:
259       return 1;
260 }
261
262 /**
263  * \ingroup gdcmHeader
264  * \brief   Retrieve the number of planes of volume or the number
265  *          of frames of a multiframe.
266  * \warning When present we consider the "Number of Frames" as the third
267  *          dimension. When absent we consider the third dimension as
268  *          being the "Planes" tag content.
269  * @return  The encountered size when found, 1 by default (single image).
270  */
271 int gdcmHeader::GetZSize(void) {
272    // Both  DicomV3 and ACR/Nema consider the "Number of Frames"
273    // as the third dimension.
274    std::string StrSize = GetEntryByNumber(0x0028,0x0008);
275    if (StrSize != GDCM_UNFOUND)
276       return atoi(StrSize.c_str());
277
278    // We then consider the "Planes" entry as the third dimension [we
279    // cannot retrieve by name since "Planes tag is present both in
280    // IMG (0028,0012) and OLY (6000,0012) sections of the dictionary]. 
281    StrSize = GetEntryByNumber(0x0028,0x0012);
282    if (StrSize != GDCM_UNFOUND)
283       return atoi(StrSize.c_str());
284    return 1;
285 }
286
287 /**
288  * \ingroup gdcmHeader
289  * \brief   Retrieve the number of Bits Stored (actually used)
290  *          (as opposite to number of Bits Allocated)
291  * 
292  * @return  The encountered number of Bits Stored, 0 by default.
293  *          0 means the file is NOT USABLE. The caller has to check it !
294  */
295 int gdcmHeader::GetBitsStored(void) { 
296    std::string StrSize = GetEntryByNumber(0x0028,0x0101);
297    if (StrSize == GDCM_UNFOUND)
298       return 0;  // It's supposed to be mandatory
299                  // the caller will have to check
300    return atoi(StrSize.c_str());
301 }
302
303 /**
304  * \ingroup gdcmHeader
305  * \brief   Retrieve the number of Bits Allocated
306  *          (8, 12 -compacted ACR-NEMA files, 16, ...)
307  * 
308  * @return  The encountered number of Bits Allocated, 0 by default.
309  *          0 means the file is NOT USABLE. The caller has to check it !
310  */
311 int gdcmHeader::GetBitsAllocated(void) { 
312    std::string StrSize = GetEntryByNumber(0x0028,0x0100);
313    if (StrSize == GDCM_UNFOUND)
314       return 0; // It's supposed to be mandatory
315                 // the caller will have to check
316    return atoi(StrSize.c_str());
317 }
318
319 /**
320  * \ingroup gdcmHeader
321  * \brief   Retrieve the number of Samples Per Pixel
322  *          (1 : gray level, 3 : RGB -1 or 3 Planes-)
323  * 
324  * @return  The encountered number of Samples Per Pixel, 1 by default.
325  *          (Gray level Pixels)
326  */
327 int gdcmHeader::GetSamplesPerPixel(void) { 
328    std::string StrSize = GetEntryByNumber(0x0028,0x0002);
329    if (StrSize == GDCM_UNFOUND)
330       return 1; // Well, it's supposed to be mandatory ...
331                 // but sometimes it's missing : we assume Gray pixels
332    return atoi(StrSize.c_str());
333 }
334
335 /**
336  * \ingroup gdcmHeader
337  * \brief   Retrieve the Planar Configuration for RGB images
338  *          (0 : RGB Pixels , 1 : R Plane + G Plane + B Plane)
339  * 
340  * @return  The encountered Planar Configuration, 0 by default.
341  */
342 int gdcmHeader::GetPlanarConfiguration(void) { 
343    std::string StrSize = GetEntryByNumber(0x0028,0x0006);
344    if (StrSize == GDCM_UNFOUND)
345       return 0;
346    return atoi(StrSize.c_str());
347 }
348
349 /**
350  * \ingroup gdcmHeader
351  * \brief   Return the size (in bytes) of a single pixel of data.
352  * @return  The size in bytes of a single pixel of data; 0 by default
353  *          0 means the file is NOT USABLE; the caller will have to check        
354  */
355 int gdcmHeader::GetPixelSize(void) {
356    std::string PixelType = GetPixelType();
357    if (PixelType == "8U"  || PixelType == "8S")
358       return 1;
359    if (PixelType == "16U" || PixelType == "16S")
360       return 2;
361    if (PixelType == "32U" || PixelType == "32S")
362       return 4;
363    dbg.Verbose(0, "gdcmHeader::GetPixelSize: Unknown pixel type");
364    return 0;
365 }
366
367 /**
368  * \ingroup gdcmHeader
369  * \brief   Build the Pixel Type of the image.
370  *          Possible values are:
371  *          - 8U  unsigned  8 bit,
372  *          - 8S    signed  8 bit,
373  *          - 16U unsigned 16 bit,
374  *          - 16S   signed 16 bit,
375  *          - 32U unsigned 32 bit,
376  *          - 32S   signed 32 bit,
377  * \warning 12 bit images appear as 16 bit.
378  * \        24 bit images appear as 8 bit
379  * @return  0S if nothing found. NOT USABLE file. The caller has to check
380  */
381 std::string gdcmHeader::GetPixelType(void) {
382    std::string BitsAlloc = GetEntryByNumber(0x0028, 0x0100); // Bits Allocated
383    if (BitsAlloc == GDCM_UNFOUND) {
384       dbg.Verbose(0, "gdcmHeader::GetPixelType: unfound Bits Allocated");
385       BitsAlloc = std::string("16");
386    }
387    if (BitsAlloc == "12")            // It will be unpacked
388       BitsAlloc = std::string("16");
389    else if (BitsAlloc == "24")       // (in order no to be messed up
390       BitsAlloc = std::string("8");  // by old RGB images)
391      
392    std::string Signed = GetEntryByNumber(0x0028, 0x0103); // "Pixel Representation"
393    if (Signed == GDCM_UNFOUND) {
394       dbg.Verbose(0, "gdcmHeader::GetPixelType: unfound Pixel Representation");
395       BitsAlloc = std::string("0");
396    }
397    if (Signed == "0")
398       Signed = std::string("U");
399    else
400       Signed = std::string("S");
401
402    return( BitsAlloc + Signed);
403 }
404
405 /**
406  * \ingroup gdcmHeader
407  * \brief   Recover the offset (from the beginning of the file) of the pixels.
408  */
409 size_t gdcmHeader::GetPixelOffset(void) {
410    // If this file complies with the norm we should encounter the
411    // "Image Location" tag (0x0028, 0x0200). This tag contains the
412    // the group that contains the pixel data (hence the "Pixel Data"
413    // is found by indirection through the "Image Location").
414    // Inside the group pointed by "Image Location" the searched element
415    // is conventionally the element 0x0010 (when the norm is respected).
416    // When the "Image Location" is absent we default to group 0x7fe0.
417    guint16 grPixel;
418    guint16 numPixel;
419    std::string ImageLocation = GetEntryByNumber(0x0028, 0x0200);
420
421    if ( ImageLocation == GDCM_UNFOUND ) { // Image Location
422       grPixel = 0x7fe0;
423    } else {
424       grPixel = (guint16) atoi( ImageLocation.c_str() );
425    }
426    if (grPixel != 0x7fe0)
427       // This is a kludge for old dirty Philips imager.
428       numPixel = 0x1010;
429    else
430       numPixel = 0x0010;
431          
432    gdcmHeaderEntry* PixelElement = GetHeaderEntryByNumber(grPixel,numPixel);
433    if (PixelElement)
434       return PixelElement->GetOffset();
435    else
436       return 0;
437 }
438
439 /**
440  * \ingroup gdcmHeader
441  * \brief   Recover the pixel area length (in Bytes)
442  *  @return 0 by default. NOT USABLE file. The caller has to check.
443  */
444 size_t gdcmHeader::GetPixelAreaLength(void) {
445    // If this file complies with the norm we should encounter the
446    // "Image Location" tag (0x0028,  0x0200). This tag contains the
447    // the group that contains the pixel data (hence the "Pixel Data"
448    // is found by indirection through the "Image Location").
449    // Inside the group pointed by "Image Location" the searched element
450    // is conventionally the element 0x0010 (when the norm is respected).
451    // When the "Image Location" is absent we default to group 0x7fe0.
452    guint16 grPixel;
453    guint16 numPixel;
454    std::string ImageLocation = GetEntryByNumber(0x0028, 0x0200);
455    if ( ImageLocation == GDCM_UNFOUND ) {
456       grPixel = 0x7fe0;
457    } else {
458       grPixel = (guint16) atoi( ImageLocation.c_str() );
459    }
460    if (grPixel != 0x7fe0)
461       // This is a kludge for old dirty Philips imager.
462       numPixel = 0x1010;
463    else
464       numPixel = 0x0010;
465          
466    gdcmHeaderEntry* PixelElement = GetHeaderEntryByNumber(grPixel,numPixel);
467    if (PixelElement)
468       return PixelElement->GetLength();
469    else
470       return 0;
471 }
472
473 /**
474   * \ingroup gdcmHeader
475   * \brief tells us if LUT are used
476   * \warning Right now, 'Segmented xxx Palette Color Lookup Table Data'
477   * \        are NOT considered as LUT, since nobody knows
478   * \        how to deal with them
479   * @return a Boolean 
480   */
481 bool gdcmHeader::HasLUT(void) {
482
483    // Check the presence of the LUT Descriptors 
484    if ( !GetHeaderEntryByNumber(0x0028,0x1101) )
485       return false;
486    // LutDescriptorGreen 
487    if ( !GetHeaderEntryByNumber(0x0028,0x1102) )
488       return false;
489    // LutDescriptorBlue 
490    if ( !GetHeaderEntryByNumber(0x0028,0x1103) )
491       return false;
492    //  It is not enough
493    // we check also 
494    if ( !GetHeaderEntryByNumber(0x0028,0x1201) )
495       return false;  
496    if ( !GetHeaderEntryByNumber(0x0028,0x1202) )
497       return false;
498    if ( !GetHeaderEntryByNumber(0x0028,0x1203) )
499       return false;   
500    return true;
501 }
502
503 /**
504   * \ingroup gdcmHeader
505   * \brief gets the info from 0028,1101 : Lookup Table Desc-Red
506   * \           else 0
507   * @return Lookup Table number of Bits , 0 by default
508   * \       when (0028,0004),Photometric Interpretation = [PALETTE COLOR ] 
509   */
510 int gdcmHeader::GetLUTNbits(void) {
511    std::vector<std::string> tokens;
512    //int LutLength;
513    //int LutDepth;
514    int LutNbits;
515    //Just hope Lookup Table Desc-Red = Lookup Table Desc-Red = Lookup Table Desc-Blue
516    // Consistency already checked in GetLUTLength
517    std::string LutDescription = GetEntryByNumber(0x0028,0x1101);
518    if (LutDescription == GDCM_UNFOUND)
519       return 0;
520    tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
521    Tokenize (LutDescription, tokens, "\\");
522    //LutLength=atoi(tokens[0].c_str());
523    //LutDepth=atoi(tokens[1].c_str());
524    LutNbits=atoi(tokens[2].c_str());
525    tokens.clear();
526    return LutNbits;
527 }
528
529 /**
530   * \ingroup gdcmHeader
531   * \brief builts Red/Green/Blue/Alpha LUT from Header
532   * \       when (0028,0004),Photometric Interpretation = [PALETTE COLOR ]
533   * \        and (0028,1101),(0028,1102),(0028,1102)  
534   * \          - xxx Palette Color Lookup Table Descriptor - are found
535   * \        and (0028,1201),(0028,1202),(0028,1202) 
536   * \          - xxx Palette Color Lookup Table Data - are found 
537   * \warning does NOT deal with :
538   * \ 0028 1100 Gray Lookup Table Descriptor (Retired)
539   * \ 0028 1221 Segmented Red Palette Color Lookup Table Data
540   * \ 0028 1222 Segmented Green Palette Color Lookup Table Data
541   * \ 0028 1223 Segmented Blue Palette Color Lookup Table Data 
542   * \ no known Dicom reader deals with them :-(
543   * @return a RGBA Lookup Table 
544   */ 
545 unsigned char * gdcmHeader::GetLUTRGBA(void) {
546 // Not so easy : see 
547 // http://www.barre.nom.fr/medical/dicom2/limitations.html#Color%20Lookup%20Tables
548
549 //  if Photometric Interpretation # PALETTE COLOR, no LUT to be done
550    if (GetEntryByNumber(0x0028,0x0004) != "PALETTE COLOR ") {
551         return NULL;
552    }  
553    int lengthR, debR, nbitsR;
554    int lengthG, debG, nbitsG;
555    int lengthB, debB, nbitsB;
556    
557 // Get info from Lut Descriptors
558 // (the 3 LUT descriptors may be different)    
559    std::string LutDescriptionR = GetEntryByNumber(0x0028,0x1101);
560    if (LutDescriptionR == GDCM_UNFOUND)
561       return NULL;
562    std::string LutDescriptionG = GetEntryByNumber(0x0028,0x1102);
563    if (LutDescriptionG == GDCM_UNFOUND)
564       return NULL;   
565    std::string LutDescriptionB = GetEntryByNumber(0x0028,0x1103);
566    if (LutDescriptionB == GDCM_UNFOUND)
567       return NULL;
568       
569    std::vector<std::string> tokens;
570       
571    tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
572    Tokenize (LutDescriptionR, tokens, "\\");
573    lengthR=atoi(tokens[0].c_str()); // Red LUT length in Bytes
574    debR   =atoi(tokens[1].c_str()); // subscript of the first Lut Value
575    nbitsR =atoi(tokens[2].c_str()); // Lut item size (in Bits)
576    tokens.clear();
577    
578    tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
579    Tokenize (LutDescriptionG, tokens, "\\");
580    lengthG=atoi(tokens[0].c_str()); // Green LUT length in Bytes
581    debG   =atoi(tokens[1].c_str());
582    nbitsG =atoi(tokens[2].c_str());
583    tokens.clear();  
584    
585    tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
586    Tokenize (LutDescriptionB, tokens, "\\");
587    lengthB=atoi(tokens[0].c_str()); // Blue LUT length in Bytes
588    debB   =atoi(tokens[1].c_str());
589    nbitsB =atoi(tokens[2].c_str());
590    tokens.clear();
591  
592    // Load LUTs into memory, (as they were stored on disk)
593    unsigned char *lutR = (unsigned char *)
594                          GetEntryVoidAreaByNumber(0x0028,0x1201);
595    unsigned char *lutG = (unsigned char *)
596                          GetEntryVoidAreaByNumber(0x0028,0x1202);
597    unsigned char *lutB = (unsigned char *)
598                          GetEntryVoidAreaByNumber(0x0028,0x1203); 
599    
600    if (!lutR || !lutG || !lutB ) {
601         return NULL;
602    } 
603    // forge the 4 * 8 Bits Red/Green/Blue/Alpha LUT 
604    
605    unsigned char *LUTRGBA = (unsigned char *)calloc(1024,1); // 256 * 4 (R, G, B, Alpha) 
606    if (!LUTRGBA) {
607       return NULL;
608    }
609    memset(LUTRGBA, 0, 1024);
610         // Bits Allocated
611    int nb;
612    std::string str_nb = GetEntryByNumber(0x0028,0x0100);
613    if (str_nb == GDCM_UNFOUND ) {
614       nb = 16;
615    } else {
616       nb = atoi(str_nb.c_str() );
617    }  
618    int mult;
619
620    if (nbitsR==16 && nb==8) // when LUT item size is different than pixel size
621       mult=2;               // high byte must be = low byte 
622    else                     // See PS 3.3-2003 C.11.1.1.2 p 619
623       mult=1; 
624  
625    // if we get a black image, let's just remove the '+1'
626    // from 'i*mult+1' and check again 
627    // if it works, we shall have to check the 3 Palettes
628    // to see which byte is ==0 (first one, or second one)
629    // and fix the code
630    // We give up the checking to avoid some overhead 
631    unsigned char *a;      
632    int i;
633
634    a = LUTRGBA+0;
635    for(i=0;i<lengthR;i++) {
636       *a = lutR[i*mult+1]; 
637       a+=4;       
638    }        
639    a = LUTRGBA+1;
640    for(i=0;i<lengthG;i++) {
641       *a = lutG[i*mult+1]; 
642       a+=4;       
643    }  
644    a = LUTRGBA+2;
645    for(i=0;i<lengthB;i++) {
646       *a = lutB[i*mult+1]; 
647       a+=4;       
648    }  
649    a = LUTRGBA+3;
650    for(i=0;i<256;i++) {
651       *a = 1; // Alpha component
652       a+=4; 
653    } 
654    
655    //How to free the now useless LUTs?
656
657    //free(LutR); free(LutB); free(LutG); // Seg Fault when used
658    return(LUTRGBA);   
659
660
661 /**
662  * \ingroup gdcmHeader
663  * \brief gets the info from 0002,0010 : Transfert Syntax
664  * \      else 1.
665  * @return Transfert Syntax Name (as oposite to Transfert Syntax UID)
666  */
667 std::string gdcmHeader::GetTransfertSyntaxName(void) { 
668    // use the gdcmTS (TS : Transfert Syntax)
669    std::string TransfertSyntax = GetEntryByNumber(0x0002,0x0010);
670    if (TransfertSyntax == GDCM_UNFOUND) {
671       dbg.Verbose(0, "gdcmHeader::GetTransfertSyntaxName: unfound Transfert Syntax (0002,0010)");
672       return "Uncompressed ACR-NEMA";
673    }
674    // we do it only when we need it
675    gdcmTS * ts = gdcmGlobal::GetTS();
676    std::string tsName=ts->GetValue(TransfertSyntax);
677    //delete ts; // Seg Fault when deleted ?!
678    return tsName;
679 }
680
681 /**
682  * \ingroup   gdcmFile
683  * \brief Sets the Pixel Area size in the Header
684  *        --> not-for-rats function
685  * 
686  * \warning WARNING doit-etre etre publique ? 
687  * TODO : y aurait il un inconvenient à fusionner ces 2 fonctions
688  *
689  * @param ImageDataSize new Pixel Area Size
690  *        warning : nothing else is checked
691  */
692 void gdcmHeader::SetImageDataSize(size_t ImageDataSize) {
693    std::string content1;
694    char car[20];        
695    // Assumes HeaderEntry (0x7fe0, 0x0010) exists ...   
696    sprintf(car,"%d",ImageDataSize);
697  
698    gdcmHeaderEntry *a = GetHeaderEntryByNumber(0x7fe0, 0x0010);
699    a->SetLength(ImageDataSize);
700                 
701    ImageDataSize+=8;
702    sprintf(car,"%d",ImageDataSize);
703    content1=car;        
704    SetEntryByNumber(content1, 0x7fe0, 0x0000);
705 }
706
707 //-----------------------------------------------------------------------------
708 // Protected
709
710 //-----------------------------------------------------------------------------
711 // Private
712
713 //-----------------------------------------------------------------------------