diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2006-08-19 03:12:28 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2006-08-19 03:12:28 +0000 |
commit | 1fd361a1ea06e44286c213ca1f814f49306fdc43 (patch) | |
tree | 64c8c96cf54d8718847339a403e5e67b922e8c3f /converter/other/jpegdatasource.c | |
download | netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.gz netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.xz netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.zip |
Create Subversion repository
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'converter/other/jpegdatasource.c')
-rw-r--r-- | converter/other/jpegdatasource.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/converter/other/jpegdatasource.c b/converter/other/jpegdatasource.c new file mode 100644 index 00000000..5c1070e4 --- /dev/null +++ b/converter/other/jpegdatasource.c @@ -0,0 +1,183 @@ +/***************************************************************************** + jpegdatasource.c +****************************************************************************** + This is the data source manager that Jpegtopnm supplies to the JPEG + library. The Jpeg library uses this object to get JPEG input. + + This data source manager is the same as the Jpeg library's built in + "stdio" one, except that it looks ahead and one can query it to see + if there is any data in the stream that the Jpeg library hasn't seen + yet. Thus, you can use it in a program that reads multiple JPEG + images and know when to stop. You can also nicely handle completely + empty input files more gracefully than just crying input error. + + This data source manager does 4K fread() reads and passes 4K buffers + to the Jpeg library. It reads one 4K block ahead, so there is up to + 8K of image buffered at any time. + + By Bryan Henderson, San Jose CA 2002.10.13 +*****************************************************************************/ + +#include <ctype.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +/* Note: jpeglib.h prerequires stdlib.h and ctype.h. It should include them + itself, but doesn't. +*/ +#include <jpeglib.h> + +#include "pm_c_util.h" +#include "mallocvar.h" +#include "pnm.h" + +#include "jpegdatasource.h" + +#define BUFFER_SIZE 4096 + +struct sourceManager { + /* The following structure _must_ be the first thing in this structure, + because the methods below assume the address of the struct + jpeg_source_mgr is the same as the address of the struct sourceManager. + The former address is the only information the Jpeg library gives + these methods to tell them on what source manager object they are + supposed to operate. + */ + struct jpeg_source_mgr jpegSourceMgr; + FILE * ifP; + JOCTET * currentBuffer; + JOCTET * nextBuffer; + unsigned int bytesInNextBuffer; + JOCTET buffer1[BUFFER_SIZE]; + JOCTET buffer2[BUFFER_SIZE]; +}; + + +static void +dsInitSource(j_decompress_ptr const cinfoP) { +/*---------------------------------------------------------------------------- + This is the init_source method for the data source manager the Jpeg + library uses. +-----------------------------------------------------------------------------*/ + /* The object was created ready to go and remains ready from one image + to the next. No per-image initialization is necessary. + */ +} + + + +static boolean +dsFillInputBuffer(j_decompress_ptr const cinfoP) { +/*---------------------------------------------------------------------------- + This is the fill_input_buffer method for the data source manager the Jpeg + library uses. +-----------------------------------------------------------------------------*/ + struct sourceManager * const srcP = (struct sourceManager *) cinfoP->src; + + if (srcP->bytesInNextBuffer == 0) + pm_error("End-of-file encountered in the middle of JPEG image."); + else { + /* Rotate the buffers */ + srcP->jpegSourceMgr.next_input_byte = srcP->nextBuffer; + srcP->jpegSourceMgr.bytes_in_buffer = srcP->bytesInNextBuffer; + { + JOCTET * tmp; + tmp = srcP->nextBuffer; + srcP->nextBuffer = srcP->currentBuffer; + srcP->currentBuffer = tmp; + } + + /* Fill the new 'next' buffer */ + srcP->bytesInNextBuffer = + fread(srcP->nextBuffer, 1, BUFFER_SIZE, srcP->ifP); + } + return TRUE; +} + + + +static void +dsSkipInputData(j_decompress_ptr const cinfoP, long const num_bytes) { +/*---------------------------------------------------------------------------- + This is the skip_input_data method for the data source manager the Jpeg + library uses. +-----------------------------------------------------------------------------*/ + struct jpeg_source_mgr * const jpegSourceMgrP = cinfoP->src; + + long i; + + for (i = 0; i < num_bytes; ++i) { + if (jpegSourceMgrP->bytes_in_buffer == 0) + dsFillInputBuffer(cinfoP); + ++jpegSourceMgrP->next_input_byte; + --jpegSourceMgrP->bytes_in_buffer; + } +} + + + +static void +dsTermSource(j_decompress_ptr const cinfoP) { +/*---------------------------------------------------------------------------- + This is the term_source method for the data source manager the Jpeg + library uses. +-----------------------------------------------------------------------------*/ + /* We couldn't care less that the Jpeg library is done reading an + image. The source manager object remains active and ready for the + Jpeg library to read the next image. + */ +} + + + +bool +dsDataLeft(struct sourceManager * const srcP) { + + return((srcP->jpegSourceMgr.bytes_in_buffer > 0 || + srcP->bytesInNextBuffer > 0)); +} + + + +struct sourceManager * +dsCreateSource(const char * const fileName) { + + struct sourceManager * srcP; + + MALLOCVAR(srcP); + if (srcP == NULL) + pm_error("Unable to get memory for the Jpeg library source manager."); + + srcP->ifP = pm_openr(fileName); + + srcP->jpegSourceMgr.init_source = dsInitSource; + srcP->jpegSourceMgr.fill_input_buffer = dsFillInputBuffer; + srcP->jpegSourceMgr.skip_input_data = dsSkipInputData; + srcP->jpegSourceMgr.resync_to_restart = jpeg_resync_to_restart; + srcP->jpegSourceMgr.term_source = dsTermSource; + + srcP->currentBuffer = srcP->buffer1; + srcP->nextBuffer = srcP->buffer2; + srcP->jpegSourceMgr.bytes_in_buffer = + fread(srcP->currentBuffer, 1, BUFFER_SIZE, srcP->ifP); + srcP->jpegSourceMgr.next_input_byte = srcP->currentBuffer; + srcP->bytesInNextBuffer = + fread(srcP->nextBuffer, 1, BUFFER_SIZE, srcP->ifP); + + return srcP; +} + +void +dsDestroySource(struct sourceManager * const srcP) { + + pm_close(srcP->ifP); + free(srcP); + +} + + + +struct jpeg_source_mgr * +dsJpegSourceMgr(struct sourceManager * const srcP) { + return &srcP->jpegSourceMgr; +} |