+2005-01-24 Mathieu Malaterre <Mathieu.Malaterre@creatis.insa-lyon.fr>
+ * Grealty simplify the JPEg decompression, no need to differenciate based on
+ the JPEG possible type (with/without fragment, with/without multiple frame).
+ Everything is done throught the JPEG IO Suspension mechanism in IJG
+
2005-01-22 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
* src/gdcmDicomDirElement.h, gdcmDict.h : rename AddNewXxx methods to AddXxx.
* src/gdcmDict.h : rename GetDictEntry moethod to GetEntry, to be coherent
Program: gdcm
Module: $RCSfile: gdcmJPEGFragment.cxx,v $
Language: C++
- Date: $Date: 2005/01/18 14:28:32 $
- Version: $Revision: 1.5 $
+ Date: $Date: 2005/01/24 14:52:50 $
+ 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
bool gdcm_read_JPEG2000_file (std::ifstream* fp, void* image_buffer);
// For JPEG 8 Bits, body in file gdcmJpeg8.cxx
-bool gdcm_read_JPEG_file8 (std::ifstream *fp, void *image_buffer);
+//bool gdcm_read_JPEG_file8 (JPEGFragment *frag, std::ifstream *fp, void *image_buffer);
bool gdcm_read_JPEG_memory8 (const JOCTET *buffer, const size_t buflen,
void *image_buffer,
size_t *howManyRead, size_t *howManyWritten);
//
// For JPEG 12 Bits, body in file gdcmJpeg12.cxx
-bool gdcm_read_JPEG_file12 (std::ifstream *fp, void *image_buffer);
+//bool gdcm_read_JPEG_file12 (JPEGFragment *frag, std::ifstream *fp, void *image_buffer);
bool gdcm_read_JPEG_memory12 (const JOCTET *buffer, const size_t buflen,
void *image_buffer,
size_t *howManyRead, size_t *howManyWritten);
// For JPEG 16 Bits, body in file gdcmJpeg16.cxx
// Beware this is misleading there is no 16bits DCT algorithm, only
// jpeg lossless compression exist in 16bits.
-bool gdcm_read_JPEG_file16 (std::ifstream *fp, void *image_buffer);
+//bool gdcm_read_JPEG_file16 (JPEGFragment *frag, std::ifstream *fp, void *image_buffer);
bool gdcm_read_JPEG_memory16 (const JOCTET *buffer, const size_t buflen,
void* image_buffer,
size_t *howManyRead, size_t *howManyWritten);
{
Offset = 0;
Length = 0;
+
+// StateSuspension = 0;
+// void *SampBuffer;
+ pimage = 0;
+
}
/**
* @param buffer output (data decompress)
* @param nBits 8/12 or 16 bits jpeg
*/
-void JPEGFragment::DecompressJPEGFramesFromFile(std::ifstream *fp, uint8_t *buffer, int nBits)
+void JPEGFragment::DecompressJPEGFramesFromFile(std::ifstream *fp, uint8_t *buffer, int nBits, int & statesuspension)
{
// First thing need to reset file to proper position:
fp->seekg( Offset, std::ios::beg);
if ( nBits == 8 )
{
// JPEG Lossy : call to IJG 6b
- if ( ! gdcm_read_JPEG_file8( fp, buffer) )
+ if ( ! this->gdcm_read_JPEG_file8( fp, buffer, statesuspension) )
{
//return false;
}
else if ( nBits <= 12 )
{
// Reading Fragment pixels
- if ( ! gdcm_read_JPEG_file12 ( fp, buffer) )
+ if ( ! this->gdcm_read_JPEG_file12 ( fp, buffer, statesuspension) )
{
//return false;
}
else if ( nBits <= 16 )
{
// Reading Fragment pixels
- if ( ! gdcm_read_JPEG_file16 ( fp, buffer) )
+ if ( ! this->gdcm_read_JPEG_file16 ( fp, buffer, statesuspension) )
{
//return false;
}
Program: gdcm
Module: $RCSfile: gdcmJPEGFragment.h,v $
Language: C++
- Date: $Date: 2005/01/20 16:17:00 $
- Version: $Revision: 1.11 $
+ Date: $Date: 2005/01/24 14:52:50 $
+ Version: $Revision: 1.12 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
public:
JPEGFragment();
void Print( std::ostream &os = std::cout, std::string indent = "" );
- void DecompressJPEGFramesFromFile(std::ifstream *fp, uint8_t *buffer, int nBits);
+ void DecompressJPEGFramesFromFile(std::ifstream *fp, uint8_t *buffer, int nBits, int & statesuspension);
void DecompressJPEGSingleFrameFragmentsFromFile(JOCTET *buffer, size_t totalLength, uint8_t* raw, int nBits);
void DecompressJPEGFragmentedFramesFromFile(JOCTET *buffer, uint8_t* raw, int nBits, size_t &howManyRead, size_t &howManyWritten, size_t totalLength);
-private:
- long Offset;
- long Length;
+ bool gdcm_read_JPEG_file8 (std::ifstream* fp, void* image_buffer, int & statesuspension );
+ bool gdcm_read_JPEG_file12 (std::ifstream* fp, void* image_buffer, int & statesuspension );
+ bool gdcm_read_JPEG_file16 (std::ifstream* fp, void* image_buffer, int & statesuspension );
+
+//private:
+ uint32_t Offset;
+ uint32_t Length;
+
+ uint8_t *pimage;
+
friend class Document;
friend class FileHelper;
Program: gdcm
Module: $RCSfile: gdcmJPEGFragmentsInfo.cxx,v $
Language: C++
- Date: $Date: 2005/01/23 10:12:34 $
- Version: $Revision: 1.8 $
+ Date: $Date: 2005/01/24 14:52:50 $
+ Version: $Revision: 1.9 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
namespace gdcm
{
+JPEGFragmentsInfo::JPEGFragmentsInfo()
+ {
+ StateSuspension = 0;
+ }
/**
* \brief Default destructor
*/
}
+void JPEGFragmentsInfo::DecompressJPEGFramesFromFile(std::ifstream *fp, uint8_t *buffer, int nBits, int numBytes, int length)
+{
+ // Pointer to the Raw image
+ uint8_t *localRaw = buffer;
+
+ // Loop on the fragment[s]
+ JPEGFragmentsList::const_iterator it;
+ for( it = Fragments.begin();
+ it != Fragments.end();
+ ++it )
+ {
+ //(*it)->pimage = localRaw;
+ (*it)->DecompressJPEGFramesFromFile(fp, localRaw, nBits, StateSuspension);
+ // update pointer to image after some scanlines read:
+ localRaw = (*it)->pimage;
+ // Advance to next free location in Raw
+ // for next fragment decompression (if any)
+
+ //localRaw += length * numBytes;
+ //std::cerr << "Used to increment by: " << length * numBytes << std::endl;
+ }
+}
+
} // end namespace gdcm
Program: gdcm
Module: $RCSfile: gdcmJPEGFragmentsInfo.h,v $
Language: C++
- Date: $Date: 2005/01/20 16:17:00 $
- Version: $Revision: 1.11 $
+ Date: $Date: 2005/01/24 14:52:50 $
+ Version: $Revision: 1.12 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
class GDCM_EXPORT JPEGFragmentsInfo
{
public:
+ JPEGFragmentsInfo();
~JPEGFragmentsInfo();
void Print( std::ostream &os = std::cout, std::string const & indent = "" );
size_t GetFragmentsLength();
void ReadAllFragments(std::ifstream *fp, JOCTET *buffer );
+ void DecompressJPEGFramesFromFile(std::ifstream *fp, uint8_t *buffer, int nBits, int numBytes, int length);
private:
typedef std::list< JPEGFragment* > JPEGFragmentsList;
- JPEGFragmentsList Fragments;
+
+ //Some mathieu hack:
+ int StateSuspension;
+ void *SampBuffer;
+ char* pimage;
+ JPEGFragmentsList Fragments;
friend class Document;
friend class FileHelper;
Program: gdcm
Module: $RCSfile: gdcmJpeg.cxx,v $
Language: C++
- Date: $Date: 2005/01/23 18:13:48 $
- Version: $Revision: 1.35 $
+ Date: $Date: 2005/01/24 14:52:50 $
+ Version: $Revision: 1.36 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
=========================================================================*/
#include "gdcmFileHelper.h"
+#include "gdcmJPEGFragment.h"
/*
DICOM provides a mechanism for supporting the use of JPEG Image Compression
struct jpeg_error_mgr pub; /* "public" fields */
jmp_buf setjmp_buffer; /* for return to caller */
};
-
-//-----------------------------------------------------------------------------
typedef struct my_error_mgr* my_error_ptr;
+//-----------------------------------------------------------------------------
/*
* Here's the routine that will replace the standard error_exit method:
* @param image_buffer to receive uncompressed pixels
* @return 1 on success, 0 on error
*/
-
-bool gdcm_read_JPEG_file ( std::ifstream* fp, void* image_buffer )
+void *SampBuffer;
+bool JPEGFragment::gdcm_read_JPEG_file (std::ifstream* fp, void* image_buffer , int& statesuspension)
{
- char* pimage;
-
+ //static int fragimage = 0;
+ //std::cerr << "Image Fragment:" << fragimage++ << std::endl;
+ pimage = (uint8_t*)image_buffer;
/* This struct contains the JPEG decompression parameters and pointers to
* working space (which is allocated as needed by the JPEG library).
*/
- struct jpeg_decompress_struct cinfo;
+ static struct jpeg_decompress_struct cinfo;
/* -------------- inside, we found :
* JDIMENSION image_width; // input image width
int row_stride;/* physical row width in output buffer */
+ //std::cerr << "StateSuspension: " << statesuspension << std::endl;
+//#define GDCM_JPG_DEBUG
#ifdef GDCM_JPG_DEBUG
printf("entree dans File::gdcm_read_JPEG_file (i.e. 8), depuis gdcmJpeg\n");
#endif //GDCM_JPG_DEBUG
/* If we get here, the JPEG code has signaled an error.
* We need to clean up the JPEG object, close the input file, and return.
*/
+ std::cerr << "Qu'est c'est ce bordel !!!!!" << std::endl;
jpeg_destroy_decompress(&cinfo);
return 0;
}
/* Now we can initialize the JPEG decompression object. */
+ if( statesuspension == 0 )
+ {
jpeg_create_decompress(&cinfo);
-
/* Step 2: specify data source (eg, a file) */
#ifdef GDCM_JPG_DEBUG
printf("Entree Step 2\n");
#endif //GDCM_JPG_DEBUG
- jpeg_stdio_src(&cinfo, fp);
+ jpeg_stdio_src(&cinfo, fp, this, 1);
+ }
+ else
+ {
+ jpeg_stdio_src(&cinfo, fp, this, 0);
+ }
/* Step 3: read file parameters with jpeg_read_header() */
#ifdef GDCM_JPG_DEBUG
printf("Entree Step 3\n");
#endif //GDCM_JPG_DEBUG
- (void) jpeg_read_header(&cinfo, TRUE);
+ if( statesuspension < 2 )
+ {
+ if( jpeg_read_header(&cinfo, TRUE) == JPEG_SUSPENDED )
+ {
+ std::cerr << "Suspension: jpeg_read_header" << std::endl;
+ }
/* We can ignore the return value from jpeg_read_header since
* (a) suspension is not possible with the stdio data source, and
cinfo.out_color_space = JCS_UNKNOWN;
}
+ } //statesuspension < 2
#ifdef GDCM_JPG_DEBUG
printf("--------------Header contents :----------------\n");
printf("Entree Step 5\n");
#endif //GDCM_JPG_DEBUG
- (void) jpeg_start_decompress(&cinfo);
+ if(statesuspension < 3 )
+ {
+ if( jpeg_start_decompress(&cinfo) == FALSE )
+ {
+ std::cerr << "Suspension: jpeg_start_decompress" << std::endl;
+ }
/* We can ignore the return value since suspension is not possible
* with the stdio data source.
*/
printf ("cinfo.output_height %d cinfo.output_width %d\n",
cinfo.output_height,cinfo.output_width);
#endif //GDCM_JPG_DEBUG
- pimage=(char *)image_buffer;
+ SampBuffer = buffer;
+ } // statesuspension < 3
+ else
+ {
+ buffer = (JSAMPARRAY)SampBuffer;
+ }
int bufsize = cinfo.output_width * cinfo.output_components;
size_t rowsize = bufsize * sizeof(JSAMPLE);
*/
//printf( "scanlines: %d\n",cinfo.output_scanline);
- (void) jpeg_read_scanlines(&cinfo, buffer, 1);
+ if( jpeg_read_scanlines(&cinfo, buffer, 1) == 0 )
+ {
+ std::cerr << "Suspension: jpeg_read_scanlines" << std::endl;
+ statesuspension = 3;
+ return true;
+ }
// The ijg has no notion of big endian, therefore always swap the jpeg stream
#if defined(GDCM_WORDS_BIGENDIAN) && (CMAKE_BITS_IN_JSAMPLE != 8)
uint16_t *buffer16 = (uint16_t*)*buffer;
printf("Entree Step 7\n");
#endif //GDCM_JPG_DEBUG
- (void) jpeg_finish_decompress(&cinfo);
+ if( jpeg_finish_decompress(&cinfo) == FALSE )
+ {
+ std::cerr << "Suspension: jpeg_finish_decompress" << std::endl;
+ }
/* We can ignore the return value since suspension is not possible
* with the stdio data source.
/* This is an important step since it will release a good deal of memory. */
jpeg_destroy_decompress(&cinfo);
+ //std::cerr << "jpeg_destroy_decompress" << std::endl;
/* After finish_decompress, we can close the input file.
* Here we postpone it until after no more JPEG errors are possible,
void* image_buffer,
size_t *howManyRead, size_t *howManyWritten)
{
- char* pimage=(char *)image_buffer;
+ volatile char * pimage=(volatile char *)image_buffer;
JOCTET* input = (JOCTET*) input_buffer;
/* This struct contains the JPEG decompression parameters and pointers to
for(unsigned int i=0;i<rowsize/2;i++)
pimage16[i] = (buffer16[i] >> 8) | (buffer16[i] << 8 );
#else
- memcpy( pimage, *buffer,rowsize);
+ memcpy( (void*)pimage, *buffer,rowsize);
#endif //GDCM_WORDS_BIGENDIAN
pimage+=rowsize;
}
-
+
/* Step 7: Finish decompression */
#ifdef GDCM_JPG_DEBUG
printf("Entree Step 7\n");
Program: gdcm
Module: $RCSfile: gdcmJpeg12.cxx,v $
Language: C++
- Date: $Date: 2005/01/20 17:17:12 $
- Version: $Revision: 1.29 $
+ Date: $Date: 2005/01/24 14:52:50 $
+ Version: $Revision: 1.30 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
#define gdcm_write_JPEG_file gdcm_write_JPEG_file12
#define gdcm_read_JPEG_file gdcm_read_JPEG_file12
#define gdcm_read_JPEG_memory gdcm_read_JPEG_memory12
+//#define StateSuspension StateSuspension12
+#define SampBuffer SampBuffer12
+//#define pimage pimage12
#include "gdcmJpeg.cxx"
Program: gdcm
Module: $RCSfile: gdcmJpeg16.cxx,v $
Language: C++
- Date: $Date: 2005/01/20 17:17:12 $
- Version: $Revision: 1.8 $
+ Date: $Date: 2005/01/24 14:52:50 $
+ Version: $Revision: 1.9 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
#define gdcm_write_JPEG_file gdcm_write_JPEG_file16
#define gdcm_read_JPEG_file gdcm_read_JPEG_file16
#define gdcm_read_JPEG_memory gdcm_read_JPEG_memory16
+//#define StateSuspension StateSuspension16
+#define SampBuffer SampBuffer16
+//#define pimage pimage16
#include "gdcmJpeg.cxx"
Program: gdcm
Module: $RCSfile: gdcmJpeg8.cxx,v $
Language: C++
- Date: $Date: 2005/01/20 17:17:12 $
- Version: $Revision: 1.14 $
+ Date: $Date: 2005/01/24 14:52:50 $
+ 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
#define gdcm_write_JPEG_file gdcm_write_JPEG_file8
#define gdcm_read_JPEG_file gdcm_read_JPEG_file8
#define gdcm_read_JPEG_memory gdcm_read_JPEG_memory8
+//#define StateSuspension StateSuspension8
+#define SampBuffer SampBuffer8
+//#define pimage pimage8
#include "gdcmJpeg.cxx"
Program: gdcm
Module: $RCSfile: gdcmPixelReadConvert.cxx,v $
Language: C++
- Date: $Date: 2005/01/23 10:12:34 $
- Version: $Revision: 1.32 $
+ Date: $Date: 2005/01/24 14:52:50 $
+ Version: $Revision: 1.33 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
bool PixelReadConvert::ReadAndDecompressJPEGFramesFromFile( std::ifstream *fp )
{
// Pointer to the Raw image
- uint8_t *localRaw = Raw;
+ //uint8_t *localRaw = Raw;
// Precompute the offset localRaw will be shifted with
int length = XSize * YSize * SamplesPerPixel;
int numberBytes = BitsAllocated / 8;
- // Loop on the fragment[s]
- for( JPEGFragmentsInfo::JPEGFragmentsList::iterator
- it = JPEGInfo->Fragments.begin();
- it != JPEGInfo->Fragments.end();
- ++it )
- {
- (*it)->DecompressJPEGFramesFromFile(fp, localRaw, BitsStored );
-
- // Advance to next free location in Raw
- // for next fragment decompression (if any)
-
- localRaw += length * numberBytes;
- }
+// // Loop on the fragment[s]
+// for( JPEGFragmentsInfo::JPEGFragmentsList::iterator
+// it = JPEGInfo->Fragments.begin();
+// it != JPEGInfo->Fragments.end();
+// ++it )
+// {
+// (*it)->DecompressJPEGFramesFromFile(fp, localRaw, BitsStored );
+//
+// // Advance to next free location in Raw
+// // for next fragment decompression (if any)
+//
+// localRaw += length * numberBytes;
+// }
+ JPEGInfo->DecompressJPEGFramesFromFile(fp, Raw, BitsStored, numberBytes, length );
return true;
}
return false;
}
- if ( ( ZSize == 1 ) && ( JPEGInfo->Fragments.size() > 1 ) )
- {
- // we have one frame split into several fragments
- // we will pack those fragments into a single buffer and
- // read from it
- return ReadAndDecompressJPEGSingleFrameFragmentsFromFile( fp );
- }
- else if (JPEGInfo->Fragments.size() == (size_t)ZSize)
- {
+// if ( ( ZSize == 1 ) && ( JPEGInfo->Fragments.size() > 1 ) )
+// {
+// // we have one frame split into several fragments
+// // we will pack those fragments into a single buffer and
+// // read from it
+// return ReadAndDecompressJPEGSingleFrameFragmentsFromFile( fp );
+// }
+// else if (JPEGInfo->Fragments.size() == (size_t)ZSize)
+// {
// suppose each fragment is a frame
return ReadAndDecompressJPEGFramesFromFile( fp );
- }
- else
- {
- // The dicom image contains frames containing fragments of images
- // a more complex algorithm :-)
- return ReadAndDecompressJPEGFragmentedFramesFromFile( fp );
- }
+// }
+// else
+// {
+// // The dicom image contains frames containing fragments of images
+// // a more complex algorithm :-)
+// return ReadAndDecompressJPEGFragmentedFramesFromFile( fp );
+// }
}
/**
std::ifstream *infile; /* source stream */
JOCTET * buffer; /* start of buffer */
boolean start_of_file; /* have we gotten any data yet? */
+ //PixelReadConvert *pixels;
+ gdcm::JPEGFragment *frag;
+ size_t bytes_read;
} my_source_mgr;
typedef my_source_mgr * my_src_ptr;
{
my_src_ptr src = (my_src_ptr) cinfo->src;
- src->infile->read( (char*)src->buffer, INPUT_BUF_SIZE);
+ //std::cerr << "Before comp:" << src->bytes_read << " / " << src->frag->Length << std::endl;
+ if( src->bytes_read == src->frag->Length )
+ {
+ //std::cerr << "Sweet finished this fragment" << std::endl;
+ return FALSE;
+ }
+
+ size_t input_buf_size = INPUT_BUF_SIZE;
+ if( (src->bytes_read + INPUT_BUF_SIZE) > src->frag->Length )
+ {
+ //std::cerr << "Woula error:" << src->bytes_read << " / " << src->frag->Length << std::endl;
+ input_buf_size = src->frag->Length - src->bytes_read;
+ //std::cerr << "Ok only reading: " << input_buf_size << " / " << INPUT_BUF_SIZE << std::endl;
+ }
+
+ //std::cerr << "infile read:" << src->pub.bytes_in_buffer << std::endl;
+ src->infile->read( (char*)src->buffer, input_buf_size);
size_t nbytes = src->infile->gcount();
+ //std::cerr << "input_buf_size=" << input_buf_size << " and nbytes=" << nbytes << std::endl;
if (nbytes <= 0) {
if (src->start_of_file) /* Treat empty input file as fatal error */
src->pub.next_input_byte = src->buffer;
src->pub.bytes_in_buffer = nbytes;
src->start_of_file = FALSE;
+ src->bytes_read += nbytes;
+
return TRUE;
+ // otherwise cause a suspension return
+ //std::cerr << "fill_input_buffer" << std::endl;
+ //return FALSE;
}
METHODDEF(void)
skip_input_data (j_decompress_ptr cinfo, long num_bytes)
{
+ //std::cerr << "skip_input_data:" << num_bytes << std::endl;
my_src_ptr src = (my_src_ptr) cinfo->src;
/* Just a dumb implementation for now. Could use fseek() except
*/
GLOBAL(void)
-jpeg_stdio_src (j_decompress_ptr cinfo, std::ifstream * infile)
+jpeg_stdio_src (j_decompress_ptr cinfo, std::ifstream * infile, gdcm::JPEGFragment *frag, int flag)
{
my_src_ptr src;
src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
src->pub.term_source = term_source;
src->infile = infile;
+
+ if( flag )
+ {
src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
src->pub.next_input_byte = NULL; /* until buffer loaded */
+ src->frag = frag;
+ src->bytes_read = 0;
+ }
+ else
+ {
+ //only upate the new fragment
+ src->frag = frag;
+ src->bytes_read = 0;
+ }
}