forked from 0ad/0ad
188 lines
5.2 KiB
C++
188 lines
5.2 KiB
C++
#include "precompiled.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/*
|
|
* jmemdatasrc.c (adapted from IJG jdatasrc.c)
|
|
*
|
|
* Copyright (C) 2004, Jan Wassenberg.
|
|
* Copyright (C) 1994-1996, Thomas G. Lane.
|
|
*
|
|
* This file contains decompression data source routines for the case of
|
|
* reading JPEG data from a single memory buffer. Suspension isn't used.
|
|
*
|
|
* IMPORTANT: we assume that JOCTET is 8 bits.
|
|
*/
|
|
|
|
/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
|
|
#include "jpeglib.h"
|
|
#include "jerror.h"
|
|
|
|
// (Simon) Macros from jinclude.h, which isn't installed by default on my system
|
|
#define SIZEOF(_a) ((size_t) sizeof(_a))
|
|
|
|
/* Expanded data source object for memory input */
|
|
typedef struct
|
|
{
|
|
struct jpeg_source_mgr pub; /* public fields */
|
|
|
|
JOCTET* buf;
|
|
size_t size; /* total size (bytes) */
|
|
size_t pos; /* offset (bytes) to new data */
|
|
}
|
|
MemSrcMgr;
|
|
|
|
typedef MemSrcMgr* SrcPtr;
|
|
|
|
|
|
/*
|
|
* Initialize source --- called by jpeg_read_header
|
|
* before any data is actually read.
|
|
*/
|
|
|
|
METHODDEF(void) init_source(j_decompress_ptr cinfo)
|
|
{
|
|
}
|
|
|
|
|
|
/*
|
|
* Fill the input buffer --- called whenever buffer is emptied.
|
|
*
|
|
* In typical applications, this should read fresh data into the buffer
|
|
* (ignoring the current state of next_input_byte & bytes_in_buffer),
|
|
* reset the pointer & count to the start of the buffer, and return TRUE
|
|
* indicating that the buffer has been reloaded. It is not necessary to
|
|
* fill the buffer entirely, only to obtain at least one more byte.
|
|
*
|
|
* There is no such thing as an EOF return. If the end of the file has been
|
|
* reached, the routine has a choice of ERREXIT() or inserting fake data into
|
|
* the buffer. In most cases, generating a warning message and inserting a
|
|
* fake EOI marker is the best course of action --- this will allow the
|
|
* decompressor to output however much of the image is there. However,
|
|
* the resulting error message is misleading if the real problem is an empty
|
|
* input file, so we handle that case specially.
|
|
*/
|
|
|
|
METHODDEF(boolean) fill_input_buffer(j_decompress_ptr cinfo)
|
|
{
|
|
SrcPtr src = (SrcPtr)cinfo->src;
|
|
static const JOCTET eoi[2] = { 0xFF, JPEG_EOI };
|
|
|
|
/*
|
|
* since jpeg_mem_src fills the buffer with everything we've got,
|
|
* jpeg is trying to read beyond end of buffer. return a fake EOI marker.
|
|
* note: don't modify input buffer: it might be read-only.
|
|
*/
|
|
|
|
WARNMS(cinfo, JWRN_JPEG_EOF);
|
|
|
|
|
|
src->pub.next_input_byte = eoi;
|
|
src->pub.bytes_in_buffer = 2;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
* Skip data --- used to skip over a potentially large amount of
|
|
* uninteresting data (such as an APPn marker).
|
|
*/
|
|
|
|
METHODDEF(void) skip_input_data(j_decompress_ptr cinfo, long num_bytes)
|
|
{
|
|
SrcPtr src = (SrcPtr)cinfo->src;
|
|
size_t skip_count = (size_t)num_bytes;
|
|
|
|
/* docs say non-positive num_byte skips should be ignored */
|
|
if(num_bytes <= 0)
|
|
return;
|
|
|
|
/*
|
|
* just subtract bytes available in buffer,
|
|
* making sure we don't underflow the size_t.
|
|
* note: if we skip to or beyond end of buffer,
|
|
* bytes_in_buffer = 0 => fill_input_buffer called => abort.
|
|
*/
|
|
if(skip_count > src->pub.bytes_in_buffer)
|
|
skip_count = src->pub.bytes_in_buffer;
|
|
|
|
src->pub.bytes_in_buffer -= skip_count;
|
|
src->pub.next_input_byte += skip_count;
|
|
}
|
|
|
|
|
|
/*
|
|
* An additional method that can be provided by data source modules is the
|
|
* resync_to_restart method for error recovery in the presence of RST markers.
|
|
* For the moment, this source module just uses the default resync method
|
|
* provided by the JPEG library. That method assumes that no backtracking
|
|
* is possible.
|
|
*/
|
|
|
|
|
|
/*
|
|
* Terminate source --- called by jpeg_finish_decompress
|
|
* after all data has been read. Often a no-op.
|
|
*
|
|
* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
|
|
* application must deal with any cleanup that should happen even
|
|
* for error exit.
|
|
*/
|
|
|
|
METHODDEF(void) term_source(j_decompress_ptr cinfo)
|
|
{
|
|
/*
|
|
* no-op (we don't own the buffer and shouldn't,
|
|
* to make possible multiple images in a source).
|
|
*/
|
|
}
|
|
|
|
|
|
/*
|
|
* Prepare for input from a buffer.
|
|
* The caller is responsible for freeing it after finishing decompression.
|
|
*/
|
|
|
|
GLOBAL(void) jpeg_mem_src(j_decompress_ptr cinfo, void* p, size_t size)
|
|
{
|
|
SrcPtr src;
|
|
|
|
/* Treat 0-length buffer as fatal error */
|
|
if(size == 0)
|
|
ERREXIT(cinfo, JERR_INPUT_EMPTY);
|
|
|
|
/*
|
|
* The source object is made permanent so that
|
|
* a series of JPEG images can be read from the same file
|
|
* by calling jpeg_mem_src only before the first one.
|
|
* This makes it unsafe to use this manager and a different source
|
|
* manager serially with the same JPEG object. Caveat programmer.
|
|
|
|
/* first time for this JPEG object? */
|
|
if(!cinfo->src)
|
|
cinfo->src = (struct jpeg_source_mgr*)
|
|
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
|
SIZEOF(MemSrcMgr));
|
|
/* (takes care of raising error if out of memory) */
|
|
|
|
src = (SrcPtr)cinfo->src;
|
|
src->pub.init_source = init_source;
|
|
src->pub.fill_input_buffer = fill_input_buffer;
|
|
src->pub.skip_input_data = skip_input_data;
|
|
src->pub.resync_to_restart = jpeg_resync_to_restart; /* default */
|
|
src->pub.term_source = term_source;
|
|
|
|
/*
|
|
* fill buffer with everything we have.
|
|
* if fill_input_buffer is called, the buffer was overrun.
|
|
*/
|
|
src->pub.bytes_in_buffer = size;
|
|
src->pub.next_input_byte = (JOCTET*)p;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|