+2004-10-10 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+ * CLEANUP_ROUND (10) for gdcmPixelConvert (Xanax is my friend stage)
+ The JPEG fragments are now parsed at the same stage than the RLE
+ information. All code related to JPEG is now in gdcmPixelConvert:
+ - src/gdcmJPEGFragment.h and gdcmJPEGFragmentsInfo.[h|cxx] added
+ - src/gdcmJpeg12.cxx, gdcmJpeg2000.cxx and gdcmJpeg8.cxx no longer
+ export a gdcmFile:: method. This are simply global functions
+ (for the time being this is better than having them attach to
+ either gdcmFile:: or gdcmPixelConvert::).
+ - src/gdcmDocument.[cxx|h], gdcmDocument:: now parser the JPEG fragments
+ and stores the result in a gdcmJPEGFragmentsInfo.
+ - src/gdcmFile.[cxx|h] and gdcmPixelConvert.[cxx|h]: all JPEG related
+ code (among other stuff) moved away from gdcmFile:; to
+ gdcmPixelConvert::
+
2004-10-08 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
* src/gdcmCommon.h now declares int8_t for non stdint.h plateforms.
* CLEANUP_ROUND (7) for gdcmPixelConvert (lost at sea)
- src/gdcmFile.[cxx|h} gdcmPixelConvert.[cxx|h], SwapZone(),
ConvertReorderEndianity(), ConvertDecmpres12BitsTo16Bits() moved
away from gdcmFile:: to gdcmPixelConvert::.
-
2004-10-07 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
* CLEANUP_ROUND (5) for gdcmPixelConvert (Upshit creek without a paddle)
long long -> int64_t;
Hence do not use declarations like "unsigned int".
With g++, accessing those typedef is achieved by the following
- #include <stdint.h>
+ #include < stdint.h >
</PRE>
gdcmGlobal.cxx
gdcmHeader.cxx
gdcmHeaderHelper.cxx
+ gdcmJPEGFragmentsInfo.cxx
gdcmJpeg8.cxx
gdcmJpeg12.cxx
gdcmJpeg2000.cxx
Program: gdcm
Module: $RCSfile: gdcmDocument.cxx,v $
Language: C++
- Date: $Date: 2004/10/10 03:03:10 $
- Version: $Revision: 1.101 $
+ Date: $Date: 2004/10/10 16:43:59 $
+ Version: $Revision: 1.102 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
}
/**
- * \brief Determines if the Transfer Syntax corresponds to encapsulated
- * of encoded Pixel Data (as opposed to native).
- * @return True when encapsulated. False when native.
+ * \brief Determines if the Transfer Syntax corresponds to any form
+ * of Jpeg encoded Pixel data.
+ * @return True when any form of JPEG found. False otherwise.
*/
-bool gdcmDocument::IsEncapsulateTransferSyntax()
+bool gdcmDocument::IsJPEGTransferSyntax()
{
return ( IsJPEGBaseLineProcess1TransferSyntax()
|| IsJPEGExtendedProcess2_4TransferSyntax()
|| IsJPEGExtendedProcess3_5TransferSyntax()
|| IsJPEGSpectralSelectionProcess6_8TransferSyntax()
- || IsRLELossLessTransferSyntax()
|| IsJPEGLossless()
|| IsJPEG2000() );
}
+
+/**
+ * \brief Determines if the Transfer Syntax corresponds to encapsulated
+ * of encoded Pixel Data (as opposed to native).
+ * @return True when encapsulated. False when native.
+ */
+bool gdcmDocument::IsEncapsulateTransferSyntax()
+{
+ return ( IsJPEGTransferSyntax()
+ || IsRLELossLessTransferSyntax() );
+}
+
/**
* \brief Predicate for dicom version 3 file.
* @return True when the file is a dicom version 3.
gdcmVRKey vr = valEntry->GetVR();
if( vr == "US" || vr == "SS" )
{
- c = gdcmUtil::CountSubstring(content, "\\") + 1; // for multivaluated items
+ // for multivaluated items
+ c = gdcmUtil::CountSubstring(content, "\\") + 1;
l = c*2;
}
else if( vr == "UL" || vr == "SL" )
{
- c = gdcmUtil::CountSubstring(content, "\\") + 1; // for multivaluated items
+ // for multivaluated items
+ c = gdcmUtil::CountSubstring(content, "\\") + 1;
l = c*4;;
}
}
LoadDocEntry( newBinEntry );
}
- if (newDocEntry->GetGroup() == 0x7fe0 &&
- newDocEntry->GetElement() == 0x0010 )
+ if ( ( newDocEntry->GetGroup() == 0x7fe0 )
+ && ( newDocEntry->GetElement() == 0x0010 ) )
{
if ( IsRLELossLessTransferSyntax() )
{
long PositionOnEntry = ftell(Fp);
- fseek(Fp, newDocEntry->GetOffset(), SEEK_SET);
+ fseek( Fp, newDocEntry->GetOffset(), SEEK_SET );
ComputeRLEInfo();
- fseek(Fp, PositionOnEntry, SEEK_SET);
+ fseek( Fp, PositionOnEntry, SEEK_SET );
}
- else
+ else
+ if ( IsJPEGTransferSyntax() )
{
- SkipToNextDocEntry(newDocEntry);
+ long PositionOnEntry = ftell(Fp);
+ fseek( Fp, newDocEntry->GetOffset(), SEEK_SET );
+ ComputeJPEGFragmentInfo();
+ fseek( Fp, PositionOnEntry, SEEK_SET );
}
}
- else
- {
- // to be sure we are at the beginning
- SkipToNextDocEntry(newDocEntry);
- }
+
+ // Just to make sure we are at the beginning of next entry.
+ SkipToNextDocEntry(newDocEntry);
}
else
{
}
/**
- * \brief Parse pixel data from disk of [multi-]fragment RLE encoding.
- * Compute the RLE extra information and store it in \ref RLEInfo
- * for later pixel retrieval usage.
+ * \brief When parsing the Pixel Data of an encapsulated file, read
+ * the basic offset table (when present, and BTW dump it).
*/
-void gdcmDocument::ComputeRLEInfo()
+void gdcmDocument::ReadAndSkipEncapsulatedBasicOffsetTable()
{
- if ( ! IsRLELossLessTransferSyntax() )
- {
- return;
- }
- // Encoded pixel data: for the time being we are only concerned with
- // Jpeg or RLE Pixel data encodings.
- // As stated in PS 3.5-2003, section 8.2 p44:
- // "If sent in Encapsulated Format (i.e. other than the Native Format) the
- // value representation OB is used".
- // Hence we expect an OB value representation. Concerning OB VR,
- // the section PS 3.5-2003, section A.4.c p 58-59, states:
- // "For the Value Representations OB and OW, the encoding shall meet the
- // following specifications depending on the Data element tag:"
- // [...snip...]
- // - the first item in the sequence of items before the encoded pixel
- // data stream shall be basic offset table item. The basic offset table
- // item value, however, is not required to be present"
-
//// Read the Basic Offset Table Item Tag length...
uint32_t itemLength = ReadTagLength(0xfffe, 0xe000);
char* basicOffsetTableItemValue = new char[itemLength + 1];
fread(basicOffsetTableItemValue, itemLength, 1, Fp);
+#ifdef GDCM_DEBUG
for (unsigned int i=0; i < itemLength; i += 4 )
{
uint32_t individualLength = str2num( &basicOffsetTableItemValue[i],
std::ostringstream s;
s << " Read one length: ";
s << std::hex << individualLength << std::endl;
- dbg.Verbose(0, "gdcmDocument::ComputeRLEInfo: ", s.str().c_str());
+ dbg.Verbose(0,
+ "gdcmDocument::ReadAndSkipEncapsulatedBasicOffsetTable: ",
+ s.str().c_str());
}
+#endif //GDCM_DEBUG
+
delete[] basicOffsetTableItemValue;
}
+}
- // Encapsulated RLE Compressed Images (see PS 3.5-2003, Annex G)
- // Loop on the frame[s] and store the parsed information in a
- // gdcmRLEFramesInfo.
- long frameLength;
+/**
+ * \brief Parse pixel data from disk of [multi-]fragment RLE encoding.
+ * Compute the RLE extra information and store it in \ref RLEInfo
+ * for later pixel retrieval usage.
+ */
+void gdcmDocument::ComputeRLEInfo()
+{
+ if ( ! IsRLELossLessTransferSyntax() )
+ {
+ return;
+ }
+
+ // Encoded pixel data: for the time being we are only concerned with
+ // Jpeg or RLE Pixel data encodings.
+ // As stated in PS 3.5-2003, section 8.2 p44:
+ // "If sent in Encapsulated Format (i.e. other than the Native Format) the
+ // value representation OB is used".
+ // Hence we expect an OB value representation. Concerning OB VR,
+ // the section PS 3.5-2003, section A.4.c p 58-59, states:
+ // "For the Value Representations OB and OW, the encoding shall meet the
+ // following specifications depending on the Data element tag:"
+ // [...snip...]
+ // - the first item in the sequence of items before the encoded pixel
+ // data stream shall be basic offset table item. The basic offset table
+ // item value, however, is not required to be present"
+
+ ReadAndSkipEncapsulatedBasicOffsetTable();
+ // Encapsulated RLE Compressed Images (see PS 3.5-2003, Annex G)
// Loop on the individual frame[s] and store the information
// on the RLE fragments in a gdcmRLEFramesInfo.
// Note: - when only a single frame is present, this is a
// classical image.
// - when more than one frame are present, then we are in
// the case of a multi-frame image.
+ long frameLength;
while ( (frameLength = ReadTagLength(0xfffe, 0xe000)) )
{
// Parse the RLE Header and store the corresponding RLE Segment
}
}
+/**
+ * \brief Parse pixel data from disk of [multi-]fragment Jpeg encoding.
+ * Compute the jpeg extra information (fragment[s] offset[s] and
+ * length) and store it[them] in \ref JPEGInfo for later pixel
+ * retrieval usage.
+ */
+void gdcmDocument::ComputeJPEGFragmentInfo()
+{
+ // If you need to, look for comments of ComputeRLEInfo().
+ if ( ! IsJPEGTransferSyntax() )
+ {
+ return;
+ }
+
+ ReadAndSkipEncapsulatedBasicOffsetTable();
+
+ // Loop on the fragments[s] and store the parsed information in a
+ // gdcmJPEGInfo.
+ long fragmentLength;
+ while ( (fragmentLength = ReadTagLength(0xfffe, 0xe000)) )
+ {
+ long fragmentOffset = ftell(Fp);
+
+ // Store the collected info
+ gdcmJPEGFragment* newFragment = new gdcmJPEGFragment;
+ newFragment->Offset = fragmentOffset;
+ newFragment->Length = fragmentLength;
+ JPEGInfo.Fragments.push_back( newFragment );
+
+ SkipBytes( fragmentLength );
+ }
+
+ // Make sure that at the end of the item we encounter a 'Sequence
+ // Delimiter Item':
+ if ( !ReadTag(0xfffe, 0xe0dd) )
+ {
+ dbg.Verbose(0, "gdcmDocument::ComputeRLEInfo: no sequence delimiter ");
+ dbg.Verbose(0, " item at end of JPEG item sequence");
+ }
+}
+
/**
* \brief Walk recursively the given \ref gdcmDocEntrySet, and feed
* the given hash table (\ref TagDocEntryHT) with all the
Program: gdcm
Module: $RCSfile: gdcmDocument.h,v $
Language: C++
- Date: $Date: 2004/10/09 03:36:57 $
- Version: $Revision: 1.48 $
+ Date: $Date: 2004/10/10 16:44:00 $
+ Version: $Revision: 1.49 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
#include "gdcmDictSet.h"
#include "gdcmDocEntry.h"
#include "gdcmRLEFramesInfo.h"
+#include "gdcmJPEGFragmentsInfo.h"
#include "gdcmDocEntrySet.h"
#include "gdcmElementSet.h"
/// Store the RLE frames info obtained during parsing of pixels.
gdcmRLEFramesInfo RLEInfo;
+ /// Store the JPEG fragments info obtained during parsing of pixels.
+ gdcmJPEGFragmentsInfo JPEGInfo;
+
/// \brief Amount of printed details for each Header Entry (Dicom Element):
/// 0 : stands for the least detail level.
int PrintLevel;
bool IsExplicitVRLittleEndianTransferSyntax();
bool IsDeflatedExplicitVRLittleEndianTransferSyntax();
bool IsExplicitVRBigEndianTransferSyntax();
+ bool IsRLELossLessTransferSyntax();
bool IsJPEGBaseLineProcess1TransferSyntax();
bool IsJPEGExtendedProcess2_4TransferSyntax();
bool IsJPEGExtendedProcess3_5TransferSyntax();
bool IsJPEGSpectralSelectionProcess6_8TransferSyntax();
- bool IsRLELossLessTransferSyntax();
bool IsJPEGLossless();
bool IsJPEG2000();
+ bool IsJPEGTransferSyntax();
bool IsEncapsulateTransferSyntax();
bool IsDicomV3();
gdcmDocument( std::string const & filename );
virtual ~gdcmDocument();
+ void ReadAndSkipEncapsulatedBasicOffsetTable();
void ComputeRLEInfo();
+ void ComputeJPEGFragmentInfo();
// Entry
bool CheckIfEntryExistByNumber(uint16_t group, uint16_t elem );
public:
Program: gdcm
Module: $RCSfile: gdcmFile.cxx,v $
Language: C++
- Date: $Date: 2004/10/08 17:24:54 $
- Version: $Revision: 1.137 $
+ Date: $Date: 2004/10/10 16:44:00 $
+ Version: $Revision: 1.138 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
#include "gdcmFile.h"
#include "gdcmDebug.h"
#include "gdcmPixelConvert.h"
-#include "jpeg/ljpg/jpegless.h"
typedef std::pair<TagDocEntryHT::iterator,TagDocEntryHT::iterator> IterHT;
bool signedPixel = Header->IsSignedPixelData();
gdcmPixelConvert::ConvertReorderEndianity(
- (uint8_t*) destination,
- ImageDataSize,
- numberBitsStored,
- numberBitsAllocated,
- Header->GetSwapCode(),
- signedPixel );
-
- ConvertReArrangeBits( (uint8_t*) destination,
+ (uint8_t*) destination,
+ ImageDataSize,
+ numberBitsStored,
+ numberBitsAllocated,
+ Header->GetSwapCode(),
+ signedPixel );
+
+ gdcmPixelConvert::ConvertReArrangeBits(
+ (uint8_t*) destination,
ImageDataSize,
numberBitsStored,
numberBitsAllocated,
return ImageDataSize;
}
-/**
- * \brief Re-arrange the bits within the bytes.
- */
-void gdcmFile::ConvertReArrangeBits( uint8_t* pixelZone,
- size_t imageDataSize,
- int numberBitsStored,
- int numberBitsAllocated,
- int highBitPosition)
- throw ( gdcmFormatError )
-{
- if ( numberBitsStored != numberBitsAllocated )
- {
- int l = (int)(imageDataSize / (numberBitsAllocated/8));
- if ( numberBitsAllocated == 16 )
- {
- uint16_t mask = 0xffff;
- mask = mask >> ( numberBitsAllocated - numberBitsStored );
- uint16_t* deb = (uint16_t*)pixelZone;
- for(int i = 0; i<l; i++)
- {
- *deb = (*deb >> (numberBitsStored - highBitPosition - 1)) & mask;
- deb++;
- }
- }
- else if ( numberBitsAllocated == 32 )
- {
- uint32_t mask = 0xffffffff;
- mask = mask >> ( numberBitsAllocated - numberBitsStored );
- uint32_t* deb = (uint32_t*)pixelZone;
- for(int i = 0; i<l; i++)
- {
- *deb = (*deb >> (numberBitsStored - highBitPosition - 1)) & mask;
- deb++;
- }
- }
- else
- {
- dbg.Verbose(0, "gdcmFile::ConvertReArrangeBits: weird image");
- throw gdcmFormatError( "gdcmFile::ConvertReArrangeBits()",
- "weird image !?" );
- }
- }
-}
-
/**
* \brief Convert (Y plane, cB plane, cR plane) to RGB pixels
* \warning Works on all the frames at a time
// ---------------------- Run Length Encoding
if ( Header->IsRLELossLessTransferSyntax() )
{
- bool res = gdcmPixelConvert::gdcm_read_RLE_file ( destination,
+ bool res = gdcmPixelConvert::ReadAndDecompressRLEFile(
+ destination,
Header->GetXSize(),
Header->GetYSize(),
Header->GetZSize(),
numberBitsAllocated = 16;
}
- int nBytes= numberBitsAllocated/8;
- int taille = Header->GetXSize() * Header->GetYSize()
- * Header->GetSamplesPerPixel();
- long fragmentBegining; // for ftell, fseek
-
- bool jpg2000 = Header->IsJPEG2000();
- bool jpgLossless = Header->IsJPEGLossless();
-
- bool res = true;
- uint16_t ItemTagGr, ItemTagEl;
- int ln;
-
- // Position on begining of Jpeg Pixels
-
- fread(&ItemTagGr,2,1,fp); // Reading (fffe) : Item Tag Gr
- fread(&ItemTagEl,2,1,fp); // Reading (e000) : Item Tag El
- if(Header->GetSwapCode())
- {
- ItemTagGr = Header->SwapShort(ItemTagGr);
- ItemTagEl = Header->SwapShort(ItemTagEl);
- }
-
- fread(&ln,4,1,fp);
- if( Header->GetSwapCode() )
- {
- ln = Header->SwapLong( ln ); // Basic Offset Table Item length
- }
-
- if ( ln != 0 )
- {
- // What is it used for ?!?
- uint8_t* BasicOffsetTableItemValue = new uint8_t[ln+1];
- fread(BasicOffsetTableItemValue,ln,1,fp);
- //delete[] BasicOffsetTableItemValue;
- }
-
- // first Fragment initialisation
- fread(&ItemTagGr,2,1,fp); // Reading (fffe) : Item Tag Gr
- fread(&ItemTagEl,2,1,fp); // Reading (e000) : Item Tag El
- if( Header->GetSwapCode() )
- {
- ItemTagGr = Header->SwapShort( ItemTagGr );
- ItemTagEl = Header->SwapShort( ItemTagEl );
- }
-
- // parsing fragments until Sequence Delim. Tag found
- while ( ItemTagGr == 0xfffe && ItemTagEl != 0xe0dd )
- {
- // --- for each Fragment
- fread(&ln,4,1,fp);
- if( Header->GetSwapCode() )
- {
- ln = Header->SwapLong(ln); // Fragment Item length
- }
- fragmentBegining = ftell( fp );
-
- if ( jpg2000 )
- {
- // JPEG 2000 : call to ???
- res = gdcm_read_JPEG2000_file (fp,destination); // Not Yet written
- // ------------------------------------- endif (JPEG2000)
- }
- else if (jpgLossless)
- {
- // JPEG LossLess : call to xmedcom Lossless JPEG
- // Reading Fragment pixels
- JPEGLosslessDecodeImage (fp, (uint16_t*)destination,
- Header->GetPixelSize() * 8 * Header->GetSamplesPerPixel(), ln);
- res = 1; // in order not to break the loop
-
- } // ------------------------------------- endif (JPEGLossless)
- else
- {
- // JPEG Lossy : call to IJG 6b
- if ( Header->GetBitsStored() == 8)
- {
- // Reading Fragment pixels
- res = gdcm_read_JPEG_file (fp,destination);
- }
- else if ( Header->GetBitsStored() == 12)
- {
- // Reading Fragment pixels
- res = gdcm_read_JPEG_file12 (fp,destination);
- }
- else
- {
- // other JPEG lossy not supported
- dbg.Error(" gdcmFile::ReadPixelData : unknown jpeg lossy compression");
- return 0;
- }
- // ------------------------------------- endif (JPEGLossy)
- }
-
- if ( !res )
- {
- break;
- }
-
- // location in user's memory
- // for next fragment (if any)
- destination = (uint8_t*)destination + taille * nBytes;
-
- fseek(fp,fragmentBegining, SEEK_SET); // To be sure we start
- fseek(fp,ln,SEEK_CUR); // at the begining of next fragment
-
- ItemTagGr = ItemTagEl = 0;
- fread(&ItemTagGr,2,1,fp); // Reading (fffe) : Item Tag Gr
- fread(&ItemTagEl,2,1,fp); // Reading (e000) : Item Tag El
- if( Header->GetSwapCode() )
- {
- ItemTagGr = Header->SwapShort( ItemTagGr );
- ItemTagEl = Header->SwapShort( ItemTagEl );
- }
- }
- // endWhile parsing fragments until Sequence Delim. Tag found
-
+ bool res = gdcmPixelConvert::ReadAndDecompressJPEGFile(
+ (uint8_t*)destination,
+ Header->GetXSize(),
+ Header->GetYSize(),
+ Header->GetBitsAllocated(),
+ Header->GetBitsStored(),
+ Header->GetSamplesPerPixel(),
+ Header->GetPixelSize(),
+ Header->IsJPEG2000(),
+ Header->IsJPEGLossless(),
+ &(Header->JPEGInfo),
+ fp );
Header->CloseFile();
return res;
}
Program: gdcm
Module: $RCSfile: gdcmFile.h,v $
Language: C++
- Date: $Date: 2004/10/08 17:02:53 $
- Version: $Revision: 1.58 $
+ Date: $Date: 2004/10/10 16:44:00 $
+ Version: $Revision: 1.59 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
void ConvertRGBPlanesToRGBPixels( uint8_t* source, uint8_t* destination );
void ConvertYcBcRPlanesToRGBPixels( uint8_t* source, uint8_t* destination );
- void ConvertReArrangeBits(
- uint8_t* pixelZone,
- size_t imageDataSize,
- int numberBitsStored,
- int numberBitsAllocated,
- int highBitPosition ) throw ( gdcmFormatError );
/// Accessor to \ref ImageDataSize
size_t GetImageDataSize(){ return ImageDataSize; };
bool ReadPixelData(void* destination);
// For JPEG 8 Bits, body in file gdcmJpeg.cxx
- bool gdcm_read_JPEG_file (FILE* fp, void* image_buffer);
bool gdcm_write_JPEG_file (FILE* fp, void* image_buffer,
int image_width, int image_heigh,
int quality);
// For JPEG 12 Bits, body in file gdcmJpeg12.cxx
- bool gdcm_read_JPEG_file12 (FILE* fp, void* image_buffer);
bool gdcm_write_JPEG_file12 (FILE* fp, void* image_buffer,
int image_width, int image_height,
int quality);
- // For JPEG 2000, body in file gdcmJpeg2000.cxx
- bool gdcm_read_JPEG2000_file (FILE* fp, void* image_buffer);
-
void SaveInitialValues(); // will belong to the future gdcmPixelData class
void RestoreInitialValues(); // will belong to the future gdcmPixelData class
void DeleteInitialValues(); // will belong to the future gdcmPixelData class
--- /dev/null
+/*=========================================================================
+
+ Program: gdcm
+ Module: $RCSfile: gdcmJPEGFragment.h,v $
+ Language: C++
+ Date: $Date: 2004/10/10 16:44:00 $
+ Version: $Revision: 1.1 $
+
+ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+ l'Image). All rights reserved. See Doc/License.txt or
+ http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the above copyright notices for more information.
+
+=========================================================================*/
+
+
+#ifndef GDCMJPEGFRAGMENT_H
+#define GDCMJPEGFRAGMENT_H
+
+#include "gdcmCommon.h"
+
+/**
+ * \brief Utility class for summerizing the informations of a JPEG
+ * fragment of an "Encapsulated JPEG Compressed Image".
+ * This information is a mix of:
+ * - the fragment offset
+ * - the fragment length
+ *
+ * Each instance of this class (they can be as many instances for
+ * a given gdcmDocument as they are JPEG fragments and they are
+ * collected in a \ref gdcmJPEGFragmentsInfo )
+ */
+class GDCM_EXPORT gdcmJPEGFragment
+{
+friend class gdcmDocument;
+friend class gdcmFile;
+friend class gdcmPixelConvert;
+ long Offset;
+ long Length;
+ gdcmJPEGFragment()
+ {
+ Offset = 0;
+ Length = 0;
+ }
+};
+
+//-----------------------------------------------------------------------------
+#endif
--- /dev/null
+/*=========================================================================
+
+ Program: gdcm
+ Module: $RCSfile: gdcmJPEGFragmentsInfo.cxx,v $
+ Language: C++
+ Date: $Date: 2004/10/10 16:44:00 $
+ Version: $Revision: 1.1 $
+
+ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+ l'Image). All rights reserved. See Doc/License.txt or
+ http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the above copyright notices for more information.
+
+=========================================================================*/
+
+#include "gdcmJPEGFragmentsInfo.h"
+
+gdcmJPEGFragmentsInfo::~gdcmJPEGFragmentsInfo()
+{
+ for(JPEGFragmentsList::iterator it = Fragments.begin();
+ it != Fragments.end();
+ ++it )
+ {
+ delete (*it);
+ }
+ Fragments.clear();
+}
--- /dev/null
+/*=========================================================================
+
+ Program: gdcm
+ Module: $RCSfile: gdcmJPEGFragmentsInfo.h,v $
+ Language: C++
+ Date: $Date: 2004/10/10 16:44:00 $
+ Version: $Revision: 1.1 $
+
+ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+ l'Image). All rights reserved. See Doc/License.txt or
+ http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE. See the above copyright notices for more information.
+
+=========================================================================*/
+
+
+#ifndef GDCMJPEGFRAGMENTSINFO_H
+#define GDCMJPEGFRAGMENTSINFO_H
+
+#include "gdcmJPEGFragment.h"
+#include <list>
+
+/**
+ * \brief Utility class for gathering the informations of the collection
+ * of JPEG fragment[s] (see \ref gdcmJPEGFragment) when handling
+ * "Encapsulated JPEG Compressed Images".
+ * The informations on each frame are obtained during the parsing
+ * of a gdcmDocument (refer to
+ * \ref gdcmDocument::ComputeJPEGFragmentInfo() ).
+ * They shall be used when (if necessary) decoding the fragments.
+ *
+ * This class is simply a stl list<> of \ref gdcmJPEGFragment.
+ */
+class GDCM_EXPORT gdcmJPEGFragmentsInfo
+{
+ typedef std::list< gdcmJPEGFragment* > JPEGFragmentsList;
+friend class gdcmDocument;
+friend class gdcmFile;
+friend class gdcmPixelConvert;
+ JPEGFragmentsList Fragments;
+public:
+ ~gdcmJPEGFragmentsInfo();
+};
+
+//-----------------------------------------------------------------------------
+#endif
Program: gdcm
Module: $RCSfile: gdcmJpeg12.cxx,v $
Language: C++
- Date: $Date: 2004/10/10 00:42:55 $
- Version: $Revision: 1.19 $
+ Date: $Date: 2004/10/10 16:44:00 $
+ Version: $Revision: 1.20 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
* @return 1 on success, 0 on error
*/
-bool gdcmFile::gdcm_read_JPEG_file12 (FILE* fp,void* image_buffer)
+bool gdcm_read_JPEG_file12 ( FILE* fp,void* image_buffer )
{
char *pimage;
Program: gdcm
Module: $RCSfile: gdcmJpeg2000.cxx,v $
Language: C++
- Date: $Date: 2004/10/08 04:52:55 $
- Version: $Revision: 1.10 $
+ Date: $Date: 2004/10/10 16:44:00 $
+ Version: $Revision: 1.11 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
//-----------------------------------------------------------------------------
/**
- * \ingroup gdcmFile
* \brief routine for JPEG decompression
* @param fp pointer to an already open file descriptor
* JPEG2000 encoded image
* @warning : not yet made
*/
-bool gdcmFile::gdcm_read_JPEG2000_file (FILE* fp,void* image_buffer) {
+bool gdcm_read_JPEG2000_file (FILE* fp,void* image_buffer) {
(void)fp; //FIXME
(void)image_buffer; //FIXME
std::cout << "Sorry JPEG 2000 File not yet taken into account" << std::endl;
Program: gdcm
Module: $RCSfile: gdcmJpeg8.cxx,v $
Language: C++
- Date: $Date: 2004/10/10 00:42:55 $
- Version: $Revision: 1.4 $
+ Date: $Date: 2004/10/10 16:44:00 $
+ Version: $Revision: 1.5 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
*/
/**
- * \ingroup gdcmFile
* \brief routine for JPEG decompression
* @param fp pointer to an already open file descriptor
* 8 significant bits per pixel
* @return 1 on success, 0 on error
*/
-bool gdcmFile::gdcm_read_JPEG_file (FILE* fp, void* image_buffer)
+bool gdcm_read_JPEG_file ( FILE* fp, void* image_buffer )
{
char* pimage;
Program: gdcm
Module: $RCSfile: gdcmPixelConvert.cxx,v $
Language: C++
- Date: $Date: 2004/10/10 03:03:10 $
- Version: $Revision: 1.5 $
+ Date: $Date: 2004/10/10 16:44:00 $
+ 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
////////////////// TEMPORARY NOT
// look for "fixMem" and convert that to a member of this class
// Removing the prefix fixMem and dealing with allocations should do the trick
+//
+// grep PIXELCONVERT everywhere and clean up !
+
+
#define str2num(str, typeNum) *((typeNum *)(str))
#include "gdcmDebug.h"
#include "gdcmPixelConvert.h"
+// External JPEG decompression
+
+// for JPEGLosslessDecodeImage
+#include "jpeg/ljpg/jpegless.h"
+
+// For JPEG 2000, body in file gdcmJpeg2000.cxx
+bool gdcm_read_JPEG2000_file (FILE* fp, void* image_buffer);
+
+// For JPEG 8 Bits, body in file gdcmJpeg8.cxx
+bool gdcm_read_JPEG_file (FILE* fp, void* image_buffer);
+
+// For JPEG 12 Bits, body in file gdcmJpeg12.cxx
+bool gdcm_read_JPEG_file12 (FILE* fp, void* image_buffer);
+
+
//-----------------------------------------------------------------------------
// Constructor / Destructor
}
}
-/**
- * \brief Read from file an uncompressed image.
- */
-bool gdcmPixelConvert::ReadUncompressed( FILE* filePointer,
- size_t uncompressedSize,
- size_t expectedSize )
-{
- if ( expectedSize > uncompressedSize )
- {
- dbg.Verbose(0, "gdcmPixelConvert::ReadUncompressed: expectedSize"
- "is bigger than it should");
- return false;
- }
- SetUncompressedSize( uncompressedSize );
- AllocateUncompressed();
- size_t ItemRead = fread( (void*)Uncompressed, expectedSize, 1, filePointer);
- if ( ItemRead != 1 )
- {
- return false;
- }
- return true;
-}
-
-/**
- * \brief Convert a Gray plane and ( Lut R, Lut G, Lut B ) into an
- * RGB plane.
- * @return True on success.
- */
-bool gdcmPixelConvert::ConvertGrayAndLutToRGB( uint8_t *lutRGBA )
-
-{
- (void)lutRGBA;
- /// We assume Uncompressed contains the decompressed gray plane
- /// and build the RGB image.
- SetRGBSize( UncompressedSize );
- AllocateRGB();
-
-//aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
-//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-//COPY HERE THE CODE OF GetImageDataIntoVector
-
- /// \todo check that operator new []didn't fail, and sometimes return false
- return true;
-}
-
/**
* \brief Try to deal with RLE 16 Bits.
* We assume the RLE has allready been parsed and loaded in
- * Uncompressed (through \ref ReadAndUncompressRLE8Bits ).
+ * Uncompressed (through \ref ReadAndDecompressJPEGFile ).
* We here need to make 16 Bits Pixels from Low Byte and
* High Byte 'Planes'...(for what it may mean)
* @return Boolean
* at which the pixel data should be copied
* @return Boolean
*/
-bool gdcmPixelConvert::gdcm_read_RLE_file( void* image_buffer,
+bool gdcmPixelConvert::ReadAndDecompressRLEFile( void* image_buffer,
int XSize,
int YSize,
int ZSize,
++it )
{
// Loop on the fragments
- for( int k = 1; k <= (*it)->NumberFragments; k++ )
+ for( unsigned int k = 1; k <= (*it)->NumberFragments; k++ )
{
- fseek( fp, (*it)->Offset[k] ,SEEK_SET);
+ fseek( fp, (*it)->Offset[k] ,SEEK_SET );
(void)gdcmPixelConvert::ReadAndUncompressRLEFragment(
(uint8_t*) im, (*it)->Length[k],
uncompressedSegmentSize, fp );
}
}
+/**
+ * \brief Reads from disk the Pixel Data of JPEG Dicom encapsulated
+ & file and uncompress it.
+ * @param fp already open File Pointer
+ * @param destination Where decompressed fragments should end up
+ * @return Boolean
+ */
+bool gdcmPixelConvert::ReadAndDecompressJPEGFile( uint8_t* destination,
+ int XSize,
+ int YSize,
+ int BitsAllocated,
+ int BitsStored,
+ int SamplesPerPixel,
+ int PixelSize,
+ bool isJPEG2000,
+ bool isJPEGLossless,
+ gdcmJPEGFragmentsInfo* JPEGInfo,
+ FILE* fp )
+{
+ // Loop on the fragment[s]
+ for( gdcmJPEGFragmentsInfo::JPEGFragmentsList::iterator
+ it = JPEGInfo->Fragments.begin();
+ it != JPEGInfo->Fragments.end();
+ ++it )
+ {
+ fseek( fp, (*it)->Offset, SEEK_SET );
+
+ if ( isJPEG2000 )
+ {
+ if ( ! gdcm_read_JPEG2000_file( fp, destination ) )
+ {
+ return false;
+ }
+ }
+ else if ( isJPEGLossless )
+ {
+ // JPEG LossLess : call to xmedcom Lossless JPEG
+ JPEGLosslessDecodeImage( fp,
+ (uint16_t*)destination,
+ PixelSize * 8 * SamplesPerPixel,
+ (*it)->Length );
+ }
+ else if ( BitsStored == 8)
+ {
+ // JPEG Lossy : call to IJG 6b
+ if ( ! gdcm_read_JPEG_file ( fp, destination ) )
+ {
+ return false;
+ }
+ }
+ else if ( BitsStored == 12)
+ {
+ // Reading Fragment pixels
+ if ( ! gdcm_read_JPEG_file12 ( fp, destination ) )
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // other JPEG lossy not supported
+ dbg.Error(" gdcmFile::ReadPixelData : unknown jpeg lossy "
+ " compression ");
+ return false;
+ }
+
+ // Advance to next free location in destination
+ // for next fragment decompression (if any)
+ int length = XSize * YSize * SamplesPerPixel;
+ int numberBytes = BitsAllocated / 8;
+
+ destination = (uint8_t*)destination + length * numberBytes;
+
+ }
+ return true;
+}
+
+/**
+ * \brief Re-arrange the bits within the bytes.
+ * @param fp already open File Pointer
+ * @param destination Where decompressed fragments should end up
+ * @return Boolean
+ */
+bool gdcmPixelConvert::ConvertReArrangeBits(
+ uint8_t* pixelZone,
+ size_t imageDataSize,
+ int numberBitsStored,
+ int numberBitsAllocated,
+ int highBitPosition )
+ throw ( gdcmFormatError )
+{
+ if ( numberBitsStored != numberBitsAllocated )
+ {
+ int l = (int)(imageDataSize / (numberBitsAllocated/8));
+ if ( numberBitsAllocated == 16 )
+ {
+ uint16_t mask = 0xffff;
+ mask = mask >> ( numberBitsAllocated - numberBitsStored );
+ uint16_t* deb = (uint16_t*)pixelZone;
+ for(int i = 0; i<l; i++)
+ {
+ *deb = (*deb >> (numberBitsStored - highBitPosition - 1)) & mask;
+ deb++;
+ }
+ }
+ else if ( numberBitsAllocated == 32 )
+ {
+ uint32_t mask = 0xffffffff;
+ mask = mask >> ( numberBitsAllocated - numberBitsStored );
+ uint32_t* deb = (uint32_t*)pixelZone;
+ for(int i = 0; i<l; i++)
+ {
+ *deb = (*deb >> (numberBitsStored - highBitPosition - 1)) & mask;
+ deb++;
+ }
+ }
+ else
+ {
+ dbg.Verbose(0, "gdcmPixelConvert::ConvertReArrangeBits: weird image");
+ throw gdcmFormatError( "gdcmFile::ConvertReArrangeBits()",
+ "weird image !?" );
+ }
+ }
+}
+
Program: gdcm
Module: $RCSfile: gdcmPixelConvert.h,v $
Language: C++
- Date: $Date: 2004/10/08 17:02:53 $
- Version: $Revision: 1.4 $
+ Date: $Date: 2004/10/10 16:44:00 $
+ Version: $Revision: 1.5 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
#include "gdcmCommon.h"
#include "gdcmRLEFramesInfo.h"
+#include "gdcmJPEGFragmentsInfo.h"
#include "gdcmException.h"
/*
void Squeeze();
//////////////////////////////////////////////////////////
// In progress
-bool ReadAndUncompress12Bits( FILE* filePointer,
- size_t uncompressedSize,
- size_t PixelNumber );
-bool ReadUncompressed( FILE* filePointer,
- size_t uncompressedSize,
- size_t expectedSize );
-bool ConvertGrayAndLutToRGB( uint8_t *lutRGBA );
-bool ReadAndUncompressRLE8Bits(FILE* fp, size_t uncompressedSize );
-
static bool UncompressRLE16BitsFromRLE8Bits(
int XSize,
int YSize,
long fragmentSize,
long uncompressedSegmentSize,
FILE* fp );
- static bool gdcm_read_RLE_file(
+ static bool ReadAndDecompressRLEFile(
void* image_buffer,
int XSize,
int YSize,
int numberBitsAllocated,
int swapCode,
bool signedPixel );
+ static bool ReadAndDecompressJPEGFile(
+ uint8_t* destination,
+ int XSize,
+ int YSize,
+ int BitsAllocated,
+ int BitsStored,
+ int SamplesPerPixel,
+ int PixelSize,
+ bool isJPEG2000,
+ bool isJPEGLossless,
+ gdcmJPEGFragmentsInfo* JPEGInfo,
+ FILE* fp );
+ static bool gdcmPixelConvert::ConvertReArrangeBits(
+ uint8_t* pixelZone,
+ size_t imageDataSize,
+ int numberBitsStored,
+ int numberBitsAllocated,
+ int highBitPosition ) throw ( gdcmFormatError );
+
+
};
//-----------------------------------------------------------------------------
Program: gdcm
Module: $RCSfile: gdcmRLEFramesInfo.h,v $
Language: C++
- Date: $Date: 2004/10/08 16:27:20 $
- Version: $Revision: 1.3 $
+ Date: $Date: 2004/10/10 16:44:00 $
+ 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
* of a multiframe image. In this case the collection is limited
* to a single individual frame.
* The informations on each frame are obtained during the parsing
- * of a gdcmDocument (refer to \ref gdcmDocument::Parse7FE0() ).
+ * of a gdcmDocument (refer to
+ * \ref gdcmDocument::ComputeRLEInfo() ).
* They shall be used when (if necessary) decoding the frames.
*
* This class is simply a stl list<> of \ref gdcmRLEFrame.