X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src%2FgdcmPixelReadConvert.cxx;h=c776743a7560f13ba1189cbc141fbc9cfe013c12;hb=0bcc188c6d5185375f809253e8b9b97c856d2eac;hp=c8aec3dfaefcb0fb087fc9d7fd84ad327ba25578;hpb=1771b10b3f1a4d6f96ea1869fb005f0d48b62eda;p=gdcm.git diff --git a/src/gdcmPixelReadConvert.cxx b/src/gdcmPixelReadConvert.cxx index c8aec3df..c776743a 100644 --- a/src/gdcmPixelReadConvert.cxx +++ b/src/gdcmPixelReadConvert.cxx @@ -3,8 +3,8 @@ Program: gdcm Module: $RCSfile: gdcmPixelReadConvert.cxx,v $ Language: C++ - Date: $Date: 2007/09/04 13:14:33 $ - Version: $Revision: 1.119 $ + Date: $Date: 2007/09/17 12:18:25 $ + Version: $Revision: 1.123 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or @@ -35,7 +35,7 @@ namespace GDCM_NAME_SPACE { -//bool ReadMPEGFile (std::ifstream *fp, char *inputdata, size_t lenght); +//bool ReadMPEGFile (std::ifstream *fp, char *inputdata, size_t lenght); bool gdcm_read_JPEG2000_file (void* raw, char *inputdata, size_t inputlength); //----------------------------------------------------------------------------- @@ -70,7 +70,7 @@ PixelReadConvert::~PixelReadConvert() // Public /** * \brief Predicate to know whether the image[s] (once Raw) is RGB. - * \note See comments of \ref ConvertHandleColor + * \note See comments of ConvertHandleColor */ bool PixelReadConvert::IsRawRGB() { @@ -97,11 +97,11 @@ void PixelReadConvert::GrabInformationsFromFile( File *file, { BitsAllocated = 16; } - - else if (BitsAllocated > 8 && BitsAllocated < 16 && BitsAllocated != 12) + else if ( BitsAllocated > 8 && BitsAllocated < 16 && BitsAllocated != 12 ) { BitsAllocated = 16; - } + } + // Number of "Bits Stored", defaulted to number of "Bits Allocated" // when absent from the file. BitsStored = file->GetBitsStored(); @@ -154,13 +154,13 @@ void PixelReadConvert::GrabInformationsFromFile( File *file, } // cache whether this is a strange GE transfer syntax (which uses // a little endian transfer syntax for the header and a big endian - // transfer syntax for the pixel data). + // transfer syntax for the pixel data). IsPrivateGETransferSyntax = ( Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRBigEndianPrivateGE ); - IsMPEG = IsJPEG2000 = IsJPEGLS = IsJPEGLossy = IsJPEGLossless = IsRLELossless = false; + IsMPEG = IsJPEG2000 = IsJPEGLS = IsJPEGLossy = IsJPEGLossless = IsRLELossless = false; if (!IsRaw) - { + { while(true) { // mind the order : check the most usual first. @@ -208,7 +208,7 @@ void PixelReadConvert::GrabInformationsFromFile( File *file, // [Bin|Val]Entry occurence migth have been hindered (read simply NOT // loaded). Hence, we first try to obtain the LUTs data from the file // and when this fails we read the LUTs data directly from disk. - // \TODO Reading a [Bin|Val]Entry directly from disk is a kludge. + // \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. DataEntry::GetBinArea()) should force disk access from @@ -323,7 +323,7 @@ bool PixelReadConvert::ReadAndDecompressPixelData( std::ifstream *fp ) } if (remainingLength !=0 ) fp->read( raw, remainingLength); - + if ( fp->fail() || fp->eof()) { gdcmWarningMacro( "Reading of Raw pixel data failed." ); @@ -513,33 +513,60 @@ bool PixelReadConvert::ReadAndDecompressJPEGFile( std::ifstream *fp ) // jpeg2000 stream to use jasper: // I don't think we'll ever be able to deal with multiple fragments properly - unsigned long inputlength = 0; - JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment(); - while( jpegfrag ) - { + if( ZSize == 1 ) + { + unsigned long inputlength = 0; + JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment(); + while( jpegfrag ) + { inputlength += jpegfrag->GetLength(); jpegfrag = JPEGInfo->GetNextFragment(); - } - gdcmAssertMacro( inputlength != 0); - uint8_t *inputdata = new uint8_t[inputlength]; - char *pinputdata = (char*)inputdata; - jpegfrag = JPEGInfo->GetFirstFragment(); - while( jpegfrag ) - { + } + gdcmAssertMacro( inputlength != 0); + uint8_t *inputdata = new uint8_t[inputlength]; + char *pinputdata = (char*)inputdata; + jpegfrag = JPEGInfo->GetFirstFragment(); + while( jpegfrag ) + { fp->seekg( jpegfrag->GetOffset(), std::ios::beg); fp->read(pinputdata, jpegfrag->GetLength()); pinputdata += jpegfrag->GetLength(); jpegfrag = JPEGInfo->GetNextFragment(); - } - // Warning the inputdata buffer is delete in the function - if ( ! gdcm_read_JPEG2000_file( Raw, - (char*)inputdata, inputlength ) ) - { + } + // Warning the inputdata buffer is deleted in the function + if ( gdcm_read_JPEG2000_file( Raw, + (char*)inputdata, inputlength ) ) + { return true; - } - // wow what happen, must be an error - gdcmWarningMacro( "gdcm_read_JPEG2000_file() failed "); - return false; + } + // wow what happen, must be an error + gdcmWarningMacro( "gdcm_read_JPEG2000_file() failed "); + return false; + } + else + { + if( (unsigned int)ZSize != JPEGInfo->GetFragmentCount() ) + { + gdcmErrorMacro( "Sorry GDCM does not handle this type of fragments" ); + return false; + } + // Hopefully every dicom fragment is *exactly* the j2k stream + JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment(); + char *praw = (char*)Raw; + while( jpegfrag ) + { + unsigned long inputlength = jpegfrag->GetLength(); + char *inputdata = new char[inputlength]; + fp->seekg( jpegfrag->GetOffset(), std::ios::beg); + fp->read(inputdata, jpegfrag->GetLength()); + // Warning the inputdata buffer is deleted in the function + gdcm_read_JPEG2000_file( praw, + inputdata, inputlength) ; + praw += XSize*YSize*SamplesPerPixel*(BitsAllocated/8); + jpegfrag = JPEGInfo->GetNextFragment(); + } + return true; + } } else if ( IsJPEGLS ) { @@ -594,15 +621,14 @@ bool PixelReadConvert::ReadAndDecompressJPEGFile( std::ifstream *fp ) // Precompute the offset localRaw will be shifted with int length = XSize * YSize * ZSize * SamplesPerPixel; int numberBytes = BitsAllocated / 8; - + // to avoid major troubles when BitsStored == 8 && BitsAllocated==16 ! int dummy; if (BitsStored == 8 && BitsAllocated==16) dummy = 16; else dummy = BitsStored; - - JPEGInfo->DecompressFromFile(fp, Raw, /*BitsStored*/ dummy , numberBytes, length ); + JPEGInfo->DecompressFromFile(fp, Raw, dummy, numberBytes, length ); return true; } } @@ -845,7 +871,7 @@ void PixelReadConvert::BuildLUTRGBA() } /** - * \brief Swap the bytes, according to \ref SwapCode. + * \brief Swap the bytes, according to SwapCode. */ void PixelReadConvert::ConvertSwapZone() { @@ -976,7 +1002,6 @@ void PixelReadConvert::ConvertReorderEndianity() && BitsStored < BitsAllocated && !PixelSign ) { - int l = (int)( RawSize / ( BitsAllocated / 8 ) ); int l = (int)( RawSize / ( BitsAllocated / 8 ) ); uint16_t *deb = (uint16_t *)Raw; for(int i = 0; i> ( BitsAllocated - BitsStored ); + + // It's up to the user to decide if he wants to ignore overlays (if any), + // not to gdcm, without asking. + // default is NOT TO LOAD, in order not to confuse ITK users (and others!). + + if ( !FH->GetKeepOverlays() ) // mask spurious bits ! (overlay are NOT loaded!) + { + pmask = pmask >> ( BitsAllocated - BitsStored ); + } + // else : it's up to the user to manage the 'pixels + overlays' he just loaded! uint16_t *deb = (uint16_t*)Raw; @@ -1084,22 +1115,21 @@ bool PixelReadConvert::ConvertReArrangeBits() throw ( FormatError ) { for(int i = 0; i> (BitsStored - HighBitPosition - 1))/* & pmask */; + *deb = (*deb >> (BitsStored - HighBitPosition - 1)) & pmask; deb++; } } else // Pixels are signed { - // Hope there is never A - + // Hope there is never ACR-NEMA-like overlays within signed pixels (?!?) + // smask : to check the 'sign' when BitsStored != BitsAllocated uint16_t smask = 0x0001; smask = smask << ( 16 - (BitsAllocated - BitsStored + 1) ); // nmask : to propagate sign bit on negative values int16_t nmask = (int16_t)0x8000; nmask = nmask >> ( BitsAllocated - BitsStored - 1 ); - + for(int i = 0; i> (BitsStored - HighBitPosition - 1); @@ -1117,17 +1147,10 @@ bool PixelReadConvert::ConvertReArrangeBits() throw ( FormatError ) } else if ( BitsAllocated == 32 ) { - } - deb++; - } - } - } - else if ( BitsAllocated == 32 ) - { // pmask : to mask the 'unused bits' (may contain overlays) uint32_t pmask = 0xffffffff; pmask = pmask >> ( BitsAllocated - BitsStored ); - + uint32_t *deb = (uint32_t*)Raw; if ( !PixelSign ) @@ -1152,8 +1175,8 @@ bool PixelReadConvert::ConvertReArrangeBits() throw ( FormatError ) *deb = *deb >> (BitsStored - HighBitPosition - 1); if ( *deb & smask ) *deb = *deb | nmask; - else - *deb = *deb & pmask; + else + *deb = *deb & pmask; deb++; } } @@ -1208,9 +1231,9 @@ void PixelReadConvert::ConvertYcBcRPlanesToRGBPixels() // except for the few patches of color on the image. // On such images, RLE achieves a compression ratio that is much better // than the compression ratio on an equivalent RGB image. - + gdcmWarningMacro("--> ConvertYcBcRPlanesToRGBPixels"); - + uint8_t *localRaw = Raw; uint8_t *copyRaw = new uint8_t[ RawSize ]; memmove( copyRaw, localRaw, RawSize ); @@ -1220,7 +1243,7 @@ void PixelReadConvert::ConvertYcBcRPlanesToRGBPixels() // ftp://medical.nema.org/medical/dicom/final/sup61_ft.pdf // and be *very* affraid // - + /// \todo : find an example to see how 3rd dim and 4th dim work together int l = XSize * YSize * TSize; int nbFrames = ZSize; @@ -1356,7 +1379,7 @@ void PixelReadConvert::ComputeRawAndRGBSizes() int bitsAllocated = BitsAllocated; // Number of "Bits Allocated" is fixed to 16 when it's 12, since // in this case we will expand the image to 16 bits (see - // \ref ReadAndDecompress12BitsTo16Bits() ) + // ReadAndDecompress12BitsTo16Bits() ) if ( BitsAllocated == 12 ) { bitsAllocated = 16; @@ -1372,7 +1395,6 @@ void PixelReadConvert::ComputeRawAndRGBSizes() else { RGBSize = RawSize; - } RawSize += RawSize%2; RGBSize += RGBSize%2; @@ -1465,7 +1487,6 @@ void PixelReadConvert::CallEndMethod() CommandManager::ExecuteCommand(FH,CMD_ENDPROGRESS); } - //----------------------------------------------------------------------------- } // end namespace gdcm @@ -1546,6 +1567,13 @@ of 12 for the third value and a max of 0xfff). Since almost every vendor that I have encountered that encodes LUTs makes this mistake, perhaps it is time to amend the standard to warn +implementor's of receivers and/or sanction this bad behavior. We have +talked about this in the past in WG 6 but so far everyone has been +reluctant to write into the standard such a comment. Maybe it is time +to try again, since if one is not aware of this problem, one cannot +effectively implement display using VOI LUTs, and there is a vast +installed base to contend with. + I did not check presentation states, in which VOI LUTs could also be encountered, for the prevalence of this mistake, nor did I look at the encoding of Modality LUT's, which are unusual. Nor did I check digital