1 /*=========================================================================
4 Module: $RCSfile: gdcmFileHelper.cxx,v $
7 Date: $Date: 2005/07/30 18:27:00 $
8 Version: $Revision: 1.51 $
10 Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
11 l'Image). All rights reserved. See Doc/License.txt or
12 http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
14 This software is distributed WITHOUT ANY WARRANTY; without even
15 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 PURPOSE. See the above copyright notices for more information.
18 =========================================================================*/
20 #include "gdcmFileHelper.h"
21 #include "gdcmGlobal.h"
23 #include "gdcmDocument.h"
24 #include "gdcmDebug.h"
26 #include "gdcmBinEntry.h"
27 #include "gdcmValEntry.h"
28 #include "gdcmSeqEntry.h"
29 #include "gdcmSQItem.h"
30 #include "gdcmContentEntry.h"
32 #include "gdcmPixelReadConvert.h"
33 #include "gdcmPixelWriteConvert.h"
34 #include "gdcmDocEntryArchive.h"
35 #include "gdcmDictSet.h"
40 // ----------------------------- WARNING -------------------------
42 These lines will be moved to the document-to-be 'User's Guide'
44 // To read an image, user needs a gdcm::File
45 gdcm::File *f1 = new gdcm::File(fileName);
46 // user can now check some values
47 std::string v = f1->GetEntryValue(groupNb,ElementNb);
48 // to get the pixels, user needs a gdcm::FileHelper
49 gdcm::FileHelper *fh1 = new gdcm::FileHelper(f1);
50 // user may ask not to convert Palette to RGB
51 uint8_t *pixels = fh1->GetImageDataRaw();
52 int imageLength = fh1->GetImageDataRawSize();
53 // He can now use the pixels, create a new image, ...
54 uint8_t *userPixels = ...
56 To re-write the image, user re-uses the gdcm::FileHelper
58 fh1->SetImageData( userPixels, userPixelsLength);
59 fh1->SetTypeToRaw(); // Even if it was possible to convert Palette to RGB
62 fh1->SetWriteTypeToDcmExpl(); // he wants Explicit Value Representation
63 // Little Endian is the default
64 // no other value is allowed
65 (-->SetWriteType(ExplicitVR);)
66 -->WriteType = ExplicitVR;
67 fh1->Write(newFileName); // overwrites the file, if any
70 fh1->WriteDcmExplVR(newFileName);
73 // ----------------------------- WARNING -------------------------
75 These lines will be moved to the document-to-be 'Developer's Guide'
77 WriteMode : WMODE_RAW / WMODE_RGB
78 WriteType : ImplicitVR, ExplicitVR, ACR, ACR_LIBIDO
80 fh1->Write(newFileName);
81 SetWriteFileTypeToImplicitVR() / SetWriteFileTypeToExplicitVR();
82 (modifies TransferSyntax)
83 SetWriteToRaw(); / SetWriteToRGB();
84 (modifies, when necessary : photochromatic interpretation,
85 samples per pixel, Planar configuration,
86 bits allocated, bits stored, high bit -ACR 24 bits-
87 Pixels element VR, pushes out the LUT )
88 CheckWriteIntegrity();
89 (checks user given pixels length)
90 FileInternal->Write(fileName,WriteType)
91 fp = opens file(fileName);
92 ComputeGroup0002Length(writetype);
94 RemoveEntryNoDestroy(palettes, etc)
95 Document::WriteContent(fp, writetype);
97 (moves back to the File all the archived elements)
98 RestoreWriteFileType();
99 (pushes back group 0002, with TransferSyntax)
107 //-------------------------------------------------------------------------
108 // Constructor / Destructor
110 * \brief Constructor dedicated to deal with the *pixels* area of a ACR/DICOMV3
111 * file (gdcm::File only deals with the ... header)
112 * Opens (in read only and when possible) an existing file and checks
113 * for DICOM compliance. Returns NULL on failure.
114 * It will be up to the user to load the pixels into memory
115 * \note the in-memory representation of all available tags found in
116 * the DICOM header is post-poned to first header information access.
117 * This avoid a double parsing of public part of the header when
118 * one sets an a posteriori shadow dictionary (efficiency can be
119 * seen as a side effect).
121 FileHelper::FileHelper( )
123 FileInternal = new File( );
130 * \brief Constructor dedicated to deal with the *pixels* area of a ACR/DICOMV3
131 * file (File only deals with the ... header)
132 * Opens (in read only and when possible) an existing file and checks
133 * for DICOM compliance. Returns NULL on failure.
134 * It will be up to the user to load the pixels into memory
135 * \note the in-memory representation of all available tags found in
136 * the DICOM header is post-poned to first header information access.
137 * This avoid a double parsing of public part of the header when
138 * user sets an a posteriori shadow dictionary (efficiency can be
139 * seen as a side effect).
140 * @param header already built Header
142 FileHelper::FileHelper(File *header)
144 FileInternal = header;
152 * \brief canonical destructor
153 * \note If the header (gdcm::File) was created by the FileHelper constructor,
154 * it is destroyed by the FileHelper
156 FileHelper::~FileHelper()
158 if ( PixelReadConverter )
160 delete PixelReadConverter;
162 if ( PixelWriteConverter )
164 delete PixelWriteConverter;
178 //-----------------------------------------------------------------------------
182 * \brief Sets the LoadMode of the internal gdcm::File as a boolean string.
183 * NO_SEQ, NO_SHADOW, NO_SHADOWSEQ
184 *... (nothing more, right now)
185 * WARNING : before using NO_SHADOW, be sure *all* your files
186 * contain accurate values in the 0x0000 element (if any)
187 * of *each* Shadow Group. The parser will fail if the size is wrong !
188 * @param loadMode Load mode to be used
190 void FileHelper::SetLoadMode(int loadMode)
192 GetFile()->SetLoadMode( loadMode );
195 * \brief Sets the LoadMode of the internal gdcm::File
196 * @param fileName name of the file to be open
198 void FileHelper::SetFileName(std::string const &fileName)
200 FileInternal->SetFileName( fileName );
205 * @return false if file cannot be open or no swap info was found,
206 * or no tag was found.
208 bool FileHelper::Load()
210 return FileInternal->Load();
214 * \brief Accesses an existing DocEntry (i.e. a Dicom Element)
215 * through it's (group, element) and modifies it's content with
217 * @param content new value (string) to substitute with
218 * @param group group number of the Dicom Element to modify
219 * @param elem element number of the Dicom Element to modify
220 * \return false if DocEntry not found
222 bool FileHelper::SetValEntry(std::string const &content,
223 uint16_t group, uint16_t elem)
225 return FileInternal->SetValEntry(content, group, elem);
230 * \brief Accesses an existing DocEntry (i.e. a Dicom Element)
231 * through it's (group, element) and modifies it's content with
233 * @param content new value (void* -> uint8_t*) to substitute with
234 * @param lgth new value length
235 * @param group group number of the Dicom Element to modify
236 * @param elem element number of the Dicom Element to modify
237 * \return false if DocEntry not found
239 bool FileHelper::SetBinEntry(uint8_t *content, int lgth,
240 uint16_t group, uint16_t elem)
242 return FileInternal->SetBinEntry(content, lgth, group, elem);
246 * \brief Modifies the value of a given DocEntry (Dicom entry)
247 * when it exists. Creates it with the given value when unexistant.
248 * @param content (string)value to be set
249 * @param group Group number of the Entry
250 * @param elem Element number of the Entry
251 * \return pointer to the modified/created Dicom entry (NULL when creation
254 ValEntry *FileHelper::InsertValEntry(std::string const &content,
255 uint16_t group, uint16_t elem)
257 return FileInternal->InsertValEntry(content, group, elem);
261 * \brief Modifies the value of a given DocEntry (Dicom entry)
262 * when it exists. Creates it with the given value when unexistant.
263 * A copy of the binArea is made to be kept in the Document.
264 * @param binArea (binary)value to be set
265 * @param lgth new value length
266 * @param group Group number of the Entry
267 * @param elem Element number of the Entry
268 * \return pointer to the modified/created Dicom entry (NULL when creation
271 BinEntry *FileHelper::InsertBinEntry(uint8_t *binArea, int lgth,
272 uint16_t group, uint16_t elem)
274 return FileInternal->InsertBinEntry(binArea, lgth, group, elem);
278 * \brief Modifies the value of a given DocEntry (Dicom entry)
279 * when it exists. Creates it, empty (?!) when unexistant.
280 * @param group Group number of the Entry
281 * @param elem Element number of the Entry
282 * \return pointer to the modified/created Dicom entry (NULL when creation
285 SeqEntry *FileHelper::InsertSeqEntry(uint16_t group, uint16_t elem)
287 return FileInternal->InsertSeqEntry(group, elem);
291 * \brief Get the size of the image data
292 * If the image can be RGB (with a lut or by default), the size
293 * corresponds to the RGB image
294 * (use GetImageDataRawSize if you want to be sure to get *only*
295 * the size of the pixels)
296 * @return The image size
298 size_t FileHelper::GetImageDataSize()
300 if ( PixelWriteConverter->GetUserData() )
302 return PixelWriteConverter->GetUserDataSize();
304 return PixelReadConverter->GetRGBSize();
308 * \brief Get the size of the image data
309 * If the image could be converted to RGB using a LUT,
310 * this transformation is not taken into account by GetImageDataRawSize
311 * (use GetImageDataSize if you wish)
312 * @return The raw image size
314 size_t FileHelper::GetImageDataRawSize()
316 if ( PixelWriteConverter->GetUserData() )
318 return PixelWriteConverter->GetUserDataSize();
320 return PixelReadConverter->GetRawSize();
324 * \brief - Allocates necessary memory,
325 * - Reads the pixels from disk (uncompress if necessary),
326 * - Transforms YBR pixels, if any, into RGB pixels,
327 * - Transforms 3 planes R, G, B, if any, into a single RGB Plane
328 * - Transforms single Grey plane + 3 Palettes into a RGB Plane
329 * - Copies the pixel data (image[s]/volume[s]) to newly allocated zone.
330 * @return Pointer to newly allocated pixel data.
331 * NULL if alloc fails
333 uint8_t *FileHelper::GetImageData()
335 if ( PixelWriteConverter->GetUserData() )
337 return PixelWriteConverter->GetUserData();
342 // If the decompression failed nothing can be done.
346 if ( FileInternal->HasLUT() && PixelReadConverter->BuildRGBImage() )
348 return PixelReadConverter->GetRGB();
352 // When no LUT or LUT conversion fails, return the Raw
353 return PixelReadConverter->GetRaw();
358 * \brief Allocates necessary memory,
359 * Transforms YBR pixels (if any) into RGB pixels
360 * Transforms 3 planes R, G, B (if any) into a single RGB Plane
361 * Copies the pixel data (image[s]/volume[s]) to newly allocated zone.
362 * DOES NOT transform Grey plane + 3 Palettes into a RGB Plane
363 * @return Pointer to newly allocated pixel data.
364 * NULL if alloc fails
366 uint8_t *FileHelper::GetImageDataRaw ()
373 * Read the pixels from disk (uncompress if necessary),
374 * Transforms YBR pixels, if any, into RGB pixels
375 * Transforms 3 planes R, G, B, if any, into a single RGB Plane
376 * Transforms single Grey plane + 3 Palettes into a RGB Plane
377 * Copies at most MaxSize bytes of pixel data to caller allocated
379 * \warning This function allows people that want to build a volume
380 * from an image stack *not to* have, first to get the image pixels,
381 * and then move them to the volume area.
382 * It's absolutely useless for any VTK user since vtk chooses
383 * to invert the lines of an image, that is the last line comes first
384 * (for some axis related reasons?). Hence he will have
385 * to load the image line by line, starting from the end.
386 * VTK users have to call GetImageData
388 * @param destination Address (in caller's memory space) at which the
389 * pixel data should be copied
390 * @param maxSize Maximum number of bytes to be copied. When MaxSize
391 * is not sufficient to hold the pixel data the copy is not
392 * executed (i.e. no partial copy).
393 * @return On success, the number of bytes actually copied. Zero on
394 * failure e.g. MaxSize is lower than necessary.
396 size_t FileHelper::GetImageDataIntoVector (void *destination, size_t maxSize)
400 // If the decompression failed nothing can be done.
404 if ( FileInternal->HasLUT() && PixelReadConverter->BuildRGBImage() )
406 if ( PixelReadConverter->GetRGBSize() > maxSize )
408 gdcmWarningMacro( "Pixel data bigger than caller's expected MaxSize");
412 (void*)PixelReadConverter->GetRGB(),
413 PixelReadConverter->GetRGBSize() );
414 return PixelReadConverter->GetRGBSize();
417 // Either no LUT conversion necessary or LUT conversion failed
418 if ( PixelReadConverter->GetRawSize() > maxSize )
420 gdcmWarningMacro( "Pixel data bigger than caller's expected MaxSize");
424 (void *)PixelReadConverter->GetRaw(),
425 PixelReadConverter->GetRawSize() );
426 return PixelReadConverter->GetRawSize();
430 * \brief Points the internal pointer to the callers inData
431 * image representation, BUT WITHOUT COPYING THE DATA.
432 * 'image' Pixels are presented as C-like 2D arrays : line per line.
433 * 'volume'Pixels are presented as C-like 3D arrays : plane per plane
434 * \warning Since the pixels are not copied, it is the caller's responsability
435 * not to deallocate its data before gdcm uses them (e.g. with
436 * the Write() method )
437 * @param inData user supplied pixel area (uint8_t* is just for the compiler.
438 * user is allowed to pass any kind of pixelsn since the size is
440 * @param expectedSize total image size, *in Bytes*
442 void FileHelper::SetImageData(uint8_t *inData, size_t expectedSize)
444 SetUserData(inData, expectedSize);
448 * \brief Set the image data defined by the user
449 * \warning When writting the file, this data are get as default data to write
450 * @param inData user supplied pixel area (uint8_t* is just for the compiler.
451 * user is allowed to pass any kind of pixels since the size is
453 * @param expectedSize total image size, *in Bytes*
455 void FileHelper::SetUserData(uint8_t *inData, size_t expectedSize)
457 PixelWriteConverter->SetUserData(inData, expectedSize);
461 * \brief Get the image data defined by the user
462 * \warning When writting the file, this data are get as default data to write
464 uint8_t *FileHelper::GetUserData()
466 return PixelWriteConverter->GetUserData();
470 * \brief Get the image data size defined by the user
471 * \warning When writting the file, this data are get as default data to write
473 size_t FileHelper::GetUserDataSize()
475 return PixelWriteConverter->GetUserDataSize();
479 * \brief Get the image data from the file.
480 * If a LUT is found, the data are expanded to be RGB
482 uint8_t *FileHelper::GetRGBData()
484 return PixelReadConverter->GetRGB();
488 * \brief Get the image data size from the file.
489 * If a LUT is found, the data are expanded to be RGB
491 size_t FileHelper::GetRGBDataSize()
493 return PixelReadConverter->GetRGBSize();
497 * \brief Get the image data from the file.
498 * Even when a LUT is found, the data are not expanded to RGB!
500 uint8_t *FileHelper::GetRawData()
502 return PixelReadConverter->GetRaw();
506 * \brief Get the image data size from the file.
507 * Even when a LUT is found, the data are not expanded to RGB!
509 size_t FileHelper::GetRawDataSize()
511 return PixelReadConverter->GetRawSize();
515 * \brief Access to the underlying \ref PixelReadConverter RGBA LUT
517 uint8_t* FileHelper::GetLutRGBA()
519 if ( PixelReadConverter->GetLutRGBA() ==0 )
520 PixelReadConverter->BuildLUTRGBA();
521 return PixelReadConverter->GetLutRGBA();
525 * \brief Access to the underlying \ref PixelReadConverter RGBA LUT Item Number
527 int FileHelper::GetLutItemNumber()
529 return PixelReadConverter->GetLutItemNumber();
533 * \brief Access to the underlying \ref PixelReadConverter RGBA LUT Item Size
535 int FileHelper::GetLutItemSize()
537 return PixelReadConverter->GetLutItemSize();
541 * \brief Writes on disk A SINGLE Dicom file
542 * NO test is performed on processor "Endiannity".
543 * It's up to the user to call his Reader properly
544 * @param fileName name of the file to be created
545 * (any already existing file is over written)
546 * @return false if write fails
548 bool FileHelper::WriteRawData(std::string const &fileName)
550 std::ofstream fp1(fileName.c_str(), std::ios::out | std::ios::binary );
553 gdcmWarningMacro( "Fail to open (write) file:" << fileName.c_str());
557 if ( PixelWriteConverter->GetUserData() )
559 fp1.write( (char *)PixelWriteConverter->GetUserData(),
560 PixelWriteConverter->GetUserDataSize() );
562 else if ( PixelReadConverter->GetRGB() )
564 fp1.write( (char *)PixelReadConverter->GetRGB(),
565 PixelReadConverter->GetRGBSize());
567 else if ( PixelReadConverter->GetRaw() )
569 fp1.write( (char *)PixelReadConverter->GetRaw(),
570 PixelReadConverter->GetRawSize());
574 gdcmErrorMacro( "Nothing written." );
583 * \brief Writes on disk A SINGLE Dicom file,
584 * using the Implicit Value Representation convention
585 * NO test is performed on processor "Endianity".
586 * @param fileName name of the file to be created
587 * (any already existing file is overwritten)
588 * @return false if write fails
591 bool FileHelper::WriteDcmImplVR (std::string const &fileName)
593 SetWriteTypeToDcmImplVR();
594 return Write(fileName);
598 * \brief Writes on disk A SINGLE Dicom file,
599 * using the Explicit Value Representation convention
600 * NO test is performed on processor "Endiannity".
601 * @param fileName name of the file to be created
602 * (any already existing file is overwritten)
603 * @return false if write fails
606 bool FileHelper::WriteDcmExplVR (std::string const &fileName)
608 SetWriteTypeToDcmExplVR();
609 return Write(fileName);
613 * \brief Writes on disk A SINGLE Dicom file,
614 * using the ACR-NEMA convention
615 * NO test is performed on processor "Endiannity".
616 * (a l'attention des logiciels cliniques
617 * qui ne prennent en entrée QUE des images ACR ...
618 * \warning if a DICOM_V3 header is supplied,
619 * groups < 0x0008 and shadow groups are ignored
620 * \warning NO TEST is performed on processor "Endiannity".
621 * @param fileName name of the file to be created
622 * (any already existing file is overwritten)
623 * @return false if write fails
626 bool FileHelper::WriteAcr (std::string const &fileName)
629 return Write(fileName);
633 * \brief Writes on disk A SINGLE Dicom file,
634 * @param fileName name of the file to be created
635 * (any already existing file is overwritten)
636 * @return false if write fails
638 bool FileHelper::Write(std::string const &fileName)
643 SetWriteFileTypeToImplicitVR();
645 case Unknown: // should never happen; ExplicitVR is the default value
647 SetWriteFileTypeToExplicitVR();
651 // NOTHING is done here just for LibIDO.
652 // Just to avoid further trouble if user creates a file ex-nihilo,
653 // wants to write it as an ACR-NEMA file,
654 // and forgets to create any Entry belonging to group 0008
656 // We add Recognition Code (RET)
657 if ( ! FileInternal->GetValEntry(0x0008, 0x0010) )
658 FileInternal->InsertValEntry("", 0x0008, 0x0010);
659 SetWriteFileTypeToACR();
660 // SetWriteFileTypeToImplicitVR(); // ACR IS implicit VR !
663 CheckMandatoryElements();
665 // --------------------------------------------------------------
666 // Special Patch to allow gdcm to re-write ACR-LibIDO formated images
668 // if recognition code tells us we dealt with a LibIDO image
669 // we reproduce on disk the switch between lineNumber and columnNumber
670 // just before writting ...
671 /// \todo the best trick would be *change* the recognition code
672 /// but pb expected if user deals with, e.g. COMPLEX images
674 if ( WriteType == ACR_LIBIDO )
680 SetWriteToNoLibido();
682 // ----------------- End of Special Patch ----------------
687 SetWriteToRaw(); // modifies and pushes to the archive, when necessary
690 SetWriteToRGB(); // modifies and pushes to the archive, when necessary
694 bool check = CheckWriteIntegrity(); // verifies length
697 check = FileInternal->Write(fileName,WriteType);
701 RestoreWriteFileType();
702 RestoreWriteMandatory();
704 // --------------------------------------------------------------
705 // Special Patch to allow gdcm to re-write ACR-LibIDO formated images
707 // ...and we restore the header to be Dicom Compliant again
708 // just after writting
709 RestoreWriteOfLibido();
710 // ----------------- End of Special Patch ----------------
715 //-----------------------------------------------------------------------------
718 * \brief Checks the write integrity
720 * The tests made are :
721 * - verify the size of the image to write with the possible write
722 * when the user set an image data
723 * @return true if check is successfull
725 bool FileHelper::CheckWriteIntegrity()
727 if ( PixelWriteConverter->GetUserData() )
729 int numberBitsAllocated = FileInternal->GetBitsAllocated();
730 if ( numberBitsAllocated == 0 || numberBitsAllocated == 12 )
732 gdcmWarningMacro( "numberBitsAllocated changed from "
733 << numberBitsAllocated << " to 16 "
734 << " for consistency purpose" );
735 numberBitsAllocated = 16;
738 size_t decSize = FileInternal->GetXSize()
739 * FileInternal->GetYSize()
740 * FileInternal->GetZSize()
741 * FileInternal->GetSamplesPerPixel()
742 * ( numberBitsAllocated / 8 );
743 size_t rgbSize = decSize;
744 if ( FileInternal->HasLUT() )
745 rgbSize = decSize * 3;
750 if ( decSize!=PixelWriteConverter->GetUserDataSize() )
752 gdcmWarningMacro( "Data size (Raw) is incorrect. Should be "
753 << decSize << " / Found :"
754 << PixelWriteConverter->GetUserDataSize() );
759 if ( rgbSize!=PixelWriteConverter->GetUserDataSize() )
761 gdcmWarningMacro( "Data size (RGB) is incorrect. Should be "
762 << decSize << " / Found "
763 << PixelWriteConverter->GetUserDataSize() );
773 * \brief Updates the File to write RAW data (as opposed to RGB data)
774 * (modifies, when necessary, photochromatic interpretation,
775 * bits allocated, Pixels element VR)
777 void FileHelper::SetWriteToRaw()
779 if ( FileInternal->GetNumberOfScalarComponents() == 3
780 && !FileInternal->HasLUT() )
786 ValEntry *photInt = CopyValEntry(0x0028,0x0004);
787 if (FileInternal->HasLUT() )
789 photInt->SetValue("PALETTE COLOR ");
793 photInt->SetValue("MONOCHROME2 ");
796 PixelWriteConverter->SetReadData(PixelReadConverter->GetRaw(),
797 PixelReadConverter->GetRawSize());
799 std::string vr = "OB";
800 if ( FileInternal->GetBitsAllocated()>8 )
802 if ( FileInternal->GetBitsAllocated()==24 ) // For RGB ACR files
805 CopyBinEntry(GetFile()->GetGrPixel(),GetFile()->GetNumPixel(),vr);
806 pixel->SetValue(GDCM_BINLOADED);
807 pixel->SetBinArea(PixelWriteConverter->GetData(),false);
808 pixel->SetLength(PixelWriteConverter->GetDataSize());
810 Archive->Push(photInt);
811 Archive->Push(pixel);
816 * \brief Updates the File to write RGB data (as opposed to RAW data)
817 * (modifies, when necessary, photochromatic interpretation,
818 * samples per pixel, Planar configuration,
819 * bits allocated, bits stored, high bit -ACR 24 bits-
820 * Pixels element VR, pushes out the LUT, )
822 void FileHelper::SetWriteToRGB()
824 if ( FileInternal->GetNumberOfScalarComponents()==3 )
826 PixelReadConverter->BuildRGBImage();
828 ValEntry *spp = CopyValEntry(0x0028,0x0002);
831 ValEntry *planConfig = CopyValEntry(0x0028,0x0006);
832 planConfig->SetValue("0 ");
834 ValEntry *photInt = CopyValEntry(0x0028,0x0004);
835 photInt->SetValue("RGB ");
837 if ( PixelReadConverter->GetRGB() )
839 PixelWriteConverter->SetReadData(PixelReadConverter->GetRGB(),
840 PixelReadConverter->GetRGBSize());
844 PixelWriteConverter->SetReadData(PixelReadConverter->GetRaw(),
845 PixelReadConverter->GetRawSize());
848 std::string vr = "OB";
849 if ( FileInternal->GetBitsAllocated()>8 )
851 if ( FileInternal->GetBitsAllocated()==24 ) // For RGB ACR files
854 CopyBinEntry(GetFile()->GetGrPixel(),GetFile()->GetNumPixel(),vr);
855 pixel->SetValue(GDCM_BINLOADED);
856 pixel->SetBinArea(PixelWriteConverter->GetData(),false);
857 pixel->SetLength(PixelWriteConverter->GetDataSize());
860 Archive->Push(planConfig);
861 Archive->Push(photInt);
862 Archive->Push(pixel);
865 Archive->Push(0x0028,0x1101);
866 Archive->Push(0x0028,0x1102);
867 Archive->Push(0x0028,0x1103);
868 Archive->Push(0x0028,0x1201);
869 Archive->Push(0x0028,0x1202);
870 Archive->Push(0x0028,0x1203);
872 // push out Palette Color Lookup Table UID, if any
873 Archive->Push(0x0028,0x1199);
875 // For old '24 Bits' ACR-NEMA
876 // Thus, we have a RGB image and the bits allocated = 24 and
877 // samples per pixels = 1 (in the read file)
878 if ( FileInternal->GetBitsAllocated()==24 )
880 ValEntry *bitsAlloc = CopyValEntry(0x0028,0x0100);
881 bitsAlloc->SetValue("8 ");
883 ValEntry *bitsStored = CopyValEntry(0x0028,0x0101);
884 bitsStored->SetValue("8 ");
886 ValEntry *highBit = CopyValEntry(0x0028,0x0102);
887 highBit->SetValue("7 ");
889 Archive->Push(bitsAlloc);
890 Archive->Push(bitsStored);
891 Archive->Push(highBit);
901 * \brief Restore the File write mode
903 void FileHelper::RestoreWrite()
905 Archive->Restore(0x0028,0x0002);
906 Archive->Restore(0x0028,0x0004);
907 Archive->Restore(0x0028,0x0006);
908 Archive->Restore(GetFile()->GetGrPixel(),GetFile()->GetNumPixel());
910 // For old ACR-NEMA (24 bits problem)
911 Archive->Restore(0x0028,0x0100);
912 Archive->Restore(0x0028,0x0101);
913 Archive->Restore(0x0028,0x0102);
916 Archive->Restore(0x0028,0x1101);
917 Archive->Restore(0x0028,0x1102);
918 Archive->Restore(0x0028,0x1103);
919 Archive->Restore(0x0028,0x1201);
920 Archive->Restore(0x0028,0x1202);
921 Archive->Restore(0x0028,0x1203);
923 // For the Palette Color Lookup Table UID
924 Archive->Restore(0x0028,0x1203);
927 // group 0002 may be pushed out for ACR-NEMA writting purposes
928 Archive->Restore(0x0002,0x0000);
929 Archive->Restore(0x0002,0x0001);
930 Archive->Restore(0x0002,0x0002);
931 Archive->Restore(0x0002,0x0003);
932 Archive->Restore(0x0002,0x0010);
933 Archive->Restore(0x0002,0x0012);
934 Archive->Restore(0x0002,0x0013);
935 Archive->Restore(0x0002,0x0016);
936 Archive->Restore(0x0002,0x0100);
937 Archive->Restore(0x0002,0x0102);
941 * \brief Pushes out the whole group 0002
942 * FIXME : better, set a flag to tell the writer not to write it ...
943 * FIXME : method should probably have an other name !
944 * SetWriteFileTypeToACR is NOT opposed to
945 * SetWriteFileTypeToExplicitVR and SetWriteFileTypeToImplicitVR
947 void FileHelper::SetWriteFileTypeToACR()
949 Archive->Push(0x0002,0x0000);
950 Archive->Push(0x0002,0x0001);
951 Archive->Push(0x0002,0x0002);
952 Archive->Push(0x0002,0x0003);
953 Archive->Push(0x0002,0x0010);
954 Archive->Push(0x0002,0x0012);
955 Archive->Push(0x0002,0x0013);
956 Archive->Push(0x0002,0x0016);
957 Archive->Push(0x0002,0x0100);
958 Archive->Push(0x0002,0x0102);
962 * \brief Sets in the File the TransferSyntax to 'Explicit VR Little Endian"
964 void FileHelper::SetWriteFileTypeToExplicitVR()
966 std::string ts = Util::DicomString(
967 Global::GetTS()->GetSpecialTransferSyntax(TS::ExplicitVRLittleEndian) );
969 ValEntry *tss = CopyValEntry(0x0002,0x0010);
976 * \brief Sets in the File the TransferSyntax to 'Implicit VR Little Endian"
978 void FileHelper::SetWriteFileTypeToImplicitVR()
980 std::string ts = Util::DicomString(
981 Global::GetTS()->GetSpecialTransferSyntax(TS::ImplicitVRLittleEndian) );
983 ValEntry *tss = CopyValEntry(0x0002,0x0010);
991 * \brief Restore in the File the initial group 0002
993 void FileHelper::RestoreWriteFileType()
998 * \brief Set the Write not to Libido format
1000 void FileHelper::SetWriteToLibido()
1002 ValEntry *oldRow = dynamic_cast<ValEntry *>
1003 (FileInternal->GetDocEntry(0x0028, 0x0010));
1004 ValEntry *oldCol = dynamic_cast<ValEntry *>
1005 (FileInternal->GetDocEntry(0x0028, 0x0011));
1007 if ( oldRow && oldCol )
1009 std::string rows, columns;
1011 ValEntry *newRow=new ValEntry(oldRow->GetDictEntry());
1012 ValEntry *newCol=new ValEntry(oldCol->GetDictEntry());
1014 newRow->Copy(oldCol);
1015 newCol->Copy(oldRow);
1017 newRow->SetValue(oldCol->GetValue());
1018 newCol->SetValue(oldRow->GetValue());
1020 Archive->Push(newRow);
1021 Archive->Push(newCol);
1024 ValEntry *libidoCode = CopyValEntry(0x0008,0x0010);
1025 libidoCode->SetValue("ACRNEMA_LIBIDO_1.1");
1026 Archive->Push(libidoCode);
1030 * \brief Set the Write not to No Libido format
1032 void FileHelper::SetWriteToNoLibido()
1034 ValEntry *recCode = dynamic_cast<ValEntry *>
1035 (FileInternal->GetDocEntry(0x0008,0x0010));
1038 if ( recCode->GetValue() == "ACRNEMA_LIBIDO_1.1" )
1040 ValEntry *libidoCode = CopyValEntry(0x0008,0x0010);
1041 libidoCode->SetValue("");
1042 Archive->Push(libidoCode);
1048 * \brief Restore the Write format
1050 void FileHelper::RestoreWriteOfLibido()
1052 Archive->Restore(0x0028,0x0010);
1053 Archive->Restore(0x0028,0x0011);
1054 Archive->Restore(0x0008,0x0010);
1056 // Restore 'LibIDO-special' entries, if any
1057 Archive->Restore(0x0028,0x0015);
1058 Archive->Restore(0x0028,0x0016);
1059 Archive->Restore(0x0028,0x0017);
1060 Archive->Restore(0x0028,0x00199);
1064 * \brief Duplicates a ValEntry or creates it.
1065 * @param group Group number of the Entry
1066 * @param elem Element number of the Entry
1067 * \return pointer to the new Val Entry (NULL when creation failed).
1069 ValEntry *FileHelper::CopyValEntry(uint16_t group, uint16_t elem)
1071 DocEntry *oldE = FileInternal->GetDocEntry(group, elem);
1076 newE = new ValEntry(oldE->GetDictEntry());
1081 newE = GetFile()->NewValEntry(group, elem);
1088 * \brief Duplicates a BinEntry or creates it.
1089 * @param group Group number of the Entry
1090 * @param elem Element number of the Entry
1091 * @param vr Value Representation of the Entry
1092 * FIXME : what is it used for?
1093 * \return pointer to the new Bin Entry (NULL when creation failed).
1095 BinEntry *FileHelper::CopyBinEntry(uint16_t group, uint16_t elem,
1096 const std::string &vr)
1098 DocEntry *oldE = FileInternal->GetDocEntry(group, elem);
1102 if ( oldE->GetVR()!=vr )
1107 newE = new BinEntry(oldE->GetDictEntry());
1112 newE = GetFile()->NewBinEntry(group, elem, vr);
1119 * \brief This method is called automatically, just before writting
1120 * in order to produce a 'True Dicom V3' image
1121 * We cannot know *how* the user made the File (reading an old ACR-NEMA
1122 * file or a not very clean DICOM file ...)
1124 * Just before writting :
1125 * - we check the Entries
1126 * - we create the mandatory entries if they are missing
1127 * - we modify the values if necessary
1128 * - we push the sensitive entries to the Archive
1129 * The writing process will restore the entries as they where before
1130 * entering FileHelper::CheckMandatoryElements, so the user will always
1131 * see the entries just as he left them.
1133 * \todo : - warn the user if we had to add some entries :
1134 * even if a mandatory entry is missing, we add it, with a default value
1135 * (we don't want to give up the writting process if user forgot to
1136 * specify Lena's Patient ID, for instance ...)
1137 * - read the whole PS 3.3 Part of DICOM (890 pages)
1138 * and write a *full* checker (probably one method per Modality ...)
1139 * Any contribution is welcome.
1140 * - write a user callable full checker, to allow post reading
1141 * and/or pre writting image consistency check.
1144 void FileHelper::CheckMandatoryElements()
1146 // just to remember : 'official' 0002 group
1147 if ( WriteType != ACR && WriteType != ACR_LIBIDO )
1149 // Group 000002 (Meta Elements) already pushed out
1151 //0002 0000 UL 1 Meta Group Length
1152 //0002 0001 OB 1 File Meta Information Version
1153 //0002 0002 UI 1 Media Stored SOP Class UID
1154 //0002 0003 UI 1 Media Stored SOP Instance UID
1155 //0002 0010 UI 1 Transfer Syntax UID
1156 //0002 0012 UI 1 Implementation Class UID
1157 //0002 0013 SH 1 Implementation Version Name
1158 //0002 0016 AE 1 Source Application Entity Title
1159 //0002 0100 UI 1 Private Information Creator
1160 //0002 0102 OB 1 Private Information
1162 // Create them if not found
1163 // Always modify the value
1164 // Push the entries to the archive.
1165 ValEntry *e_0002_0000 = CopyValEntry(0x0002,0x0000);
1166 e_0002_0000->SetValue("0"); // for the moment
1167 Archive->Push(e_0002_0000);
1169 BinEntry *e_0002_0001 = CopyBinEntry(0x0002,0x0001, "OB");
1170 e_0002_0001->SetBinArea((uint8_t*)Util::GetFileMetaInformationVersion(),
1172 e_0002_0001->SetLength(2);
1173 Archive->Push(e_0002_0001);
1175 // 'Media Stored SOP Class UID'
1176 ValEntry *e_0002_0002 = CopyValEntry(0x0002,0x0002);
1177 // [Secondary Capture Image Storage]
1178 e_0002_0002->SetValue("1.2.840.10008.5.1.4.1.1.7");
1179 Archive->Push(e_0002_0002);
1181 // 'Media Stored SOP Instance UID'
1182 ValEntry *e_0002_0003 = CopyValEntry(0x0002,0x0003);
1183 e_0002_0003->SetValue(Util::CreateUniqueUID());
1184 Archive->Push(e_0002_0003);
1186 // 'Implementation Class UID'
1187 ValEntry *e_0002_0012 = CopyValEntry(0x0002,0x0012);
1188 e_0002_0012->SetValue(Util::CreateUniqueUID());
1189 Archive->Push(e_0002_0012);
1191 // 'Implementation Version Name'
1192 ValEntry *e_0002_0013 = CopyValEntry(0x0002,0x0013);
1193 e_0002_0013->SetValue("GDCM 1.1");
1194 Archive->Push(e_0002_0013);
1196 //'Source Application Entity Title' Not Mandatory
1197 //ValEntry *e_0002_0016 = CopyValEntry(0x0002,0x0016);
1198 // e_0002_0016->SetValue("1.2.840.10008.5.1.4.1.1.7");
1199 // Archive->Push(e_0002_0016);
1202 // Push out 'LibIDO-special' entries, if any
1203 Archive->Push(0x0028,0x0015);
1204 Archive->Push(0x0028,0x0016);
1205 Archive->Push(0x0028,0x0017);
1206 Archive->Push(0x0028,0x00199);
1208 // Deal with the pb of (Bits Stored = 12)
1209 // - we're gonna write the image as Bits Stored = 16
1210 if ( FileInternal->GetEntryValue(0x0028,0x0100) == "12")
1212 ValEntry *e_0028_0100 = CopyValEntry(0x0028,0x0100);
1213 e_0028_0100->SetValue("16");
1214 Archive->Push(e_0028_0100);
1217 // Check if user wasn't drunk ;-)
1219 std::ostringstream s;
1220 // check 'Bits Allocated' vs decent values
1221 int nbBitsAllocated = FileInternal->GetBitsAllocated();
1222 if ( nbBitsAllocated == 0 || nbBitsAllocated > 32)
1224 ValEntry *e_0028_0100 = CopyValEntry(0x0028,0x0100);
1225 e_0028_0100->SetValue("16");
1226 Archive->Push(e_0028_0100);
1227 gdcmWarningMacro("(0028,0100) changed from "
1228 << nbBitsAllocated << " to 16 for consistency purpose");
1229 nbBitsAllocated = 16;
1231 // check 'Bits Stored' vs 'Bits Allocated'
1232 int nbBitsStored = FileInternal->GetBitsStored();
1233 if ( nbBitsStored == 0 || nbBitsStored > nbBitsAllocated )
1235 s << nbBitsAllocated;
1236 ValEntry *e_0028_0101 = CopyValEntry(0x0028,0x0101);
1237 e_0028_0101->SetValue( s.str() );
1238 Archive->Push(e_0028_0101);
1239 gdcmWarningMacro("(0028,0101) changed from "
1240 << nbBitsStored << " to " << nbBitsAllocated
1241 << " for consistency purpose" );
1242 nbBitsStored = nbBitsAllocated;
1244 // check 'Hight Bit Position' vs 'Bits Allocated' and 'Bits Stored'
1245 int highBitPosition = FileInternal->GetHighBitPosition();
1246 if ( highBitPosition == 0 ||
1247 highBitPosition > nbBitsAllocated-1 ||
1248 highBitPosition < nbBitsStored-1 )
1250 ValEntry *e_0028_0102 = CopyValEntry(0x0028,0x0102);
1252 s << nbBitsStored - 1;
1253 e_0028_0102->SetValue( s.str() );
1254 Archive->Push(e_0028_0102);
1255 gdcmWarningMacro("(0028,0102) changed from "
1256 << highBitPosition << " to " << nbBitsAllocated-1
1257 << " for consistency purpose");
1259 // --- Check UID-related Entries ---
1261 // If 'SOP Class UID' exists ('true DICOM' image)
1262 // we create the 'Source Image Sequence' SeqEntry
1263 // to hold informations about the Source Image
1265 ValEntry *e_0008_0016 = FileInternal->GetValEntry(0x0008, 0x0016);
1266 if ( e_0008_0016 != 0 )
1268 // Create 'Source Image Sequence' SeqEntry
1269 SeqEntry *sis = new SeqEntry (
1270 Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x2112) );
1271 SQItem *sqi = new SQItem(1);
1272 // (we assume 'SOP Instance UID' exists too)
1273 // create 'Referenced SOP Class UID'
1274 ValEntry *e_0008_1150 = new ValEntry(
1275 Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x1150) );
1276 e_0008_1150->SetValue( e_0008_0016->GetValue());
1277 sqi->AddEntry(e_0008_1150);
1279 // create 'Referenced SOP Instance UID'
1280 ValEntry *e_0008_0018 = FileInternal->GetValEntry(0x0008, 0x0018);
1281 ValEntry *e_0008_1155 = new ValEntry(
1282 Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x1155) );
1283 e_0008_1155->SetValue( e_0008_0018->GetValue());
1284 sqi->AddEntry(e_0008_1155);
1286 sis->AddSQItem(sqi,1);
1287 // temporarily replaces any previous 'Source Image Sequence'
1290 // 'Image Type' (The written image is no longer an 'ORIGINAL' one)
1291 ValEntry *e_0008_0008 = CopyValEntry(0x0008,0x0008);
1292 e_0008_0008->SetValue("DERIVED\\PRIMARY");
1293 Archive->Push(e_0008_0008);
1297 // There was no 'SOP Class UID'.
1298 // the source image was NOT a true Dicom one.
1299 // We consider the image is a 'Secondary Capture' one
1301 e_0008_0016 = new ValEntry(
1302 Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x0016) );
1303 // [Secondary Capture Image Storage]
1304 e_0008_0016 ->SetValue("1.2.840.10008.5.1.4.1.1.7");
1305 Archive->Push(e_0008_0016);
1308 // ---- The user will never have to take any action on the following ----.
1310 // new value for 'SOP Instance UID'
1311 ValEntry *e_0008_0018 = new ValEntry(
1312 Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x0018) );
1313 e_0008_0018->SetValue( Util::CreateUniqueUID() );
1314 Archive->Push(e_0008_0018);
1316 // Instance Creation Date
1317 ValEntry *e_0008_0012 = CopyValEntry(0x0008,0x0012);
1318 std::string date = Util::GetCurrentDate();
1319 e_0008_0012->SetValue(date.c_str());
1320 Archive->Push(e_0008_0012);
1322 // Instance Creation Time
1323 ValEntry *e_0008_0013 = CopyValEntry(0x0008,0x0013);
1324 std::string time = Util::GetCurrentTime();
1325 e_0008_0013->SetValue(time.c_str());
1326 Archive->Push(e_0008_0013);
1328 // ----- Add Mandatory Entries if missing ---
1330 // Entries whose type is 1 are mandatory, with a mandatory value
1331 // Entries whose type is 1c are mandatory-inside-a-Sequence
1332 // Entries whose type is 2 are mandatory, with a optional value
1333 // Entries whose type is 2c are mandatory-inside-a-Sequence
1334 // Entries whose type is 3 are optional
1336 // 'Serie Instance UID'
1337 // Keep the value if exists
1338 // The user is allowed to create his own Series,
1339 // keeping the same 'Serie Instance UID' for various images
1340 // The user shouldn't add any image to a 'Manufacturer Serie'
1341 // but there is no way no to allowed him to do that
1342 ValEntry *e_0020_000e = FileInternal->GetValEntry(0x0020, 0x000e);
1345 e_0020_000e = new ValEntry(
1346 Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0020, 0x000e) );
1347 e_0020_000e->SetValue(Util::CreateUniqueUID() );
1348 Archive->Push(e_0020_000e);
1351 // 'Study Instance UID'
1352 // Keep the value if exists
1353 // The user is allowed to create his own Study,
1354 // keeping the same 'Study Instance UID' for various images
1355 // The user may add images to a 'Manufacturer Study',
1356 // adding new series to an already existing Study
1357 ValEntry *e_0020_000d = FileInternal->GetValEntry(0x0020, 0x000d);
1360 e_0020_000d = new ValEntry(
1361 Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0020, 0x000d) );
1362 e_0020_000d->SetValue(Util::CreateUniqueUID() );
1363 Archive->Push(e_0020_000d);
1366 // Modality : if missing we set it to 'OTher'
1367 ValEntry *e_0008_0060 = FileInternal->GetValEntry(0x0008, 0x0060);
1370 e_0008_0060 = new ValEntry(
1371 Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x0060) );
1372 e_0008_0060->SetValue("OT");
1373 Archive->Push(e_0008_0060);
1376 // Manufacturer : if missing we set it to 'GDCM Factory'
1377 ValEntry *e_0008_0070 = FileInternal->GetValEntry(0x0008, 0x0070);
1380 e_0008_0070 = new ValEntry(
1381 Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x0070) );
1382 e_0008_0070->SetValue("GDCM Factory");
1383 Archive->Push(e_0008_0070);
1386 // Institution Name : if missing we set it to 'GDCM Hospital'
1387 ValEntry *e_0008_0080 = FileInternal->GetValEntry(0x0008, 0x0080);
1390 e_0008_0080 = new ValEntry(
1391 Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x0080) );
1392 e_0008_0080->SetValue("GDCM Hospital");
1393 Archive->Push(e_0008_0080);
1396 // Patient's Name : if missing, we set it to 'GDCM^Patient'
1397 ValEntry *e_0010_0010 = FileInternal->GetValEntry(0x0010, 0x0010);
1400 e_0010_0010 = new ValEntry(
1401 Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0010, 0x0010) );
1402 e_0010_0010->SetValue("GDCM^Patient");
1403 Archive->Push(e_0010_0010);
1406 // Patient's Birth Date : 'type 2' entry -> must exist, value not mandatory
1407 ValEntry *e_0010_0030 = FileInternal->GetValEntry(0x0010, 0x0030);
1410 e_0010_0030 = new ValEntry(
1411 Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0010, 0x0030) );
1412 e_0010_0030->SetValue("");
1413 Archive->Push(e_0010_0030);
1416 // Patient's Sex :'type 2' entry -> must exist, value not mandatory
1417 ValEntry *e_0010_0040 = FileInternal->GetValEntry(0x0010, 0x0040);
1420 e_0010_0040 = new ValEntry(
1421 Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0010, 0x0040) );
1422 e_0010_0040->SetValue("");
1423 Archive->Push(e_0010_0040);
1426 // Referring Physician's Name :'type 2' entry -> must exist, value not mandatory
1427 ValEntry *e_0008_0090 = FileInternal->GetValEntry(0x0008, 0x0090);
1430 e_0008_0090 = new ValEntry(
1431 Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x0090) );
1432 e_0008_0090->SetValue("");
1433 Archive->Push(e_0008_0090);
1436 // Remove some inconstencies (probably some more will be added)
1438 // if (0028 0008)Number of Frames exists
1439 // Push out (0020 0052),Frame of Reference UID
1440 // (only meaningfull within a Serie)
1441 ValEntry *e_0028_0008 = FileInternal->GetValEntry(0x0028, 0x0008);
1444 Archive->Push(0x0020, 0X0052);
1449 * \brief Restore in the File the initial group 0002
1451 void FileHelper::RestoreWriteMandatory()
1453 // group 0002 may be pushed out for ACR-NEMA writting purposes
1454 Archive->Restore(0x0002,0x0000);
1455 Archive->Restore(0x0002,0x0001);
1456 Archive->Restore(0x0002,0x0002);
1457 Archive->Restore(0x0002,0x0003);
1458 Archive->Restore(0x0002,0x0010);
1459 Archive->Restore(0x0002,0x0012);
1460 Archive->Restore(0x0002,0x0013);
1461 Archive->Restore(0x0002,0x0016);
1462 Archive->Restore(0x0002,0x0100);
1463 Archive->Restore(0x0002,0x0102);
1465 Archive->Restore(0x0008,0x0012);
1466 Archive->Restore(0x0008,0x0013);
1467 Archive->Restore(0x0008,0x0016);
1468 Archive->Restore(0x0008,0x0018);
1469 Archive->Restore(0x0008,0x0060);
1470 Archive->Restore(0x0008,0x0070);
1471 Archive->Restore(0x0008,0x0080);
1472 Archive->Restore(0x0008,0x0090);
1473 Archive->Restore(0x0008,0x2112);
1475 Archive->Restore(0x0010,0x0010);
1476 Archive->Restore(0x0010,0x0030);
1477 Archive->Restore(0x0010,0x0040);
1479 Archive->Restore(0x0020,0x000d);
1480 Archive->Restore(0x0020,0x000e);
1484 //-----------------------------------------------------------------------------
1487 * \brief Factorization for various forms of constructors.
1489 void FileHelper::Initialize()
1491 WriteMode = WMODE_RAW;
1492 WriteType = ExplicitVR;
1494 PixelReadConverter = new PixelReadConvert;
1495 PixelWriteConverter = new PixelWriteConvert;
1496 Archive = new DocEntryArchive( FileInternal );
1498 if ( FileInternal->IsReadable() )
1500 PixelReadConverter->GrabInformationsFromFile( FileInternal );
1505 * \brief Reads/[decompresses] the pixels,
1506 * *without* making RGB from Palette Colors
1507 * @return the pixels area, whatever its type
1508 * (uint8_t is just for prototyping : feel free to Cast it)
1510 uint8_t *FileHelper::GetRaw()
1512 PixelReadConverter->SetUserFunction( UserFunction );
1514 uint8_t *raw = PixelReadConverter->GetRaw();
1517 // The Raw image migth not be loaded yet:
1518 std::ifstream *fp = FileInternal->OpenFile();
1519 PixelReadConverter->ReadAndDecompressPixelData( fp );
1521 FileInternal->CloseFile();
1523 raw = PixelReadConverter->GetRaw();
1526 gdcmWarningMacro( "Read/decompress of pixel data apparently went wrong.");
1533 //-----------------------------------------------------------------------------
1535 * \brief Prints the common part of ValEntry, BinEntry, SeqEntry
1536 * @param os ostream we want to print in
1537 * @param indent (unused)
1539 void FileHelper::Print(std::ostream &os, std::string const &)
1541 FileInternal->SetPrintLevel(PrintLevel);
1542 FileInternal->Print(os);
1544 PixelReadConverter->SetPrintLevel(PrintLevel);
1545 PixelReadConverter->Print(os);
1548 #ifndef GDCM_LEGACY_REMOVE
1551 * Constructor dedicated to deal with the *pixels* area of a ACR/DICOMV3
1552 * file (gdcm::File only deals with the ... header)
1553 * Opens (in read only and when possible) an existing file and checks
1554 * for DICOM compliance. Returns NULL on failure.
1555 * It will be up to the user to load the pixels into memory
1556 * \note the in-memory representation of all available tags found in
1557 * the DICOM header is post-poned to first header information access.
1558 * This avoid a double parsing of public part of the header when
1559 * one sets an a posteriori shadow dictionary (efficiency can be
1560 * seen as a side effect).
1561 * @param filename file to be opened for parsing
1562 * @deprecated use SetFilename() + Load() methods
1564 FileHelper::FileHelper(std::string const &filename )
1566 FileInternal = new File( );
1567 FileInternal->SetFileName( filename );
1568 FileInternal->Load();
1573 //-----------------------------------------------------------------------------
1574 } // end namespace gdcm