X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;ds=sidebyside;f=src%2FgdcmFile.cxx;h=6909a643aa7d8a859a841f59181b313977b34696;hb=f5028f34faa657dc1722331963f97c7734ee2d2a;hp=3484aecf075b7f470081797e839877fc5ff296f3;hpb=1d69b92978803204089d270599133917d944c651;p=gdcm.git diff --git a/src/gdcmFile.cxx b/src/gdcmFile.cxx index 3484aecf..6909a643 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/12 04:35:46 $ - Version: $Revision: 1.139 $ + Date: $Date: 2004/10/20 22:31:52 $ + Version: $Revision: 1.147 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -18,7 +18,6 @@ #include "gdcmFile.h" #include "gdcmDebug.h" -#include "gdcmPixelConvert.h" namespace gdcm { @@ -84,6 +83,9 @@ void File::Initialise() { ImageDataSize = ImageDataSizeRaw; } + + PixelConverter = new PixelConvert; + PixelConverter->GrabInformationsFromHeader( HeaderInternal ); } SaveInitialValues(); } @@ -266,8 +268,11 @@ int File::ComputeDecompressedPixelDataSizeFromHeader() // 0028|1202 [US] [Green Palette Color Lookup Table Data] // 0028|1203 [US] [Blue Palette Color Lookup Table Data] - // Number of "Bits Allocated" int numberBitsAllocated = HeaderInternal->GetBitsAllocated(); + // Number of "Bits Allocated" is fixed to 16 when: + // - it is not defined (i.e. it's value is 0) + // - it's 12, since we will expand the image to 16 bits (see + // PixelConvert::ConvertDecompress12BitsTo16Bits() ) if ( ( numberBitsAllocated == 0 ) || ( numberBitsAllocated == 12 ) ) { numberBitsAllocated = 16; @@ -357,41 +362,29 @@ 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 ) + if ( PixelConverter->BuildRGBImage() ) { - int j; - // move Gray pixels to temp area - memmove(newDest, destination, ImageDataSizeRaw); - for (size_t i=0; iGetRGB(), + PixelConverter->GetRGBSize() ); - // now, it's an RGB image - // Lets's write it in the Header + // now, it's an RGB image + // Lets's write it in the Header - // FIXME : Better use CreateOrReplaceIfExist ? + // FIXME : Better use CreateOrReplaceIfExist ? - 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); + 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() 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 ! @@ -417,40 +410,59 @@ size_t File::GetImageDataIntoVector (void* destination, size_t maxSize) */ uint8_t* File::GetImageDataRaw () { - size_t imgDataSize; - if ( HeaderInternal->HasLUT() ) - /// \todo Let Header user a chance to get the right value - imgDataSize = ImageDataSizeRaw; - else - imgDataSize = ImageDataSize; - - // FIXME (Mathieu) - // I need to deallocate Pixel_Data before doing any allocation: - - if ( Pixel_Data ) - if ( LastAllocatedPixelDataLength != imgDataSize ) - free(Pixel_Data); - if ( !Pixel_Data ) - Pixel_Data = new uint8_t[imgDataSize]; + uint8_t* decompressed = PixelConverter->GetDecompressed(); + if ( ! decompressed ) + { + // The decompressed image migth not be loaded yet: + FILE* fp = HeaderInternal->OpenFile(); + PixelConverter->ReadAndDecompressPixelData( fp ); + HeaderInternal->CloseFile(); + if ( ! decompressed ) + { + dbg.Verbose(0, "File::GetImageDataRaw: read/decompress of " + "pixel data apparently went wrong."); + return 0; + } + } - if ( Pixel_Data ) +// PIXELCONVERT CLEANME + // Restore the header in a disk-consistent state + // (if user asks twice to get the pixels from disk) + if ( PixelRead != -1 ) // File was "read" before { - LastAllocatedPixelDataLength = imgDataSize; - - // we load the pixels ( grey level or RGB, but NO transformation) - GetImageDataIntoVectorRaw(Pixel_Data, imgDataSize); + RestoreInitialValues(); + } + if ( PixelConverter->IsDecompressedRGB() ) + { + /////////////////////////////////////////////////// + // now, it's an RGB image + // Lets's write it in the Header + // Droping Palette Color out of the Header + // has been moved to the Write process. + // TODO : move 'values' modification to the write process + // : save also (in order to be able to restore) + // : 'high bit' -when not equal to 'bits stored' + 1 + // : 'bits allocated', when it's equal to 12 ?! + std::string spp = "3"; // Samples Per Pixel + std::string photInt = "RGB "; // Photometric Interpretation + std::string planConfig = "0"; // Planar Configuration + HeaderInternal->SetEntryByNumber(spp,0x0028,0x0002); + HeaderInternal->SetEntryByNumber(photInt,0x0028,0x0004); + HeaderInternal->SetEntryByNumber(planConfig,0x0028,0x0006); + } - // We say the value *is* loaded. - GetHeader()->SetEntryByNumber( GDCM_BINLOADED, - GetHeader()->GetGrPixel(), GetHeader()->GetNumPixel()); + // We say the value *is* loaded. + GetHeader()->SetEntryByNumber( GDCM_BINLOADED, + GetHeader()->GetGrPixel(), GetHeader()->GetNumPixel()); + + // will be 7fe0, 0010 in standard cases + GetHeader()->SetEntryBinAreaByNumber( decompressed, + GetHeader()->GetGrPixel(), GetHeader()->GetNumPixel()); - // will be 7fe0, 0010 in standard cases - GetHeader()->SetEntryBinAreaByNumber(Pixel_Data, - GetHeader()->GetGrPixel(), GetHeader()->GetNumPixel()); - } PixelRead = 1; // PixelRaw +// END PIXELCONVERT CLEANME - return Pixel_Data; + return decompressed; } /** @@ -476,7 +488,7 @@ uint8_t* File::GetImageDataRaw () * @return On success, the number of bytes actually copied. Zero on * failure e.g. MaxSize is lower than necessary. */ -size_t File::GetImageDataIntoVectorRaw (void* destination, size_t maxSize) +void File::GetImageDataIntoVectorRaw (void* destination, size_t maxSize) { // we save the initial values of the following // in order to be able to restore the header in a disk-consistent state @@ -493,104 +505,19 @@ size_t File::GetImageDataIntoVectorRaw (void* destination, size_t maxSize) { dbg.Verbose(0, "File::GetImageDataIntoVector: pixel data bigger" "than caller's expected MaxSize"); - return (size_t)0; - } - - ReadPixelData( destination ); - - // Number of Bits Allocated for storing a Pixel - int numberBitsAllocated = HeaderInternal->GetBitsAllocated(); - if ( numberBitsAllocated == 0 ) - { - numberBitsAllocated = 16; - } - - // Number of Bits actually used - int numberBitsStored = HeaderInternal->GetBitsStored(); - if ( numberBitsStored == 0 ) - { - numberBitsStored = numberBitsAllocated; - } - - // High Bit Position - int highBitPosition = HeaderInternal->GetHighBitPosition(); - if ( highBitPosition == 0 ) - { - highBitPosition = numberBitsAllocated - 1; + return; } - bool signedPixel = HeaderInternal->IsSignedPixelData(); - - PixelConvert::ConvertReorderEndianity( - (uint8_t*) destination, - ImageDataSize, - numberBitsStored, - numberBitsAllocated, - HeaderInternal->GetSwapCode(), - signedPixel ); - - PixelConvert::ConvertReArrangeBits( - (uint8_t*) destination, - ImageDataSize, - numberBitsStored, - numberBitsAllocated, - highBitPosition ); - -#ifdef GDCM_DEBUG - FILE* DebugFile; - DebugFile = fopen( "SpuriousFile.RAW", "wb" ); - fwrite( PixelConvertor.GetUncompressed(), - PixelConvertor.GetUncompressedsSize(), - 1, DebugFile ); - fclose( DebugFile ); -#endif //GDCM_DEBUG - -// SPLIT ME -////////////////////////////////// -// Deal with the color - - // Monochrome pictures don't require color intervention - if ( HeaderInternal->IsMonochrome() ) - { - return ImageDataSize; - } - - // Planar configuration = 0 : Pixels are already RGB - // Planar configuration = 1 : 3 planes : R, G, B - // Planar configuration = 2 : 1 gray Plane + 3 LUT - - // Well ... supposed to be ! - // See US-PAL-8-10x-echo.dcm: PlanarConfiguration=0, - // PhotometricInterpretation=PALETTE COLOR - // and heuristic has to be found :-( - - int planConf = HeaderInternal->GetPlanarConfiguration(); - - // Planar configuration = 2 ==> 1 gray Plane + 3 LUT - // ...and... - // whatever the Planar Configuration might be, "PALETTE COLOR " - // implies that we deal with the palette. - if ( ( planConf == 2 ) || HeaderInternal->IsPaletteColor() ) - { - return ImageDataSize; - } - - // When planConf is 0, pixels are allready in RGB + FILE* fp = HeaderInternal->OpenFile(); + PixelConverter->ReadAndDecompressPixelData( fp ); + HeaderInternal->CloseFile(); + memmove( destination, + (void*)PixelConverter->GetDecompressed(), + PixelConverter->GetDecompressedSize() ); - if ( planConf == 1 ) + if ( ! PixelConverter->IsDecompressedRGB() ) { - uint8_t* newDest = new uint8_t[ImageDataSize]; - // Warning : YBR_FULL_422 acts as RGB - if ( HeaderInternal->IsYBRFull() ) - { - ConvertYcBcRPlanesToRGBPixels((uint8_t*)destination, newDest); - } - else - { - ConvertRGBPlanesToRGBPixels((uint8_t*)destination, newDest); - } - memmove(destination, newDest, ImageDataSize); - delete[] newDest; + return; } /////////////////////////////////////////////////// @@ -613,78 +540,7 @@ size_t File::GetImageDataIntoVectorRaw (void* destination, size_t maxSize) HeaderInternal->SetEntryByNumber(photInt,0x0028,0x0004); HeaderInternal->SetEntryByNumber(planConfig,0x0028,0x0006); - return ImageDataSize; -} - -/** - * \brief Convert (Y plane, cB plane, cR plane) to RGB pixels - * \warning Works on all the frames at a time - */ -void File::ConvertYcBcRPlanesToRGBPixels(uint8_t* source, - uint8_t* destination) -{ - // to see the tricks about YBR_FULL, YBR_FULL_422, - // YBR_PARTIAL_422, YBR_ICT, YBR_RCT have a look at : - // ftp://medical.nema.org/medical/dicom/final/sup61_ft.pdf - // and be *very* affraid - // - int l = HeaderInternal->GetXSize() * HeaderInternal->GetYSize(); - int nbFrames = HeaderInternal->GetZSize(); - - uint8_t* a = source; - uint8_t* b = source + l; - uint8_t* c = source + l + l; - double R, G, B; - - /// \todo : Replace by the 'well known' integer computation - /// counterpart. Refer to - /// http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf - /// for code optimisation. - - for (int i = 0; i < nbFrames; i++) - { - for (int j = 0; j < l; j++) - { - R = 1.164 *(*a-16) + 1.596 *(*c -128) + 0.5; - G = 1.164 *(*a-16) - 0.813 *(*c -128) - 0.392 *(*b -128) + 0.5; - B = 1.164 *(*a-16) + 2.017 *(*b -128) + 0.5; - - if (R < 0.0) R = 0.0; - if (G < 0.0) G = 0.0; - if (B < 0.0) B = 0.0; - if (R > 255.0) R = 255.0; - if (G > 255.0) G = 255.0; - if (B > 255.0) B = 255.0; - - *(destination++) = (uint8_t)R; - *(destination++) = (uint8_t)G; - *(destination++) = (uint8_t)B; - a++; - b++; - c++; - } - } -} - -/** - * \brief Convert (Red plane, Green plane, Blue plane) to RGB pixels - * \warning Works on all the frames at a time - */ -void File::ConvertRGBPlanesToRGBPixels(uint8_t* source, - uint8_t* destination) -{ - int l = HeaderInternal->GetXSize() * HeaderInternal->GetYSize() * HeaderInternal->GetZSize(); - - uint8_t* a = source; - uint8_t* b = source + l; - uint8_t* c = source + l + l; - - for (int j = 0; j < l; j++) - { - *(destination++) = *(a++); - *(destination++) = *(b++); - *(destination++) = *(c++); - } + return; } /** @@ -874,94 +730,12 @@ bool File::WriteBase (std::string const & fileName, FileType type) return true; } -//----------------------------------------------------------------------------- -// Private /** - * \brief Read pixel data from disk (optionaly decompressing) into the - * caller specified memory location. - * @param destination where the pixel data should be stored. - * + * \brief Access to the underlying \ref PixelConverter RGBA LUT */ -bool File::ReadPixelData(void* destination) +uint8_t* File::GetLutRGBA() { - FILE* fp = HeaderInternal->OpenFile(); - - if ( !fp ) - { - return false; - } - if ( fseek(fp, HeaderInternal->GetPixelOffset(), SEEK_SET) == -1 ) - { - HeaderInternal->CloseFile(); - return false; - } - - if ( HeaderInternal->GetBitsAllocated() == 12 ) - { - PixelConvert::ConvertDecompress12BitsTo16Bits( - (uint8_t*)destination, - HeaderInternal->GetXSize(), - HeaderInternal->GetYSize(), - fp); - HeaderInternal->CloseFile(); - return true; - } - - // ---------------------- Uncompressed File - if ( !HeaderInternal->IsDicomV3() || - HeaderInternal->IsImplicitVRLittleEndianTransferSyntax() || - HeaderInternal->IsExplicitVRLittleEndianTransferSyntax() || - HeaderInternal->IsExplicitVRBigEndianTransferSyntax() || - HeaderInternal->IsDeflatedExplicitVRLittleEndianTransferSyntax() ) - { - size_t ItemRead = fread(destination, HeaderInternal->GetPixelAreaLength(), 1, fp); - HeaderInternal->CloseFile(); - if ( ItemRead != 1 ) - { - return false; - } - else - { - return true; - } - } - - // ---------------------- Run Length Encoding - if ( HeaderInternal->IsRLELossLessTransferSyntax() ) - { - bool res = PixelConvert::ReadAndDecompressRLEFile( - destination, - HeaderInternal->GetXSize(), - HeaderInternal->GetYSize(), - HeaderInternal->GetZSize(), - HeaderInternal->GetBitsAllocated(), - &(HeaderInternal->RLEInfo), - fp ); - HeaderInternal->CloseFile(); - return res; - } - - // --------------- SingleFrame/Multiframe JPEG Lossless/Lossy/2000 - int numberBitsAllocated = HeaderInternal->GetBitsAllocated(); - if ( ( numberBitsAllocated == 0 ) || ( numberBitsAllocated == 12 ) ) - { - numberBitsAllocated = 16; - } - - bool res = PixelConvert::ReadAndDecompressJPEGFile( - (uint8_t*)destination, - HeaderInternal->GetXSize(), - HeaderInternal->GetYSize(), - HeaderInternal->GetBitsAllocated(), - HeaderInternal->GetBitsStored(), - HeaderInternal->GetSamplesPerPixel(), - HeaderInternal->GetPixelSize(), - HeaderInternal->IsJPEG2000(), - HeaderInternal->IsJPEGLossless(), - &(HeaderInternal->JPEGInfo), - fp ); - HeaderInternal->CloseFile(); - return res; + return PixelConverter->GetLutRGBA(); } } // end namespace gdcm