From e28b183ba68aa3cc84a44a779a31f9d906a1ad2f Mon Sep 17 00:00:00 2001 From: frog Date: Mon, 18 Oct 2004 12:49:19 +0000 Subject: [PATCH] 2004-10-18 Eric Boix * Doc/CMakeLists.txt, doxygen.config.in: when dot is present the collaboration diagram and inheritance diagram should be generated with doxygen. * Doc/Website/Sidebar.html: Dashboard is now also in the sidebar. * gdcmPython/gdcm.i: gdcmRLEFramesInfo.h gdcmJPEGFragmentsInfo.h are pointlessly wrapped (see http://www.creatis.insa-lyon.fr/pipermail/dcmlib/2004-October/000692.html ) * CLEANUP_ROUND (12) for gdcmPixelConvert (sugar is my friend stage) - Header::GetLUTRGBA() moved to PixelConvert::GetLutRGBA() - vtk/vtkGdcmReader.cxx: adapted to displacment of Header::GetLUTRGBA() - Document::RLEInfo and JPEGInfo are now pointer members (Swig thing) - src/gdcmFile.[cxx|h] and gdcmPixelConvert.[cxx|h]: -- File::Initialise: PixelConverter setup moved away to PixelConverter::GrabInformationsFromHeader() -- File::GetImageDataIntoVector(): Lut R + Lut G + Lut B color table interpretation moved away to PixelConverter::BuildRGBImage() --- ChangeLog | 18 ++ Doc/CMakeLists.txt | 8 + Doc/Website/Sidebar.html | 5 + Doc/doxygen.config.in | 4 +- gdcmPython/gdcm.i | 28 +-- src/gdcmBinEntry.h | 19 +- src/gdcmDocument.cxx | 17 +- src/gdcmDocument.h | 24 +-- src/gdcmFile.cxx | 123 +++--------- src/gdcmFile.h | 6 +- src/gdcmHeader.cxx | 167 +---------------- src/gdcmHeader.h | 5 +- src/gdcmJPEGFragmentsInfo.h | 7 +- src/gdcmPixelConvert.cxx | 364 +++++++++++++++++++++++++++++++++--- src/gdcmPixelConvert.h | 149 +++++++-------- src/gdcmRLEFrame.h | 5 +- vtk/vtkGdcmReader.cxx | 4 +- 17 files changed, 528 insertions(+), 425 deletions(-) diff --git a/ChangeLog b/ChangeLog index f3ead76c..4e6982ee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2004-10-18 Eric Boix + * Doc/CMakeLists.txt, doxygen.config.in: when dot is present the + collaboration diagram and inheritance diagram should be generated with + doxygen. + * Doc/Website/Sidebar.html: Dashboard is now also in the sidebar. + * gdcmPython/gdcm.i: gdcmRLEFramesInfo.h gdcmJPEGFragmentsInfo.h are + pointlessly wrapped (see + http://www.creatis.insa-lyon.fr/pipermail/dcmlib/2004-October/000692.html ) + * CLEANUP_ROUND (12) for gdcmPixelConvert (sugar is my friend stage) + - Header::GetLUTRGBA() moved to PixelConvert::GetLutRGBA() + - vtk/vtkGdcmReader.cxx: adapted to displacment of Header::GetLUTRGBA() + - Document::RLEInfo and JPEGInfo are now pointer members (Swig thing) + - src/gdcmFile.[cxx|h] and gdcmPixelConvert.[cxx|h]: + -- File::Initialise: PixelConverter setup moved away to + PixelConverter::GrabInformationsFromHeader() + -- File::GetImageDataIntoVector(): Lut R + Lut G + Lut B color table + interpretation moved away to PixelConverter::BuildRGBImage() + 2004-10-16 Mathieu Malaterre * Remove GDCM_EXPORT keyword from gdcm::DirList due to : http://support.microsoft.com/support/kb/articles/Q168/9/58.ASP diff --git a/Doc/CMakeLists.txt b/Doc/CMakeLists.txt index 6102dc84..2c0d73af 100644 --- a/Doc/CMakeLists.txt +++ b/Doc/CMakeLists.txt @@ -31,6 +31,14 @@ IF(GDCM_DOCUMENTATION) "${GDCM_DOCUMENTATION_INPUT_COMMON} ${GDCM_SOURCE_DIR}/vtk") ENDIF(GDCM_VTK) + IF(DOT) + GET_FILENAME_COMPONENT(GDCM_DOCUMENTATION_DOT_PATH ${DOT} PATH) + SET(GDCM_DOCUMENTATION_HAVE_DOT "YES") + ELSE(DOT) + SET(GDCM_DOCUMENTATION_DOT_PATH "") + SET(GDCM_DOCUMENTATION_HAVE_DOT "NO") + ENDIF(DOT) + #Should rewrote this thing with FOREACH: #----------------------------------------------------------------------------- # Build the documentation for developpers diff --git a/Doc/Website/Sidebar.html b/Doc/Website/Sidebar.html index 9e502b3c..3e455ddb 100644 --- a/Doc/Website/Sidebar.html +++ b/Doc/Website/Sidebar.html @@ -122,6 +122,11 @@ Online browsing of sources + + + DashBoard + diff --git a/Doc/doxygen.config.in b/Doc/doxygen.config.in index 4783a68a..ddb51f19 100644 --- a/Doc/doxygen.config.in +++ b/Doc/doxygen.config.in @@ -785,7 +785,7 @@ CLASS_DIAGRAMS = YES # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) -HAVE_DOT = NO +HAVE_DOT = @GDCM_DOCUMENTATION_HAVE_DOT@ # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and @@ -840,7 +840,7 @@ DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found on the path. -DOT_PATH = +DOT_PATH = @GDCM_DOCUMENTATION_DOT_PATH@ # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the diff --git a/gdcmPython/gdcm.i b/gdcmPython/gdcm.i index 27a7b02a..b4d93b1a 100644 --- a/gdcmPython/gdcm.i +++ b/gdcmPython/gdcm.i @@ -1,26 +1,28 @@ %module gdcm %{ #include "gdcmCommon.h" -#include "gdcmDictEntry.h" #include "gdcmDict.h" +#include "gdcmDictEntry.h" #include "gdcmDictSet.h" -#include "gdcmDocEntrySet.h" -#include "gdcmSQItem.h" -#include "gdcmDocument.h" -#include "gdcmElementSet.h" -#include "gdcmHeader.h" -#include "gdcmHeaderHelper.h" -#include "gdcmFile.h" -#include "gdcmUtil.h" -#include "gdcmGlobal.h" -#include "gdcmDicomDirObject.h" #include "gdcmDicomDir.h" #include "gdcmDicomDirElement.h" +#include "gdcmDicomDirImage.h" #include "gdcmDicomDirMeta.h" +#include "gdcmDicomDirObject.h" #include "gdcmDicomDirPatient.h" #include "gdcmDicomDirStudy.h" #include "gdcmDicomDirSerie.h" -#include "gdcmDicomDirImage.h" +#include "gdcmDocEntrySet.h" +#include "gdcmDocument.h" +#include "gdcmElementSet.h" +#include "gdcmFile.h" +#include "gdcmGlobal.h" +#include "gdcmHeader.h" +#include "gdcmHeaderHelper.h" +#include "gdcmRLEFramesInfo.h" +#include "gdcmJPEGFragmentsInfo.h" +#include "gdcmSQItem.h" +#include "gdcmUtil.h" #include "gdcmValEntry.h" //////////////////////////////////////////////////////////////////////////// @@ -227,6 +229,8 @@ typedef unsigned int guint32; //////////////////////////////////////////////////////////////////////////// // Warning: Order matters ! %include "gdcmCommon.h" +%include "gdcmRLEFramesInfo.h" +%include "gdcmJPEGFragmentsInfo.h" %include "gdcmDictEntry.h" %include "gdcmDict.h" %include "gdcmDocEntry.h" diff --git a/src/gdcmBinEntry.h b/src/gdcmBinEntry.h index 6ba0cba2..5191670a 100644 --- a/src/gdcmBinEntry.h +++ b/src/gdcmBinEntry.h @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmBinEntry.h,v $ Language: C++ - Date: $Date: 2004/10/12 04:35:44 $ - Version: $Revision: 1.22 $ + Date: $Date: 2004/10/18 12:49:22 $ + Version: $Revision: 1.23 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -36,30 +36,23 @@ namespace gdcm class GDCM_EXPORT BinEntry : public ValEntry { public: - - BinEntry(DictEntry* e); - BinEntry(DocEntry* d); + BinEntry( DictEntry* e ); + BinEntry( DocEntry* d ); ~BinEntry(); - void Print(std::ostream &os = std::cout); - void Write(FILE*, FileType); + void Print( std::ostream &os = std::cout ); + void Write( FILE*, FileType ); /// \brief Returns the area value of the current Dicom Header Entry /// when it's not string-translatable (e.g : a LUT table) uint8_t* GetBinArea() { return BinArea; } void SetBinArea( uint8_t* area ); -protected: - private: - -// Variables - /// \brief unsecure memory area to hold 'non string' values /// (ie : Lookup Tables, overlays, icons) uint8_t* BinArea; - }; } // end namespace gdcm //----------------------------------------------------------------------------- diff --git a/src/gdcmDocument.cxx b/src/gdcmDocument.cxx index 60ca2dff..1dbde430 100644 --- a/src/gdcmDocument.cxx +++ b/src/gdcmDocument.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmDocument.cxx,v $ Language: C++ - Date: $Date: 2004/10/12 17:31:56 $ - Version: $Revision: 1.104 $ + Date: $Date: 2004/10/18 12:49:22 $ + Version: $Revision: 1.105 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -1109,7 +1109,12 @@ void* Document::GetEntryBinAreaByNumber(uint16_t group, uint16_t elem) dbg.Verbose(1, "Document::GetDocEntryByNumber: no entry"); return 0; } - return ((BinEntry *)entry)->GetBinArea(); + if ( BinEntry* binEntry = dynamic_cast(entry) ) + { + return binEntry->GetBinArea(); + } + + return 0; } /** @@ -2447,6 +2452,8 @@ void Document::Initialise() { RefPubDict = Global::GetDicts()->GetDefaultPubDict(); RefShaDict = NULL; + RLEInfo = new RLEFramesInfo; + JPEGInfo = new JPEGFragmentsInfo; } /** @@ -2962,7 +2969,7 @@ void Document::ComputeRLEInfo() newFrameInfo->Offset[uk] = frameOffset + rleSegmentOffsetTable[uk]; newFrameInfo->Length[uk] = rleSegmentLength[uk]; } - RLEInfo.Frames.push_back( newFrameInfo ); + RLEInfo->Frames.push_back( newFrameInfo ); } // Make sure that at the end of the item we encounter a 'Sequence @@ -3001,7 +3008,7 @@ void Document::ComputeJPEGFragmentInfo() JPEGFragment* newFragment = new JPEGFragment; newFragment->Offset = fragmentOffset; newFragment->Length = fragmentLength; - JPEGInfo.Fragments.push_back( newFragment ); + JPEGInfo->Fragments.push_back( newFragment ); SkipBytes( fragmentLength ); } diff --git a/src/gdcmDocument.h b/src/gdcmDocument.h index 657fe8c2..6b730260 100644 --- a/src/gdcmDocument.h +++ b/src/gdcmDocument.h @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmDocument.h,v $ Language: C++ - Date: $Date: 2004/10/13 14:15:29 $ - Version: $Revision: 1.51 $ + Date: $Date: 2004/10/18 12:49:22 $ + Version: $Revision: 1.52 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -48,11 +48,11 @@ class GDCM_EXPORT Document : public ElementSet friend class File; private: /// Public dictionary used to parse this header - Dict *RefPubDict; + Dict* RefPubDict; /// \brief Optional "shadow dictionary" (private elements) used to parse /// this header - Dict *RefShaDict; + Dict* RefShaDict; /// \brief Size threshold above which an element value will NOT be loaded /// in memory (to avoid loading the image/volume itself). By default, @@ -75,7 +75,7 @@ protected: int SwapCode; /// File Pointer, opened during Header parsing. - FILE *Fp; + FILE* Fp; /// ACR, ACR_LIBIDO, ExplicitVR, ImplicitVR, Unknown FileType Filetype; @@ -95,10 +95,10 @@ protected: static const unsigned int MAX_SIZE_PRINT_ELEMENT_VALUE; /// Store the RLE frames info obtained during parsing of pixels. - RLEFramesInfo RLEInfo; + RLEFramesInfo* RLEInfo; /// Store the JPEG fragments info obtained during parsing of pixels. - JPEGFragmentsInfo JPEGInfo; + JPEGFragmentsInfo* JPEGInfo; /// \brief Amount of printed details for each Header Entry (Dicom Element): /// 0 : stands for the least detail level. @@ -110,9 +110,9 @@ public: virtual void PrintShaDict (std::ostream &os = std::cout); // Dictionnaries - Dict *GetPubDict(); - Dict *GetShaDict(); - bool SetShaDict(Dict *dict); + Dict* GetPubDict(); + Dict* GetShaDict(); + bool SetShaDict(Dict* dict); bool SetShaDict(DictKey const & dictName); // Informations contained in the parser @@ -138,7 +138,7 @@ public: FILE* OpenFile(); bool CloseFile(); - void Write(FILE* fp, FileType type); + void Write( FILE* fp, FileType type ); ValEntry* ReplaceOrCreateByNumber(std::string const & value, uint16_t group, uint16_t elem, @@ -205,6 +205,8 @@ public: ValEntry* GetValEntryByNumber(uint16_t group, uint16_t element); //BinEntry* GetBinEntryByNumber(uint16_t group, uint16_t element); + RLEFramesInfo* GetRLEInfo() { return RLEInfo; } + JPEGFragmentsInfo* GetJPEGInfo() { return JPEGInfo; } void LoadDocEntrySafe(DocEntry* entry); TagDocEntryHT* BuildFlatHashTable(); diff --git a/src/gdcmFile.cxx b/src/gdcmFile.cxx index 02e6a08a..da8105e3 100644 --- a/src/gdcmFile.cxx +++ b/src/gdcmFile.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmFile.cxx,v $ Language: C++ - Date: $Date: 2004/10/15 10:43:27 $ - Version: $Revision: 1.144 $ + Date: $Date: 2004/10/18 12:49:22 $ + Version: $Revision: 1.145 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -84,70 +84,7 @@ void File::Initialise() ImageDataSize = ImageDataSizeRaw; } - - - - // Just in case some access to a Header element requires disk access. - // Note: gdcmDocument::Fp is leaved open after OpenFile. - (void)HeaderInternal->OpenFile(); - // Number of Bits Allocated for storing a Pixel is defaulted to 16 - // when absent from the header. - int numberBitsAllocated = HeaderInternal->GetBitsAllocated(); - if ( numberBitsAllocated == 0 ) - { - numberBitsAllocated = 16; - } - PixelConverter.SetBitsAllocated( numberBitsAllocated ); - - // Number of "Bits Stored" defaulted to number of "Bits Allocated" - // when absent from the header. - int numberBitsStored = HeaderInternal->GetBitsStored(); - if ( numberBitsStored == 0 ) - { - numberBitsStored = numberBitsAllocated; - } - PixelConverter.SetBitsStored( numberBitsStored ); - - // High Bit Position - int highBitPosition = HeaderInternal->GetHighBitPosition(); - if ( highBitPosition == 0 ) - { - highBitPosition = numberBitsAllocated - 1; - } - PixelConverter.SetHighBitPosition( highBitPosition ); - - - PixelConverter.SetXSize( HeaderInternal->GetXSize() ); - PixelConverter.SetYSize( HeaderInternal->GetYSize() ); - PixelConverter.SetZSize( HeaderInternal->GetZSize() ); - PixelConverter.SetSamplesPerPixel( HeaderInternal->GetSamplesPerPixel() ); - PixelConverter.SetPixelSize( HeaderInternal->GetPixelSize() ); - PixelConverter.SetPixelSign( HeaderInternal->IsSignedPixelData() ); - PixelConverter.SetSwapCode( HeaderInternal->GetSwapCode() ); - PixelConverter.SetIsUncompressed( - ! HeaderInternal->IsDicomV3() - || HeaderInternal->IsImplicitVRLittleEndianTransferSyntax() - || HeaderInternal->IsExplicitVRLittleEndianTransferSyntax() - || HeaderInternal->IsExplicitVRBigEndianTransferSyntax() - || HeaderInternal->IsDeflatedExplicitVRLittleEndianTransferSyntax() ); - PixelConverter.SetIsJPEG2000( HeaderInternal->IsJPEG2000() ); - PixelConverter.SetIsJPEGLossless( HeaderInternal->IsJPEGLossless() ); - PixelConverter.SetIsRLELossless( - HeaderInternal->IsRLELossLessTransferSyntax() ); - PixelConverter.SetPixelOffset( HeaderInternal->GetPixelOffset() ); - PixelConverter.SetPixelDataLength( HeaderInternal->GetPixelAreaLength() ); - PixelConverter.SetRLEInfo( &(HeaderInternal->RLEInfo) ); - PixelConverter.SetJPEGInfo( &(HeaderInternal->JPEGInfo) ); - PixelConverter.SetHasLUT( HeaderInternal->HasLUT() ); - - PixelConverter.SetPlanarConfiguration( - HeaderInternal->GetPlanarConfiguration() ); - PixelConverter.SetIsMonochrome( HeaderInternal->IsMonochrome() ); - PixelConverter.SetIsPaletteColor( HeaderInternal->IsPaletteColor() ); - PixelConverter.SetIsYBRFull( HeaderInternal->IsYBRFull() ); - - HeaderInternal->CloseFile(); - + PixelConverter.GrabInformationsFromHeader( HeaderInternal ); } SaveInitialValues(); } @@ -424,41 +361,30 @@ size_t File::GetImageDataIntoVector (void* destination, size_t maxSize) return ImageDataSize; } - // from Lut R + Lut G + Lut B - uint8_t *newDest = new uint8_t[ImageDataSize]; - uint8_t *a = (uint8_t *)destination; - uint8_t *lutRGBA = HeaderInternal->GetLUTRGBA(); - - if ( lutRGBA ) + FILE* fp = HeaderInternal->OpenFile(); + if ( PixelConverter.BuildRGBImage( fp ) ) { - int j; - // move Gray pixels to temp area - memmove(newDest, destination, ImageDataSizeRaw); - for (size_t i=0; iSetEntryByNumber(spp,0x0028,0x0002); - std::string rgb = "RGB "; // Photometric Interpretation - HeaderInternal->SetEntryByNumber(rgb,0x0028,0x0004); - std::string planConfig = "0"; // Planar Configuration - HeaderInternal->SetEntryByNumber(planConfig,0x0028,0x0006); + std::string spp = "3"; // Samples Per Pixel + HeaderInternal->SetEntryByNumber(spp,0x0028,0x0002); + std::string rgb = "RGB "; // Photometric Interpretation + HeaderInternal->SetEntryByNumber(rgb,0x0028,0x0004); + std::string planConfig = "0"; // Planar Configuration + HeaderInternal->SetEntryByNumber(planConfig,0x0028,0x0006); } - else // GetLUTRGBA() failed + else { + // PixelConverter.BuildRGBImage( fp ) failed probably because + // PixelConverter.GetLUTRGBA() failed: // (gdcm-US-ALOKA-16.dcm), contains Segmented xxx Palette Color // that are *more* than 65535 long ?!? // No idea how to manage such an image ! @@ -468,6 +394,7 @@ size_t File::GetImageDataIntoVector (void* destination, size_t maxSize) std::string photomInterp = "MONOCHROME1 "; // Photometric Interpretation HeaderInternal->SetEntryByNumber(photomInterp,0x0028,0x0004); } + HeaderInternal->CloseFile(); /// \todo Drop Palette Color out of the Header? return ImageDataSize; @@ -785,5 +712,13 @@ bool File::WriteBase (std::string const & fileName, FileType type) return true; } +/** + * \brief Access to the underlying \ref PixelConvertver RGBA LUT + */ +uint8_t* File::GetLutRGBA() +{ + return PixelConverter.GetLutRGBA(); +} + } // end namespace gdcm diff --git a/src/gdcmFile.h b/src/gdcmFile.h index eb430a8c..361bc3d8 100644 --- a/src/gdcmFile.h +++ b/src/gdcmFile.h @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmFile.h,v $ Language: C++ - Date: $Date: 2004/10/13 14:15:30 $ - Version: $Revision: 1.62 $ + Date: $Date: 2004/10/18 12:49:22 $ + Version: $Revision: 1.63 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -80,6 +80,7 @@ public: HeaderInternal->SetEntryByNumber(content,group,element); return true; } + uint8_t* GetLutRGBA(); protected: bool WriteBase(std::string const& fileName, FileType type); @@ -101,6 +102,7 @@ private: void RestoreInitialValues(); // will belong to the future PixelData class void DeleteInitialValues(); // will belong to the future PixelData class +private: // members variables: /// Header to use to load the file diff --git a/src/gdcmHeader.cxx b/src/gdcmHeader.cxx index b6801f8b..12420a38 100644 --- a/src/gdcmHeader.cxx +++ b/src/gdcmHeader.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmHeader.cxx,v $ Language: C++ - Date: $Date: 2004/10/12 04:35:46 $ - Version: $Revision: 1.193 $ + Date: $Date: 2004/10/18 12:49:22 $ + Version: $Revision: 1.194 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -1127,169 +1127,6 @@ int Header::GetLUTNbits() return lutNbits; } -/** - * \brief builts Red/Green/Blue/Alpha LUT from Header - * when (0028,0004),Photometric Interpretation = [PALETTE COLOR ] - * and (0028,1101),(0028,1102),(0028,1102) - * - xxx Palette Color Lookup Table Descriptor - are found - * and (0028,1201),(0028,1202),(0028,1202) - * - xxx Palette Color Lookup Table Data - are found - * \warning does NOT deal with : - * 0028 1100 Gray Lookup Table Descriptor (Retired) - * 0028 1221 Segmented Red Palette Color Lookup Table Data - * 0028 1222 Segmented Green Palette Color Lookup Table Data - * 0028 1223 Segmented Blue Palette Color Lookup Table Data - * no known Dicom reader deals with them :-( - * @return a RGBA Lookup Table - */ -uint8_t* Header::GetLUTRGBA() -{ - // Not so easy : see - // http://www.barre.nom.fr/medical/dicom2/limitations.html#Color%20Lookup%20Tables - -// if Photometric Interpretation # PALETTE COLOR, no LUT to be done - if ( GetEntryByNumber(0x0028,0x0004) != "PALETTE COLOR " ) - { - return NULL; - } - - int lengthR, debR, nbitsR; - int lengthG, debG, nbitsG; - int lengthB, debB, nbitsB; - - // Get info from Lut Descriptors - // (the 3 LUT descriptors may be different) - std::string lutDescriptionR = GetEntryByNumber(0x0028,0x1101); - if ( lutDescriptionR == GDCM_UNFOUND ) - { - return NULL; - } - - std::string lutDescriptionG = GetEntryByNumber(0x0028,0x1102); - if ( lutDescriptionG == GDCM_UNFOUND ) - { - return NULL; - } - - std::string lutDescriptionB = GetEntryByNumber(0x0028,0x1103); - if ( lutDescriptionB == GDCM_UNFOUND ) - { - return NULL; - } - - // lengthR: Red LUT length in Bytes - // debR: subscript of the first Lut Value - // nbitsR: Lut item size (in Bits) - int nbRead = sscanf( lutDescriptionR.c_str(), "%d\\%d\\%d", - &lengthR, &debR, &nbitsR ); - if( nbRead != 3 ) - { - dbg.Verbose(0, "Header::GetLUTRGBA: trouble reading red LUT"); - } - - // lengthG: Green LUT length in Bytes - // debG: subscript of the first Lut Value - // nbitsG: Lut item size (in Bits) - nbRead = sscanf( lutDescriptionG.c_str(), "%d\\%d\\%d", - &lengthG, &debG, &nbitsG ); - if( nbRead != 3 ) - { - dbg.Verbose(0, "Header::GetLUTRGBA: trouble reading green LUT"); - } - - // lengthB: Blue LUT length in Bytes - // debB: subscript of the first Lut Value - // nbitsB: Lut item size (in Bits) - nbRead = sscanf( lutDescriptionB.c_str(), "%d\\%d\\%d", - &lengthB, &debB, &nbitsB ); - if( nbRead != 3 ) - { - dbg.Verbose(0, "Header::GetLUTRGBA: trouble reading blue LUT"); - } - - // Load LUTs into memory, (as they were stored on disk) - uint8_t* lutR = (uint8_t*) GetEntryBinAreaByNumber(0x0028,0x1201); - uint8_t* lutG = (uint8_t*) GetEntryBinAreaByNumber(0x0028,0x1202); - uint8_t* lutB = (uint8_t*) GetEntryBinAreaByNumber(0x0028,0x1203); - - if ( !lutR || !lutG || !lutB ) - { - dbg.Verbose(0, "Header::GetLUTRGBA: trouble with one of the LUT"); - return NULL; - } - // forge the 4 * 8 Bits Red/Green/Blue/Alpha LUT - - uint8_t* LUTRGBA = new uint8_t[1024]; // 256 * 4 (R, G, B, Alpha) - if ( !LUTRGBA ) - { - return NULL; - } - memset(LUTRGBA, 0, 1024); - - // Bits Allocated - int nb; - std::string str_nb = GetEntryByNumber(0x0028,0x0100); - if ( str_nb == GDCM_UNFOUND ) - { - nb = 16; - } - else - { - nb = atoi( str_nb.c_str() ); - } - int mult; - - if ( nbitsR == 16 && nb == 8) - { - // when LUT item size is different than pixel size - mult = 2; // high byte must be = low byte - } - else - { - // See PS 3.3-2003 C.11.1.1.2 p 619 - mult = 1; - } - - // if we get a black image, let's just remove the '+1' - // from 'i*mult+1' and check again - // if it works, we shall have to check the 3 Palettes - // to see which byte is ==0 (first one, or second one) - // and fix the code - // We give up the checking to avoid some (useless ?)overhead - // (optimistic asumption) - uint8_t* a; - int i; - - a = LUTRGBA + 0; - for( i=0; i < lengthR; ++i) - { - *a = lutR[i*mult+1]; - a += 4; - } - - a = LUTRGBA + 1; - for( i=0; i < lengthG; ++i) - { - *a = lutG[i*mult+1]; - a += 4; - } - - a = LUTRGBA + 2; - for(i=0; i < lengthB; ++i) - { - *a = lutB[i*mult+1]; - a += 4; - } - - a = LUTRGBA + 3; - for(i=0; i < 256; ++i) - { - *a = 1; // Alpha component - a += 4; - } - return LUTRGBA; -} - /** * \brief Accesses the info from 0002,0010 : Transfert Syntax and TS * else 1. diff --git a/src/gdcmHeader.h b/src/gdcmHeader.h index b16dd9af..684b99aa 100644 --- a/src/gdcmHeader.h +++ b/src/gdcmHeader.h @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmHeader.h,v $ Language: C++ - Date: $Date: 2004/10/12 04:35:46 $ - Version: $Revision: 1.89 $ + Date: $Date: 2004/10/18 12:49:22 $ + Version: $Revision: 1.90 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -162,7 +162,6 @@ public: bool HasLUT(); int GetLUTNbits(); - unsigned char * GetLUTRGBA(); std::string GetTransfertSyntaxName(); diff --git a/src/gdcmJPEGFragmentsInfo.h b/src/gdcmJPEGFragmentsInfo.h index 80cd904d..815750eb 100644 --- a/src/gdcmJPEGFragmentsInfo.h +++ b/src/gdcmJPEGFragmentsInfo.h @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmJPEGFragmentsInfo.h,v $ Language: C++ - Date: $Date: 2004/10/14 22:35:01 $ - Version: $Revision: 1.3 $ + Date: $Date: 2004/10/18 12:49:22 $ + Version: $Revision: 1.4 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -39,10 +39,11 @@ namespace gdcm */ class GDCM_EXPORT JPEGFragmentsInfo { - typedef std::list< JPEGFragment* > JPEGFragmentsList; friend class Document; friend class File; friend class PixelConvert; +private: + typedef std::list< JPEGFragment* > JPEGFragmentsList; JPEGFragmentsList Fragments; public: ~JPEGFragmentsInfo(); diff --git a/src/gdcmPixelConvert.cxx b/src/gdcmPixelConvert.cxx index b9e5e3ab..4649cbb1 100644 --- a/src/gdcmPixelConvert.cxx +++ b/src/gdcmPixelConvert.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmPixelConvert.cxx,v $ Language: C++ - Date: $Date: 2004/10/15 10:43:28 $ - Version: $Revision: 1.14 $ + Date: $Date: 2004/10/18 12:49:22 $ + Version: $Revision: 1.15 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -53,16 +53,26 @@ PixelConvert::PixelConvert() RGBSize = 0; Decompressed = 0; DecompressedSize = 0; + LutRGBA = 0; + LutRedData = 0; + LutGreenData = 0; + LutBlueData =0; } void PixelConvert::Squeeze() { - if ( RGB ) { + if ( RGB ) + { delete [] RGB; } - if ( Decompressed ) { + if ( Decompressed ) + { delete [] Decompressed; } + if ( LutRGBA ) + { + delete [] LutRGBA; + } } PixelConvert::~PixelConvert() @@ -75,7 +85,7 @@ void PixelConvert::AllocateRGB() if ( RGB ) { delete [] RGB; } - RGB = new uint8_t[RGBSize]; + RGB = new uint8_t[ RGBSize ]; } void PixelConvert::AllocateDecompressed() @@ -87,7 +97,7 @@ void PixelConvert::AllocateDecompressed() } /** - * \brief Read from file a 12 bits per pixel image and uncompress it + * \brief Read from file a 12 bits per pixel image and decompress it * into a 16 bits per pixel image. */ void PixelConvert::ReadAndDecompress12BitsTo16Bits( FILE* fp ) @@ -146,15 +156,15 @@ void PixelConvert::ReadAndDecompress12BitsTo16Bits( FILE* fp ) bool PixelConvert::DecompressRLE16BitsFromRLE8Bits( int NumberOfFrames ) { size_t PixelNumber = XSize * YSize; - size_t uncompressedSize = XSize * YSize * NumberOfFrames; + size_t decompressedSize = XSize * YSize * NumberOfFrames; // We assumed Decompressed contains the decoded RLE pixels but as // 8 bits per pixel. In order to convert those pixels to 16 bits // per pixel we cannot work in place within Decompressed and hence // we copy it in a safe place, say copyDecompressed. - uint8_t* copyDecompressed = new uint8_t[ uncompressedSize * 2 ]; - memmove( copyDecompressed, Decompressed, uncompressedSize * 2 ); + uint8_t* copyDecompressed = new uint8_t[ decompressedSize * 2 ]; + memmove( copyDecompressed, Decompressed, decompressedSize * 2 ); uint8_t* x = Decompressed; uint8_t* a = copyDecompressed; @@ -176,26 +186,26 @@ bool PixelConvert::DecompressRLE16BitsFromRLE8Bits( int NumberOfFrames ) } /** - * \brief Implementation of the RLE decoding algorithm for uncompressing + * \brief Implementation of the RLE decoding algorithm for decompressing * a RLE fragment. [refer to PS 3.5-2003, section G.3.2 p 86] * @param subDecompressed Sub region of \ref Decompressed where the de * decoded fragment should be placed. * @param fragmentSize The length of the binary fragment as found on the disk. - * @param uncompressedSegmentSize The expected length of the fragment ONCE + * @param decompressedSegmentSize The expected length of the fragment ONCE * decompressed. * @param fp File Pointer: on entry the position should be the one of * the fragment to be decoded. */ bool PixelConvert::ReadAndDecompressRLEFragment( uint8_t* subDecompressed, long fragmentSize, - long uncompressedSegmentSize, + long decompressedSegmentSize, FILE* fp ) { int8_t count; long numberOfOutputBytes = 0; long numberOfReadBytes = 0; - while( numberOfOutputBytes < uncompressedSegmentSize ) + while( numberOfOutputBytes < decompressedSegmentSize ) { fread( &count, 1, 1, fp ); numberOfReadBytes += 1; @@ -239,7 +249,7 @@ bool PixelConvert::ReadAndDecompressRLEFragment( uint8_t* subDecompressed, /** * \brief Reads from disk the Pixel Data of 'Run Length Encoded' - * Dicom encapsulated file and uncompress it. + * Dicom encapsulated file and decompress it. * @param fp already open File Pointer * at which the pixel data should be copied * @return Boolean @@ -385,7 +395,7 @@ void PixelConvert::ConvertReorderEndianity() /** * \brief Reads from disk the Pixel Data of JPEG Dicom encapsulated - & file and uncompress it. + & file and decompress it. * @param fp File Pointer * @return Boolean */ @@ -572,9 +582,7 @@ void PixelConvert::ConvertRGBPlanesToRGBPixels() bool PixelConvert::ReadAndDecompressPixelData( FILE* fp ) { - ComputeDecompressedImageDataSize(); - if ( HasLUT ) - DecompressedSize *= 3; + ComputeDecompressedAndRGBSizes(); AllocateDecompressed(); ////////////////////////////////////////////////// //// First stage: get our hands on the Pixel Data. @@ -593,18 +601,18 @@ bool PixelConvert::ReadAndDecompressPixelData( FILE* fp ) } ////////////////////////////////////////////////// - //// Second stage: read from disk dans uncompress. + //// Second stage: read from disk dans decompress. if ( BitsAllocated == 12 ) { ReadAndDecompress12BitsTo16Bits( fp); } - else if ( IsUncompressed ) + else if ( IsDecompressed ) { size_t ItemRead = fread( Decompressed, PixelDataLength, 1, fp ); if ( ItemRead != 1 ) { dbg.Verbose( 0, "PixelConvert::ReadAndDecompressPixelData: " - "reading of uncompressed pixel data failed." ); + "reading of decompressed pixel data failed." ); return false; } } @@ -715,7 +723,7 @@ bool PixelConvert::IsDecompressedRGB() return true; } -void PixelConvert::ComputeDecompressedImageDataSize() +void PixelConvert::ComputeDecompressedAndRGBSizes() { int bitsAllocated = BitsAllocated; // Number of "Bits Allocated" is fixed to 16 when it's 12, since @@ -726,11 +734,317 @@ void PixelConvert::ComputeDecompressedImageDataSize() bitsAllocated = 16; } - DecompressedSize = XSize * YSize * ZSize - * ( bitsAllocated / 8 ) - * SamplesPerPixel; + DecompressedSize = XSize * YSize * ZSize + * ( bitsAllocated / 8 ) + * SamplesPerPixel; + if ( HasLUT ) + { + RGBSize = 3 * DecompressedSize; + } + +} + +void PixelConvert::GrabInformationsFromHeader( Header* header ) +{ + // Just in case some access to a Header element requires disk access. + // Note: gdcmDocument::Fp is leaved open after OpenFile. + FILE* fp = header->OpenFile(); + // Number of Bits Allocated for storing a Pixel is defaulted to 16 + // when absent from the header. + BitsAllocated = header->GetBitsAllocated(); + if ( BitsAllocated == 0 ) + { + BitsAllocated = 16; + } + + // Number of "Bits Stored" defaulted to number of "Bits Allocated" + // when absent from the header. + BitsStored = header->GetBitsStored(); + if ( BitsStored == 0 ) + { + BitsStored = BitsAllocated; + } + + // High Bit Position + HighBitPosition = header->GetHighBitPosition(); + if ( HighBitPosition == 0 ) + { + HighBitPosition = BitsAllocated - 1; + } + + XSize = header->GetXSize(); + YSize = header->GetYSize(); + ZSize = header->GetZSize(); + SamplesPerPixel = header->GetSamplesPerPixel(); + PixelSize = header->GetPixelSize(); + PixelSign = header->IsSignedPixelData(); + SwapCode = header->GetSwapCode(); + IsDecompressed = + ( ! header->IsDicomV3() ) + || header->IsImplicitVRLittleEndianTransferSyntax() + || header->IsExplicitVRLittleEndianTransferSyntax() + || header->IsExplicitVRBigEndianTransferSyntax() + || header->IsDeflatedExplicitVRLittleEndianTransferSyntax(); + IsJPEG2000 = header->IsJPEG2000(); + IsJPEGLossless = header->IsJPEGLossless(); + IsRLELossless = header->IsRLELossLessTransferSyntax(); + PixelOffset = header->GetPixelOffset(); + PixelDataLength = header->GetPixelAreaLength(); + RLEInfo = header->GetRLEInfo(); + JPEGInfo = header->GetJPEGInfo(); + + PlanarConfiguration = header->GetPlanarConfiguration(); + IsMonochrome = header->IsMonochrome(); + IsPaletteColor = header->IsPaletteColor(); + IsYBRFull = header->IsYBRFull(); + + ///////////////////////////////////////////////////////////////// + // LUT section: + HasLUT = header->HasLUT(); + if ( HasLUT ) + { + LutRedDescriptor = header->GetEntryByNumber( 0x0028, 0x1101 ); + LutGreenDescriptor = header->GetEntryByNumber( 0x0028, 0x1102 ); + LutBlueDescriptor = header->GetEntryByNumber( 0x0028, 0x1103 ); + + // Depending on the value of Document::MAX_SIZE_LOAD_ELEMENT_VALUE + // [ refer to invocation of Document::SetMaxSizeLoadEntry() in + // Document::Document() ], the loading of the value (content) of a + // [Bin|Val]Entry occurence migth have been hindered (read simply NOT + // loaded). Hence, we first try to obtain the LUTs data from the header + // and when this fails we read the LUTs data directely from disk. + /// \todo Reading a [Bin|Val]Entry directly from disk is a kludge. + /// We should NOT bypass the [Bin|Val]Entry class. Instead + /// an access to an UNLOADED content of a [Bin|Val]Entry occurence + /// (e.g. BinEntry::GetBinArea()) should force disk access from + /// within the [Bin|Val]Entry class itself. The only problem + /// is that the [Bin|Val]Entry is unaware of the FILE* is was + /// parsed from. Fix that. FIXME. + + ////// Red round: + LutRedData = (uint8_t*)header->GetEntryBinAreaByNumber( 0x0028, 0x1201 ); + if ( ! LutRedData ) + { + // Read the Lut Data from disk + DocEntry* lutRedDataEntry = header->GetDocEntryByNumber( 0x0028, + 0x1201 ); + LutRedData = new uint8_t[ lutRedDataEntry->GetLength() ]; + fseek( fp, lutRedDataEntry->GetOffset() ,SEEK_SET ); + int numberItem = fread( LutRedData, + (size_t)lutRedDataEntry->GetLength(), + 1, fp ); + if ( numberItem != 1 ) + { + dbg.Verbose(0, "PixelConvert::GrabInformationsFromHeader: " + "unable to read red LUT data" ); + return; + } + } + + ////// Green round: + LutGreenData = (uint8_t*)header->GetEntryBinAreaByNumber(0x0028, 0x1202 ); + if ( ! LutGreenData) + { + // Read the Lut Data from disk + DocEntry* lutGreenDataEntry = header->GetDocEntryByNumber( 0x0028, + 0x1202 ); + LutGreenData = new uint8_t[ lutGreenDataEntry->GetLength() ]; + fseek( fp, lutGreenDataEntry->GetOffset() ,SEEK_SET ); + int numberItem = fread( LutGreenData, + (size_t)lutGreenDataEntry->GetLength(), + 1, fp ); + if ( numberItem != 1 ) + { + dbg.Verbose(0, "PixelConvert::GrabInformationsFromHeader: " + "unable to read green LUT data" ); + return; + } + } + + ////// Blue round: + LutBlueData = (uint8_t*)header->GetEntryBinAreaByNumber( 0x0028, 0x1203 ); + if ( ! LutBlueData ) + { + // Read the Lut Data from disk + DocEntry* lutBlueDataEntry = header->GetDocEntryByNumber( 0x0028, + 0x1203 ); + LutBlueData = new uint8_t[ lutBlueDataEntry->GetLength() ]; + fseek( fp, lutBlueDataEntry->GetOffset() ,SEEK_SET ); + int numberItem = fread( LutBlueData, + (size_t)lutBlueDataEntry->GetLength(), + 1, fp ); + if ( numberItem != 1 ) + { + dbg.Verbose(0, "PixelConvert::GrabInformationsFromHeader: " + "unable to read blue LUT data" ); + return; + } + } + } + + header->CloseFile(); +} + +/** + * \brief Build Red/Green/Blue/Alpha LUT from Header + * when (0028,0004),Photometric Interpretation = [PALETTE COLOR ] + * and (0028,1101),(0028,1102),(0028,1102) + * - xxx Palette Color Lookup Table Descriptor - are found + * and (0028,1201),(0028,1202),(0028,1202) + * - xxx Palette Color Lookup Table Data - are found + * \warning does NOT deal with : + * 0028 1100 Gray Lookup Table Descriptor (Retired) + * 0028 1221 Segmented Red Palette Color Lookup Table Data + * 0028 1222 Segmented Green Palette Color Lookup Table Data + * 0028 1223 Segmented Blue Palette Color Lookup Table Data + * no known Dicom reader deals with them :-( + * @return a RGBA Lookup Table + */ +void PixelConvert::BuildLUTRGBA( FILE* fp ) +{ + if ( LutRGBA ) + { + return; + } + // Not so easy : see + // http://www.barre.nom.fr/medical/dicom2/limitations.html#Color%20Lookup%20Tables + + if ( ! IsPaletteColor ) + { + return; + } + + if ( ( LutRedDescriptor == GDCM_UNFOUND ) + || ( LutGreenDescriptor == GDCM_UNFOUND ) + || ( LutBlueDescriptor == GDCM_UNFOUND ) ) + { + return; + } + + //////////////////////////////////////////// + // Extract the info from the LUT descriptors + int lengthR; // Red LUT length in Bytes + int debR; // Subscript of the first Lut Value + int nbitsR; // Lut item size (in Bits) + int nbRead = sscanf( LutRedDescriptor.c_str(), + "%d\\%d\\%d", + &lengthR, &debR, &nbitsR ); + if( nbRead != 3 ) + { + dbg.Verbose(0, "PixelConvert::BuildLUTRGBA: wrong red LUT descriptor"); + } + + int lengthG; // Green LUT length in Bytes + int debG; // Subscript of the first Lut Value + int nbitsG; // Lut item size (in Bits) + nbRead = sscanf( LutGreenDescriptor.c_str(), + "%d\\%d\\%d", + &lengthG, &debG, &nbitsG ); + if( nbRead != 3 ) + { + dbg.Verbose(0, "PixelConvert::BuildLUTRGBA: wrong green LUT descriptor"); + } + + int lengthB; // Blue LUT length in Bytes + int debB; // Subscript of the first Lut Value + int nbitsB; // Lut item size (in Bits) + nbRead = sscanf( LutRedDescriptor.c_str(), + "%d\\%d\\%d", + &lengthB, &debB, &nbitsB ); + if( nbRead != 3 ) + { + dbg.Verbose(0, "PixelConvert::BuildLUTRGBA: wrong blue LUT descriptor"); + } + + //////////////////////////////////////////////////////// + if ( ( ! LutRedData ) || ( ! LutGreenData ) || ( ! LutBlueData ) ) + { + return; + } + + //////////////////////////////////////////////// + // forge the 4 * 8 Bits Red/Green/Blue/Alpha LUT + LutRGBA = new uint8_t[ 1024 ]; // 256 * 4 (R, G, B, Alpha) + if ( !LutRGBA ) + { + return; + } + memset( LutRGBA, 0, 1024 ); + + int mult; + if ( ( nbitsR == 16 ) && ( BitsAllocated == 8 ) ) + { + // when LUT item size is different than pixel size + mult = 2; // high byte must be = low byte + } + else + { + // See PS 3.3-2003 C.11.1.1.2 p 619 + mult = 1; + } + + // if we get a black image, let's just remove the '+1' + // from 'i*mult+1' and check again + // if it works, we shall have to check the 3 Palettes + // to see which byte is ==0 (first one, or second one) + // and fix the code + // We give up the checking to avoid some (useless ?)overhead + // (optimistic asumption) + int i; + uint8_t* a = LutRGBA + 0; + for( i=0; i < lengthR; ++i ) + { + *a = LutRedData[i*mult+1]; + a += 4; + } + + a = LutRGBA + 1; + for( i=0; i < lengthG; ++i) + { + *a = LutGreenData[i*mult+1]; + a += 4; + } + + a = LutRGBA + 2; + for(i=0; i < lengthB; ++i) + { + *a = LutBlueData[i*mult+1]; + a += 4; + } + + a = LutRGBA + 3; + for(i=0; i < 256; ++i) + { + *a = 1; // Alpha component + a += 4; + } } +/** + * \brief Build the RGB image from the Decompressed imagage and the LUTs. + */ +bool PixelConvert::BuildRGBImage( FILE* fp ) +{ + BuildLUTRGBA( fp ); + if ( ! LutRGBA ) + { + return false; + } + + // Build RGB Pixels + AllocateRGB(); + uint8_t* localRGB = RGB; + for (size_t i = 0; i < DecompressedSize; ++i ) + { + int j = Decompressed[i] * 4; // \todo I don't get this 4 coefficient ! + *localRGB++ = LutRGBA[j]; + *localRGB++ = LutRGBA[j+1]; + *localRGB++ = LutRGBA[j+2]; + } + return true; +} + + } // end namespace gdcm // NOTES on File internal calls diff --git a/src/gdcmPixelConvert.h b/src/gdcmPixelConvert.h index 784c2e0e..e65a701c 100644 --- a/src/gdcmPixelConvert.h +++ b/src/gdcmPixelConvert.h @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmPixelConvert.h,v $ Language: C++ - Date: $Date: 2004/10/15 10:43:28 $ - Version: $Revision: 1.9 $ + Date: $Date: 2004/10/18 12:49:23 $ + Version: $Revision: 1.10 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -24,6 +24,7 @@ #include "gdcmRLEFramesInfo.h" #include "gdcmJPEGFragmentsInfo.h" #include "gdcmException.h" +#include "gdcmHeader.h" namespace gdcm { @@ -33,106 +34,37 @@ namespace gdcm * migth take during the user demanded processes. */ class GDCM_EXPORT PixelConvert { -friend class File; - /// Pixel data represented as RGB after color interpretation - uint8_t* RGB; - size_t RGBSize; //aka ImageDataSize - /// Pixel data after decompression and bit/byte rearrangement. - uint8_t* Decompressed; - size_t DecompressedSize; - - // Set by the accessors: - size_t PixelOffset; - size_t PixelDataLength; - int XSize; - int YSize; - int ZSize; - int BitsAllocated; - int BitsStored; - int HighBitPosition; - int SamplesPerPixel; - int PixelSize; - bool PixelSign; - int SwapCode; - - bool IsUncompressed; - bool IsJPEG2000; - bool IsJPEGLossless; - bool IsRLELossless; - - RLEFramesInfo* RLEInfo; - JPEGFragmentsInfo* JPEGInfo; - - // For handling color stage - int PlanarConfiguration; - bool IsMonochrome; - bool IsPaletteColor; - bool IsYBRFull; - bool HasLUT; - public: PixelConvert(); ~PixelConvert(); - //// Setter accessors: - void SetXSize( int xSize ) { XSize = xSize; } - void SetYSize( int ySize ) { YSize = ySize; } - void SetZSize( int zSize ) { ZSize = zSize; } - void SetBitsAllocated( int bitsAllocated ) { BitsAllocated = bitsAllocated; } - void SetBitsStored( int bitsStored ) { BitsStored = bitsStored; } - void SetHighBitPosition( int highBitPosition ) - { HighBitPosition = highBitPosition; } - void SetSamplesPerPixel( int samplesPerPixel ) - { SamplesPerPixel = samplesPerPixel; } - void SetPixelSize( int pixelSize ) { PixelSize = pixelSize; } - void SetPixelSign( int pixelSign ) { PixelSign = pixelSign; } - void SetSwapCode( int swapCode ) { SwapCode = swapCode; } - void SetIsUncompressed( bool isUncompressed ) - { IsUncompressed = isUncompressed; } - void SetIsJPEG2000( bool isJPEG2000 ) { IsJPEG2000 = isJPEG2000; } - void SetIsJPEGLossless( bool isJPEGLossless ) - { IsJPEGLossless = isJPEGLossless; } - void SetIsRLELossless( bool isRLELossless ) - { IsRLELossless = isRLELossless; } - void SetPixelOffset( size_t pixelOffset ) { PixelOffset = pixelOffset; } - void SetPixelDataLength( size_t pixelDataLength ) - { PixelDataLength = pixelDataLength; } - void SetRLEInfo( RLEFramesInfo* inRLEFramesInfo ) - { RLEInfo = inRLEFramesInfo; } - void SetJPEGInfo( JPEGFragmentsInfo* inJPEGFragmentsInfo ) - { JPEGInfo = inJPEGFragmentsInfo; } - - void SetPlanarConfiguration( size_t planarConfiguration ) - { PlanarConfiguration = planarConfiguration; } - void SetIsMonochrome( bool isMonochrome ) { IsMonochrome = isMonochrome; } - void SetIsPaletteColor( bool isPaletteColor ) - { IsPaletteColor = isPaletteColor; } - void SetIsYBRFull( bool isYBRFull ) { IsYBRFull = isYBRFull; } - void SetHasLUT ( bool hasLUT ) { HasLUT = hasLUT; } - - void SetRGBSize( size_t size ) { RGBSize = size; } - void SetDecompressedSize( size_t size ) { DecompressedSize = size; } - //// Getter accessors: uint8_t* GetRGB() { return RGB; } size_t GetRGBSize() { return RGBSize; } uint8_t* GetDecompressed() { return Decompressed; } size_t GetDecompressedSize() { return DecompressedSize; } + uint8_t* GetLutRGBA() { return LutRGBA; } //// Predicates: bool IsDecompressedRGB(); -////////////////////////////////////////////////////////// +// In progress + void GrabInformationsFromHeader( Header* header ); + bool ReadAndDecompressPixelData( FILE* fp ); + void Squeeze(); + bool BuildRGBImage( FILE* fp ); + private: // Use the fp: bool ReadAndDecompressRLEFragment( - uint8_t* decodedZone, + uint8_t* subDecompressed, long fragmentSize, - long uncompressedSegmentSize, + long decompressedSegmentSize, FILE* fp ); void ReadAndDecompress12BitsTo16Bits( FILE* fp ) throw ( FormatError ); bool ReadAndDecompressRLEFile( FILE* fp ); bool ReadAndDecompressJPEGFile( FILE* fp ); + void BuildLUTRGBA( FILE* fp ); // In place (within Decompressed and with no fp access) decompression // or convertion: @@ -144,13 +76,58 @@ private: void ConvertYcBcRPlanesToRGBPixels(); void ConvertHandleColor(); - void ComputeDecompressedImageDataSize(); + void ComputeDecompressedAndRGBSizes(); void AllocateRGB(); void AllocateDecompressed(); -public: -// In progress - bool ReadAndDecompressPixelData( FILE* fp ); - void Squeeze(); + +// Variables + /// Pixel data represented as RGB after LUT color interpretation. + uint8_t* RGB; + /// Size of \ref RGB image. + size_t RGBSize; + /// Pixel data after decompression and bit/byte rearrangement. + uint8_t* Decompressed; + /// Size of \ref Decompressed image. + size_t DecompressedSize; + /// \brief Red/Green/Blue/Alpha LookUpTable build out of the + /// Red/Green/Blue LUT descriptors (see \ref BuildLUTRGBA ). + uint8_t* LutRGBA; + + size_t PixelOffset; + size_t PixelDataLength; + int XSize; + int YSize; + int ZSize; + int BitsAllocated; + int BitsStored; + int HighBitPosition; + int SamplesPerPixel; + int PixelSize; + bool PixelSign; + int SwapCode; + + bool IsDecompressed; + bool IsJPEG2000; + bool IsJPEGLossless; + bool IsRLELossless; + + RLEFramesInfo* RLEInfo; + JPEGFragmentsInfo* JPEGInfo; + + // For handling color stage + int PlanarConfiguration; + bool IsMonochrome; + bool IsPaletteColor; + bool IsYBRFull; + bool HasLUT; + // The 3 LUT descriptors may be different: + std::string LutRedDescriptor; + std::string LutGreenDescriptor; + std::string LutBlueDescriptor; + uint8_t* LutRedData; + uint8_t* LutGreenData; + uint8_t* LutBlueData; + }; } // end namespace gdcm diff --git a/src/gdcmRLEFrame.h b/src/gdcmRLEFrame.h index f1e27c6e..f7dcf0d5 100644 --- a/src/gdcmRLEFrame.h +++ b/src/gdcmRLEFrame.h @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmRLEFrame.h,v $ Language: C++ - Date: $Date: 2004/10/12 04:35:47 $ - Version: $Revision: 1.5 $ + Date: $Date: 2004/10/18 12:49:23 $ + Version: $Revision: 1.6 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -21,6 +21,7 @@ #define GDCMRLEFRAME_H #include "gdcmCommon.h" + namespace gdcm { /** diff --git a/vtk/vtkGdcmReader.cxx b/vtk/vtkGdcmReader.cxx index dc866270..60f03813 100644 --- a/vtk/vtkGdcmReader.cxx +++ b/vtk/vtkGdcmReader.cxx @@ -58,7 +58,7 @@ #include #include -vtkCxxRevisionMacro(vtkGdcmReader, "$Revision: 1.51 $"); +vtkCxxRevisionMacro(vtkGdcmReader, "$Revision: 1.52 $"); vtkStandardNewMacro(vtkGdcmReader); //----------------------------------------------------------------------------- @@ -633,7 +633,7 @@ size_t vtkGdcmReader::LoadImageInMemory( { size = file.GetImageDataSizeRaw(); source = (unsigned char*) file.GetImageDataRaw(); - unsigned char *lut = file.GetHeader()->GetLUTRGBA(); + unsigned char *lut = (unsigned char*) file.GetLutRGBA(); if(!this->LookupTable) { -- 2.45.1