X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmFile.cxx;h=4b22d148d7ec4823f52bdf2e5f1ae1fbc130241a;hb=ea14e11cdd726f9c7e6d6384c7e9e508bc6efc2d;hp=4490655cc9e146d786a814dc74de914450e381be;hpb=f25cae887a0906bd4c4733da51a88bf08a85e840;p=gdcm.git diff --git a/src/gdcmFile.cxx b/src/gdcmFile.cxx index 4490655c..4b22d148 100644 --- a/src/gdcmFile.cxx +++ b/src/gdcmFile.cxx @@ -2,7 +2,6 @@ #include "gdcmFile.h" #include "gdcmUtil.h" -#include "iddcmjpeg.h" // for the 'LibIDO' Jpeg LossLess #include "jpeg/ljpg/jpegless.h" ///////////////////////////////////////////////////////////////// @@ -40,17 +39,16 @@ gdcmFile::gdcmFile(const char * filename) /** * \ingroup gdcmFile * \brief calcule la longueur (in bytes) A ALLOUER pour recevoir les - * pixels de l'image - * ou DES images dans le cas d'un multiframe - * ATTENTION : il ne s'agit PAS de la longueur du groupe des Pixels - * (dans le cas d'images compressees, elle n'a pas de sens). + * pixels de l'image ou DES images dans le cas d'un multiframe + * + * ATTENTION : il ne s'agit PAS de la longueur du groupe des Pixels + * (dans le cas d'images compressees, elle n'a pas de sens). * * @return longueur a allouer */ void gdcmFile::SetPixelDataSizeFromHeader(void) { int nb; std::string str_nb; - str_nb=gdcmHeader::GetPubElValByNumber(0x0028,0x0100); if (str_nb == GDCM_UNFOUND ) { nb = 16; @@ -58,12 +56,19 @@ void gdcmFile::SetPixelDataSizeFromHeader(void) { nb = atoi(str_nb.c_str() ); if (nb == 12) nb =16; } - lgrTotale = GetXSize() * GetYSize() * GetZSize() * (nb/8)* GetSamplesPerPixel(); - std::string str_PhotometricInterpretation = gdcmHeader::GetPubElValByNumber(0x0028,0x0004); - if ( str_PhotometricInterpretation == "PALETTE COLOR " ) { + lgrTotale = lgrTotaleRaw = GetXSize() * GetYSize() * GetZSize() + * (nb/8)* GetSamplesPerPixel(); + std::string str_PhotometricInterpretation = + gdcmHeader::GetPubElValByNumber(0x0028,0x0004); + + /*if ( str_PhotometricInterpretation == "PALETTE COLOR " )*/ + // pb when undealt Segmented Palette Color + + if (HasLUT()) { lgrTotale*=3; } } + // see PS 3.3-2003 : C.7.6.3.2.1 // // MONOCHROME1 @@ -85,17 +90,27 @@ void gdcmFile::SetPixelDataSizeFromHeader(void) { // 0028|1222 [OW] [Segmented Green Palette Color Lookup Table Data] // 0028|1223 [OW] [Segmented Blue Palette Color Lookup Table Data] - // ex : US-PAL-8-10x-echo.dcm, 8BitsRunLengthColor.dcm - // 0028|1201 [OW] [Red Palette Color Lookup Table Data] - // 0028|1202 [OW] [Green Palette Color Lookup Table Data] - // 0028|1203 [OW] [Blue Palette Color Lookup Table Data] - // ex : OT-PAL-8-face.dcm // 0028|1201 [US] [Red Palette Color Lookup Table Data] // 0028|1202 [US] [Green Palette Color Lookup Table Data] // 0028|1203 [US] [Blue Palette Color Lookup Table Data] +///////////////////////////////////////////////////////////////// +/** + * \ingroup gdcmFile + * \brief Returns the size (in bytes) of required memory to hold + * \ the pixel data represented in this file, when user DOESN'T want + * \ to get RGB pixels image when it's stored as a PALETTE COLOR image + * \ - the (vtk) user is supposed to know how deal with LUTs - + * \ warning to be used with GetImagePixelsRaw() + * @return The size of pixel data in bytes. + */ + +size_t gdcmFile::GetImageDataSizeRaw(void) { + return (lgrTotaleRaw); +} + ///////////////////////////////////////////////////////////////// /** * \ingroup gdcmFile @@ -126,8 +141,9 @@ bool gdcmFile::ReadPixelData(void* destination) { CloseFile(); return false; } - -// ------------------------- Compacted File (12 Bits Per Pixel) + + + // ---------------------- Compacted File (12 Bits Per Pixel) /* unpack 12 Bits pixels into 16 Bits pixels */ /* 2 pixels 12bit = [0xABCDEF] */ @@ -137,32 +153,32 @@ bool gdcmFile::ReadPixelData(void* destination) { int nbPixels = GetXSize()*GetYSize(); unsigned char b0, b1, b2; + unsigned short int* pdestination = (unsigned short int*)destination; for(int p=0;p> 4) << 8) + ((b0 & 0x0f) << 4) + (b1 & 0x0f); + //Two steps is necessary to please VC++ + *pdestination++ = ((b0 >> 4) << 8) + ((b0 & 0x0f) << 4) + (b1 & 0x0f); /* A */ /* B */ /* D */ - *((unsigned short int*)destination)++ = - ((b2 & 0x0f) << 8) + ((b1 >> 4) << 4) + (b2 >> 4); + *pdestination++ = ((b2 & 0x0f) << 8) + ((b1 >> 4) << 4) + (b2 >> 4); /* F */ /* C */ /* E */ // Troubles expected on Big-Endian processors ? } return(true); - } - + } -// ------------------------- Uncompressed File + // ---------------------- Uncompressed File if ( !IsDicomV3() || IsImplicitVRLittleEndianTransferSyntax() || IsExplicitVRLittleEndianTransferSyntax() || IsExplicitVRBigEndianTransferSyntax() || - IsDeflatedExplicitVRLittleEndianTransferSyntax() ) { - - size_t ItemRead = fread(destination, lgrTotale, 1, fp); + IsDeflatedExplicitVRLittleEndianTransferSyntax() ) { + + size_t ItemRead = fread(destination, GetPixelAreaLength(), 1, fp); + if ( ItemRead != 1 ) { CloseFile(); return false; @@ -171,8 +187,15 @@ bool gdcmFile::ReadPixelData(void* destination) { return true; } } + + // ---------------------- Run Length Encoding + + if (gdcmHeader::IsRLELossLessTransferSyntax()) { + int res = (bool)gdcm_read_RLE_file (destination); + return res; + } - // ------------------------ Compressed File . + // --------------- SingleFrame/Multiframe JPEG Lossless/Lossy/2000 int nb; std::string str_nb=gdcmHeader::GetPubElValByNumber(0x0028,0x0100); @@ -184,22 +207,11 @@ bool gdcmFile::ReadPixelData(void* destination) { } int nBytes= nb/8; - int taille = GetXSize() * GetYSize() * GetSamplesPerPixel(); - - - - // ---------------- RLE - - if (gdcmHeader::IsRLELossLessTransferSyntax()) { - int res = (bool)gdcm_read_RLE_file (destination); - return res; - } - - // ----------------- SingleFrame/Multiframe JPEG - + int taille = GetXSize() * GetYSize() * GetSamplesPerPixel(); long fragmentBegining; // for ftell, fseek - bool b = gdcmHeader::IsJPEG2000(); + bool jpg2000 = IsJPEG2000(); + bool jpgLossless = IsJPEGLossless(); bool res = true; guint16 ItemTagGr,ItemTagEl; @@ -243,39 +255,30 @@ bool gdcmFile::ReadPixelData(void* destination) { fragmentBegining=ftell(fp); - if (b) + if (jpg2000) { // JPEG 2000 : call to ??? + res = (bool)gdcm_read_JPEG2000_file (destination); // Not Yet written - - else if (IsJPEGLossless()) { // JPEG LossLess : call to xmedcom JPEG + + } // ------------------------------------- endif (JPEG2000) + + else if (jpgLossless) { // JPEG LossLess : call to xmedcom JPEG - JPEGLosslessDecodeImage (fp, + JPEGLosslessDecodeImage (fp, // Reading Fragment pixels (unsigned short *)destination, GetPixelSize()*8* GetSamplesPerPixel(), - ln); - + ln); res=1; // in order not to break the loop - } // ------------------------------------- endif (IsJPEGLossless()) + } // ------------------------------------- endif (JPEGLossless) - else { // JPEG Lossy : call to xmedcon JPEG - // (just to see if it works) --> it does NOT ! - /* - JPEGLosslessDecodeImage (fp, - (unsigned short *)destination, - GetPixelSize()*8* GetSamplesPerPixel(), - ln); - - */ - // JPEG Lossy : call to IJG 6b + else { // JPEG Lossy : call to IJG 6b if (GetBitsStored() == 8) { res = (bool)gdcm_read_JPEG_file (destination); // Reading Fragment pixels } else { res = (bool)gdcm_read_JPEG_file12 (destination);// Reading Fragment pixels } - - - } + } // ------------------------------------- endif (JPEGLossy) if (!res) break; @@ -302,6 +305,9 @@ bool gdcmFile::ReadPixelData(void* destination) { * \ingroup gdcmFile * \brief Allocates necessary memory, copies the pixel data * (image[s]/volume[s]) to newly allocated zone. + * Transforms YBR pixels into RGB pixels if any + Transforms 3 planes R, G, B into a single RGB Plane + Transforms single Grey plane + 3 Palettes into a RGB Plane * @return Pointer to newly allocated pixel data. * \ NULL if alloc fails */ @@ -312,10 +318,40 @@ void * gdcmFile::GetImageData (void) { return(PixelData); } +/** + * \ingroup gdcmFile + * \brief Allocates necessary memory, copies the pixel data + * (image[s]/volume[s]) to newly allocated zone. + * Transforms YBR pixels into RGB pixels if any + Transforms 3 planes R, G, B into a single RGB Plane + DOES NOT transform Grey plane + 3 Palettes into a RGB Plane + * @return Pointer to newly allocated pixel data. + * \ NULL if alloc fails + */ +void * gdcmFile::GetImageDataRaw (void) { + if (HasLUT()) + lgrTotale /= 3; // TODO Let gdcmHeadar user a chance + // to get the right value + // Create a member lgrTotaleRaw ??? + PixelData = (void *) malloc(lgrTotale); + if (PixelData) + GetImageDataIntoVectorRaw(PixelData, lgrTotale); + return(PixelData); +} + /** * \ingroup gdcmFile * \brief Copies at most MaxSize bytes of pixel data to caller's * memory space. + * \warning This function was designed to avoid people that want to build + * a volume from an image stack to need first to get the image pixels + * and then move them to the volume area. + * It's absolutely useless for any VTK user since vtk chooses + * to invert the lines of an image, that is the last line comes first + * (for some axis related reasons?). Hence he will have + * to load the image line by line, starting from the end. + * VTK users have to call GetImageData + * * @param destination Address (in caller's memory space) at which the * pixel data should be copied * @param MaxSize Maximum number of bytes to be copied. When MaxSize @@ -327,6 +363,92 @@ void * gdcmFile::GetImageData (void) { size_t gdcmFile::GetImageDataIntoVector (void* destination, size_t MaxSize) { + size_t l = GetImageDataIntoVectorRaw (destination, MaxSize); + + if (!HasLUT()) + return lgrTotale; + + // from Lut R + Lut G + Lut B + + unsigned char * newDest = (unsigned char *)malloc(lgrTotale); + unsigned char * a = (unsigned char *)destination; + unsigned char * lutRGBA = (unsigned char *)GetLUTRGBA(); + if (lutRGBA) { + int l = lgrTotaleRaw; + memmove(newDest, destination, l);// move Gray pixels to temp area + int j; + for (int i=0;i