1 /*=========================================================================
4 Module: $RCSfile: gdcmFile.cxx,v $
6 Date: $Date: 2004/10/22 03:05:41 $
7 Version: $Revision: 1.148 $
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.
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.
17 =========================================================================*/
20 #include "gdcmDebug.h"
25 typedef std::pair<TagDocEntryHT::iterator,TagDocEntryHT::iterator> IterHT;
27 //-------------------------------------------------------------------------
28 // Constructor / Destructor
30 * \brief Constructor dedicated to deal with the *pixels* area of a ACR/DICOMV3
31 * file (Header only deals with the ... header)
32 * Opens (in read only and when possible) an existing file and checks
33 * for DICOM compliance. Returns NULL on failure.
34 * It will be up to the user to load the pixels into memory
35 * (see GetImageData, GetImageDataRaw)
36 * \note the in-memory representation of all available tags found in
37 * the DICOM header is post-poned to first header information access.
38 * This avoid a double parsing of public part of the header when
39 * user sets an a posteriori shadow dictionary (efficiency can be
40 * seen as a side effect).
41 * @param header already built Header
43 File::File(Header *header)
45 HeaderInternal = header;
51 * \brief Constructor dedicated to deal with the *pixels* area of a ACR/DICOMV3
52 * file (Header only deals with the ... header)
53 * Opens (in read only and when possible) an existing file and checks
54 * for DICOM compliance. Returns NULL on failure.
55 * It will be up to the user to load the pixels into memory
56 * (see GetImageData, GetImageDataRaw)
57 * \note the in-memory representation of all available tags found in
58 * the DICOM header is post-poned to first header information access.
59 * This avoid a double parsing of public part of the header when
60 * one sets an a posteriori shadow dictionary (efficiency can be
61 * seen as a side effect).
62 * @param filename file to be opened for parsing
64 File::File(std::string const & filename )
66 HeaderInternal = new Header( filename );
72 * \brief Factorization for various forms of constructors.
74 void File::Initialise()
76 if ( HeaderInternal->IsReadable() )
78 ImageDataSizeRaw = ComputeDecompressedPixelDataSizeFromHeader();
79 if ( HeaderInternal->HasLUT() )
81 ImageDataSize = 3 * ImageDataSizeRaw;
85 ImageDataSize = ImageDataSizeRaw;
88 PixelConverter = new PixelConvert;
89 PixelConverter->GrabInformationsFromHeader( HeaderInternal );
95 * \brief canonical destructor
96 * \note If the Header was created by the File constructor,
97 * it is destroyed by the File
103 delete HeaderInternal;
107 DeleteInitialValues();
111 * \brief Sets some initial values for the Constructor
112 * \warning not end user intended
114 void File::SaveInitialValues()
117 PixelRead = -1; // no ImageData read yet.
118 LastAllocatedPixelDataLength = 0;
123 InitialPlanConfig = "";
124 InitialBitsAllocated = "";
127 InitialRedLUTDescr = 0;
128 InitialGreenLUTDescr = 0;
129 InitialBlueLUTDescr = 0;
130 InitialRedLUTData = 0;
131 InitialGreenLUTData = 0;
132 InitialBlueLUTData = 0;
134 if ( HeaderInternal->IsReadable() )
136 // the following values *may* be modified
137 // by File::GetImageDataIntoVectorRaw
138 // we save their initial value.
139 InitialSpp = HeaderInternal->GetEntryByNumber(0x0028,0x0002);
140 InitialPhotInt = HeaderInternal->GetEntryByNumber(0x0028,0x0004);
141 InitialPlanConfig = HeaderInternal->GetEntryByNumber(0x0028,0x0006);
143 InitialBitsAllocated = HeaderInternal->GetEntryByNumber(0x0028,0x0100);
144 InitialHighBit = HeaderInternal->GetEntryByNumber(0x0028,0x0102);
146 // the following entries *may* be removed from the H table
147 // (NOT deleted ...) by File::GetImageDataIntoVectorRaw
148 // we keep a pointer on them.
149 InitialRedLUTDescr = HeaderInternal->GetDocEntryByNumber(0x0028,0x1101);
150 InitialGreenLUTDescr = HeaderInternal->GetDocEntryByNumber(0x0028,0x1102);
151 InitialBlueLUTDescr = HeaderInternal->GetDocEntryByNumber(0x0028,0x1103);
153 InitialRedLUTData = HeaderInternal->GetDocEntryByNumber(0x0028,0x1201);
154 InitialGreenLUTData = HeaderInternal->GetDocEntryByNumber(0x0028,0x1202);
155 InitialBlueLUTData = HeaderInternal->GetDocEntryByNumber(0x0028,0x1203);
160 * \brief restores some initial values
161 * \warning not end user intended
163 void File::RestoreInitialValues()
165 if ( HeaderInternal->IsReadable() )
167 // the following values *may* have been modified
168 // by File::GetImageDataIntoVectorRaw
169 // we restore their initial value.
170 if ( InitialSpp != "")
171 HeaderInternal->SetEntryByNumber(InitialSpp,0x0028,0x0002);
172 if ( InitialPhotInt != "")
173 HeaderInternal->SetEntryByNumber(InitialPhotInt,0x0028,0x0004);
174 if ( InitialPlanConfig != "")
176 HeaderInternal->SetEntryByNumber(InitialPlanConfig,0x0028,0x0006);
177 if ( InitialBitsAllocated != "")
178 HeaderInternal->SetEntryByNumber(InitialBitsAllocated,0x0028,0x0100);
179 if ( InitialHighBit != "")
180 HeaderInternal->SetEntryByNumber(InitialHighBit,0x0028,0x0102);
182 // the following entries *may* be have been removed from the H table
183 // (NOT deleted ...) by File::GetImageDataIntoVectorRaw
186 if (InitialRedLUTDescr)
187 HeaderInternal->AddEntry(InitialRedLUTDescr);
188 if (InitialGreenLUTDescr)
189 HeaderInternal->AddEntry(InitialGreenLUTDescr);
190 if (InitialBlueLUTDescr)
191 HeaderInternal->AddEntry(InitialBlueLUTDescr);
193 if (InitialRedLUTData)
194 HeaderInternal->AddEntry(InitialBlueLUTDescr);
195 if (InitialGreenLUTData)
196 HeaderInternal->AddEntry(InitialGreenLUTData);
197 if (InitialBlueLUTData)
198 HeaderInternal->AddEntry(InitialBlueLUTData);
203 * \brief delete initial values (il they were saved)
204 * of InitialLutDescriptors and InitialLutData
206 void File::DeleteInitialValues()
209 // InitialLutDescriptors and InitialLutData
210 // will have to be deleted if the don't belong any longer
211 // to the Header H table when the header is deleted...
213 if ( InitialRedLUTDescr )
214 delete InitialRedLUTDescr;
216 if ( InitialGreenLUTDescr )
217 delete InitialGreenLUTDescr;
219 if ( InitialBlueLUTDescr )
220 delete InitialBlueLUTDescr;
222 if ( InitialRedLUTData )
223 delete InitialRedLUTData;
225 if ( InitialGreenLUTData != NULL)
226 delete InitialGreenLUTData;
228 if ( InitialBlueLUTData != NULL)
229 delete InitialBlueLUTData;
232 //-----------------------------------------------------------------------------
235 //-----------------------------------------------------------------------------
239 * \brief computes the length (in bytes) we must ALLOCATE to receive the
240 * image(s) pixels (multiframes taken into account)
241 * \warning : it is NOT the group 7FE0 length
242 * (no interest for compressed images).
244 int File::ComputeDecompressedPixelDataSizeFromHeader()
246 // see PS 3.3-2003 : C.7.6.3.2.1
256 // YBR_FULL_422 (no LUT, no Palette)
262 // ex : gdcm-US-ALOKA-16.dcm
263 // 0028|1221 [OW] [Segmented Red Palette Color Lookup Table Data]
264 // 0028|1222 [OW] [Segmented Green Palette Color Lookup Table Data]
265 // 0028|1223 [OW] [Segmented Blue Palette Color Lookup Table Data]
267 // ex : OT-PAL-8-face.dcm
268 // 0028|1201 [US] [Red Palette Color Lookup Table Data]
269 // 0028|1202 [US] [Green Palette Color Lookup Table Data]
270 // 0028|1203 [US] [Blue Palette Color Lookup Table Data]
272 int numberBitsAllocated = HeaderInternal->GetBitsAllocated();
273 // Number of "Bits Allocated" is fixed to 16 when:
274 // - it is not defined (i.e. it's value is 0)
275 // - it's 12, since we will expand the image to 16 bits (see
276 // PixelConvert::ConvertDecompress12BitsTo16Bits() )
277 if ( ( numberBitsAllocated == 0 ) || ( numberBitsAllocated == 12 ) )
279 numberBitsAllocated = 16;
282 int DecompressedSize = HeaderInternal->GetXSize()
283 * HeaderInternal->GetYSize()
284 * HeaderInternal->GetZSize()
285 * ( numberBitsAllocated / 8 )
286 * HeaderInternal->GetSamplesPerPixel();
288 return DecompressedSize;
292 * \brief - Allocates necessary memory,
293 * - Reads the pixels from disk (uncompress if necessary),
294 * - Transforms YBR pixels, if any, into RGB pixels
295 * - Transforms 3 planes R, G, B, if any, into a single RGB Plane
296 * - Transforms single Grey plane + 3 Palettes into a RGB Plane
297 * - Copies the pixel data (image[s]/volume[s]) to newly allocated zone.
298 * @return Pointer to newly allocated pixel data.
299 * NULL if alloc fails
301 uint8_t* File::GetImageData()
304 // I need to deallocate Pixel_Data before doing any allocation:
307 if ( LastAllocatedPixelDataLength != ImageDataSize )
310 Pixel_Data = new uint8_t[ImageDataSize];
314 LastAllocatedPixelDataLength = ImageDataSize;
316 // we load the pixels (and transform grey level + LUT into RGB)
317 GetImageDataIntoVector(Pixel_Data, ImageDataSize);
319 // We say the value *is* loaded.
320 GetHeader()->SetEntryByNumber( GDCM_BINLOADED,
321 GetHeader()->GetGrPixel(), GetHeader()->GetNumPixel());
323 // Will be 7fe0, 0010 in standard case
324 GetHeader()->SetEntryBinAreaByNumber( Pixel_Data,
325 GetHeader()->GetGrPixel(), GetHeader()->GetNumPixel());
327 PixelRead = 0; // no PixelRaw
334 * Read the pixels from disk (uncompress if necessary),
335 * Transforms YBR pixels, if any, into RGB pixels
336 * Transforms 3 planes R, G, B, if any, into a single RGB Plane
337 * Transforms single Grey plane + 3 Palettes into a RGB Plane
338 * Copies at most MaxSize bytes of pixel data to caller allocated
340 * \warning This function allows people that want to build a volume
341 * from an image stack *not to* have, first to get the image pixels,
342 * and then move them to the volume area.
343 * It's absolutely useless for any VTK user since vtk chooses
344 * to invert the lines of an image, that is the last line comes first
345 * (for some axis related reasons?). Hence he will have
346 * to load the image line by line, starting from the end.
347 * VTK users have to call GetImageData
349 * @param destination Address (in caller's memory space) at which the
350 * pixel data should be copied
351 * @param maxSize Maximum number of bytes to be copied. When MaxSize
352 * is not sufficient to hold the pixel data the copy is not
353 * executed (i.e. no partial copy).
354 * @return On success, the number of bytes actually copied. Zero on
355 * failure e.g. MaxSize is lower than necessary.
357 size_t File::GetImageDataIntoVector (void* destination, size_t maxSize)
359 GetImageDataIntoVectorRaw (destination, maxSize);
360 PixelRead = 0 ; // =0 : no ImageDataRaw
361 if ( !HeaderInternal->HasLUT() )
363 return ImageDataSize;
366 std::ifstream* fp = HeaderInternal->OpenFile();
367 if ( PixelConverter->BuildRGBImage() )
369 memmove( destination,
370 (void*)PixelConverter->GetRGB(),
371 PixelConverter->GetRGBSize() );
373 // now, it's an RGB image
374 // Lets's write it in the Header
376 // FIXME : Better use CreateOrReplaceIfExist ?
378 std::string spp = "3"; // Samples Per Pixel
379 HeaderInternal->SetEntryByNumber(spp,0x0028,0x0002);
380 std::string rgb = "RGB "; // Photometric Interpretation
381 HeaderInternal->SetEntryByNumber(rgb,0x0028,0x0004);
382 std::string planConfig = "0"; // Planar Configuration
383 HeaderInternal->SetEntryByNumber(planConfig,0x0028,0x0006);
388 // PixelConverter->BuildRGBImage() failed probably because
389 // PixelConverter->GetLUTRGBA() failed:
390 // (gdcm-US-ALOKA-16.dcm), contains Segmented xxx Palette Color
391 // that are *more* than 65535 long ?!?
392 // No idea how to manage such an image !
393 // Need to make RGB Pixels (?) from grey Pixels (?!) and Gray Lut (!?!)
394 // It seems that *no Dicom Viewer* has any idea :-(
396 std::string photomInterp = "MONOCHROME1 "; // Photometric Interpretation
397 HeaderInternal->SetEntryByNumber(photomInterp,0x0028,0x0004);
400 /// \todo Drop Palette Color out of the Header?
401 return ImageDataSize;
405 * \brief Allocates necessary memory,
406 * Transforms YBR pixels (if any) into RGB pixels
407 * Transforms 3 planes R, G, B (if any) into a single RGB Plane
408 * Copies the pixel data (image[s]/volume[s]) to newly allocated zone.
409 * DOES NOT transform Grey plane + 3 Palettes into a RGB Plane
410 * @return Pointer to newly allocated pixel data.
411 * \ NULL if alloc fails
413 uint8_t* File::GetImageDataRaw ()
415 uint8_t* decompressed = PixelConverter->GetDecompressed();
416 if ( ! decompressed )
418 // The decompressed image migth not be loaded yet:
419 std::ifstream* fp = HeaderInternal->OpenFile();
420 PixelConverter->ReadAndDecompressPixelData( fp );
421 HeaderInternal->CloseFile();
422 if ( ! decompressed )
424 dbg.Verbose(0, "File::GetImageDataRaw: read/decompress of "
425 "pixel data apparently went wrong.");
430 // PIXELCONVERT CLEANME
431 // Restore the header in a disk-consistent state
432 // (if user asks twice to get the pixels from disk)
433 if ( PixelRead != -1 ) // File was "read" before
435 RestoreInitialValues();
437 if ( PixelConverter->IsDecompressedRGB() )
439 ///////////////////////////////////////////////////
440 // now, it's an RGB image
441 // Lets's write it in the Header
442 // Droping Palette Color out of the Header
443 // has been moved to the Write process.
444 // TODO : move 'values' modification to the write process
445 // : save also (in order to be able to restore)
446 // : 'high bit' -when not equal to 'bits stored' + 1
447 // : 'bits allocated', when it's equal to 12 ?!
448 std::string spp = "3"; // Samples Per Pixel
449 std::string photInt = "RGB "; // Photometric Interpretation
450 std::string planConfig = "0"; // Planar Configuration
451 HeaderInternal->SetEntryByNumber(spp,0x0028,0x0002);
452 HeaderInternal->SetEntryByNumber(photInt,0x0028,0x0004);
453 HeaderInternal->SetEntryByNumber(planConfig,0x0028,0x0006);
456 // We say the value *is* loaded.
457 GetHeader()->SetEntryByNumber( GDCM_BINLOADED,
458 GetHeader()->GetGrPixel(), GetHeader()->GetNumPixel());
460 // will be 7fe0, 0010 in standard cases
461 GetHeader()->SetEntryBinAreaByNumber( decompressed,
462 GetHeader()->GetGrPixel(), GetHeader()->GetNumPixel());
464 PixelRead = 1; // PixelRaw
465 // END PIXELCONVERT CLEANME
471 * \brief Copies at most MaxSize bytes of pixel data to caller's
473 * \warning This function was designed to avoid people that want to build
474 * a volume from an image stack to need first to get the image pixels
475 * and then move them to the volume area.
476 * It's absolutely useless for any VTK user since vtk chooses
477 * to invert the lines of an image, that is the last line comes first
478 * (for some axis related reasons?). Hence he will have
479 * to load the image line by line, starting from the end.
480 * VTK users hace to call GetImageData
481 * \warning DOES NOT transform the Grey Plane + Palette Color (if any)
482 * into a single RGB Pixels Plane
483 * the (VTK) user will manage the palettes
485 * @param destination Address (in caller's memory space) at which the
486 * pixel data should be copied
487 * @param maxSize Maximum number of bytes to be copied. When MaxSize
488 * is not sufficient to hold the pixel data the copy is not
489 * executed (i.e. no partial copy).
490 * @return On success, the number of bytes actually copied. Zero on
491 * failure e.g. MaxSize is lower than necessary.
493 void File::GetImageDataIntoVectorRaw (void* destination, size_t maxSize)
495 // we save the initial values of the following
496 // in order to be able to restore the header in a disk-consistent state
497 // (if user asks twice to get the pixels from disk)
499 if ( PixelRead != -1 ) // File was "read" before
501 RestoreInitialValues();
504 PixelRead = 1 ; // PixelRaw
506 if ( ImageDataSize > maxSize )
508 dbg.Verbose(0, "File::GetImageDataIntoVector: pixel data bigger"
509 "than caller's expected MaxSize");
513 std::ifstream* fp = HeaderInternal->OpenFile();
514 PixelConverter->ReadAndDecompressPixelData( fp );
515 HeaderInternal->CloseFile();
516 memmove( destination,
517 (void*)PixelConverter->GetDecompressed(),
518 PixelConverter->GetDecompressedSize() );
520 if ( ! PixelConverter->IsDecompressedRGB() )
525 ///////////////////////////////////////////////////
526 // now, it's an RGB image
527 // Lets's write it in the Header
529 // Droping Palette Color out of the Header
530 // has been moved to the Write process.
532 // TODO : move 'values' modification to the write process
533 // : save also (in order to be able to restore)
534 // : 'high bit' -when not equal to 'bits stored' + 1
535 // : 'bits allocated', when it's equal to 12 ?!
537 std::string spp = "3"; // Samples Per Pixel
538 std::string photInt = "RGB "; // Photometric Interpretation
539 std::string planConfig = "0"; // Planar Configuration
541 HeaderInternal->SetEntryByNumber(spp,0x0028,0x0002);
542 HeaderInternal->SetEntryByNumber(photInt,0x0028,0x0004);
543 HeaderInternal->SetEntryByNumber(planConfig,0x0028,0x0006);
549 * \brief Points the internal Pixel_Data pointer to the callers inData
550 * image representation, BUT WITHOUT COPYING THE DATA.
551 * 'image' Pixels are presented as C-like 2D arrays : line per line.
552 * 'volume'Pixels are presented as C-like 3D arrays : plane per plane
553 * \warning Since the pixels are not copied, it is the caller's responsability
554 * not to deallocate it's data before gdcm uses them (e.g. with
555 * the Write() method.
556 * @param inData user supplied pixel area
557 * @param expectedSize total image size, in Bytes
561 bool File::SetImageData(uint8_t* inData, size_t expectedSize)
563 HeaderInternal->SetImageDataSize( expectedSize );
564 // FIXME : if already allocated, memory leak !
566 ImageDataSize = ImageDataSizeRaw = expectedSize;
568 // FIXME : 7fe0, 0010 IS NOT set ...
573 * \brief Writes on disk A SINGLE Dicom file
574 * NO test is performed on processor "Endiannity".
575 * It's up to the user to call his Reader properly
576 * @param fileName name of the file to be created
577 * (any already existing file is over written)
578 * @return false if write fails
581 bool File::WriteRawData(std::string const & fileName)
583 std::ofstream fp1(fileName.c_str(), std::ios::out | std::ios::binary );
586 printf("Fail to open (write) file [%s] \n", fileName.c_str());
589 fp1.write((char*)Pixel_Data, ImageDataSize);
596 * \brief Writes on disk A SINGLE Dicom file,
597 * using the Implicit Value Representation convention
598 * NO test is performed on processor "Endiannity".
599 * @param fileName name of the file to be created
600 * (any already existing file is overwritten)
601 * @return false if write fails
604 bool File::WriteDcmImplVR (std::string const & fileName)
606 return WriteBase(fileName, ImplicitVR);
610 * \brief Writes on disk A SINGLE Dicom file,
611 * using the Explicit Value Representation convention
612 * NO test is performed on processor "Endiannity". * @param fileName name of the file to be created
613 * (any already existing file is overwritten)
614 * @return false if write fails
617 bool File::WriteDcmExplVR (std::string const & fileName)
619 return WriteBase(fileName, ExplicitVR);
623 * \brief Writes on disk A SINGLE Dicom file,
624 * using the ACR-NEMA convention
625 * NO test is performed on processor "Endiannity".
626 * (a l'attention des logiciels cliniques
627 * qui ne prennent en entrée QUE des images ACR ...
628 * \warning if a DICOM_V3 header is supplied,
629 * groups < 0x0008 and shadow groups are ignored
630 * \warning NO TEST is performed on processor "Endiannity".
631 * @param fileName name of the file to be created
632 * (any already existing file is overwritten)
633 * @return false if write fails
636 bool File::WriteAcr (std::string const & fileName)
638 return WriteBase(fileName, ACR);
641 //-----------------------------------------------------------------------------
644 * \brief NOT a end user inteded function
645 * (used by WriteDcmExplVR, WriteDcmImplVR, WriteAcr, etc)
646 * @param fileName name of the file to be created
647 * (any already existing file is overwritten)
648 * @param type file type (ExplicitVR, ImplicitVR, ...)
649 * @return false if write fails
651 bool File::WriteBase (std::string const & fileName, FileType type)
653 if ( PixelRead == -1 && type != ExplicitVR)
658 std::ofstream* fp1 = new std::ofstream(fileName.c_str(),
659 std::ios::out | std::ios::binary);
662 printf("Failed to open (write) File [%s] \n", fileName.c_str());
666 if ( type == ImplicitVR || type == ExplicitVR )
668 // writing Dicom File Preamble
669 uint8_t* filePreamble = new uint8_t[128];
670 memset(filePreamble, 0, 128);
671 fp1->write((char*)filePreamble, 128);
672 fp1->write("DICM", 4);
674 delete[] filePreamble;
677 // --------------------------------------------------------------
678 // Special Patch to allow gdcm to re-write ACR-LibIDO formated images
680 // if recognition code tells us we dealt with a LibIDO image
681 // we reproduce on disk the switch between lineNumber and columnNumber
682 // just before writting ...
684 /// \todo the best trick would be *change* the recognition code
685 /// but pb expected if user deals with, e.g. COMPLEX images
687 std::string rows, columns;
688 if ( HeaderInternal->GetFileType() == ACR_LIBIDO)
690 rows = HeaderInternal->GetEntryByNumber(0x0028, 0x0010);
691 columns = HeaderInternal->GetEntryByNumber(0x0028, 0x0011);
693 HeaderInternal->SetEntryByNumber(columns, 0x0028, 0x0010);
694 HeaderInternal->SetEntryByNumber(rows , 0x0028, 0x0011);
696 // ----------------- End of Special Patch ----------------
698 uint16_t grPixel = HeaderInternal->GetGrPixel();
699 uint16_t numPixel = HeaderInternal->GetNumPixel();;
701 DocEntry* PixelElement =
702 GetHeader()->GetDocEntryByNumber(grPixel, numPixel);
704 if ( PixelRead == 1 )
706 // we read pixel 'as is' (no tranformation LUT -> RGB)
707 PixelElement->SetLength( ImageDataSizeRaw );
709 else if ( PixelRead == 0 )
711 // we tranformed GrayLevel pixels + LUT into RGB Pixel
712 PixelElement->SetLength( ImageDataSize );
715 HeaderInternal->Write(fp1, type);
717 // --------------------------------------------------------------
718 // Special Patch to allow gdcm to re-write ACR-LibIDO formated images
720 // ...and we restore the Header to be Dicom Compliant again
721 // just after writting
723 if ( HeaderInternal->GetFileType() == ACR_LIBIDO )
725 HeaderInternal->SetEntryByNumber(rows , 0x0028, 0x0010);
726 HeaderInternal->SetEntryByNumber(columns, 0x0028, 0x0011);
728 // ----------------- End of Special Patch ----------------
736 * \brief Access to the underlying \ref PixelConverter RGBA LUT
738 uint8_t* File::GetLutRGBA()
740 return PixelConverter->GetLutRGBA();
743 } // end namespace gdcm