Permalink
Browse files

[ImageDecoder] Support abbreviated JPEG datastreams

See libjpeg documentation for an explanation of abbreviated streams
  • Loading branch information...
1 parent ea0347d commit 9231bb453c707e6d6f032c76a4acaad88bd87ccd @aajanki aajanki committed Feb 25, 2013
Showing with 28 additions and 22 deletions.
  1. +28 −22 src/backends/image.cpp
@@ -32,13 +32,6 @@ extern "C" {
namespace lightspark
{
-struct source_mgr : public jpeg_source_mgr
-{
- source_mgr(const uint8_t* _data, int _len) : data(_data), len(_len) {}
- const uint8_t* data;
- int len;
-};
-
struct istream_source_mgr : public jpeg_source_mgr
{
istream_source_mgr(std::istream& str) : input(str), data(NULL), capacity(0) {}
@@ -47,18 +40,17 @@ struct istream_source_mgr : public jpeg_source_mgr
int capacity;
};
-static void init_source(j_decompress_ptr cinfo) {
- source_mgr* src = static_cast<source_mgr*>(cinfo->src);
- src->next_input_byte = (const JOCTET*)src->data;
- src->bytes_in_buffer = src->len;
+static void init_source_nop(j_decompress_ptr cinfo)
+{
+ //do nothing
}
static boolean fill_input_buffer(j_decompress_ptr cinfo) {
return FALSE;
}
static void skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
- source_mgr* src = static_cast<source_mgr*>(cinfo->src);
+ jpeg_source_mgr *src = cinfo->src;
src->next_input_byte = (const JOCTET*)((const char*)src->next_input_byte + num_bytes);
src->bytes_in_buffer -= num_bytes;
}
@@ -140,20 +132,24 @@ void error_exit(j_common_ptr cinfo) {
uint8_t* ImageDecoder::decodeJPEG(uint8_t* inData, int len, const uint8_t* tablesData, int tablesLen, uint32_t* width, uint32_t* height, bool* hasAlpha)
{
- struct source_mgr src(inData,len);
+ struct jpeg_source_mgr src;
- src.init_source = init_source;
+ src.next_input_byte = (const JOCTET*)inData;
+ src.bytes_in_buffer = len;
+ src.init_source = init_source_nop;
src.fill_input_buffer = fill_input_buffer;
src.skip_input_data = skip_input_data;
src.resync_to_restart = resync_to_restart;
src.term_source = term_source;
- struct source_mgr *tablesSrc;
+ struct jpeg_source_mgr *tablesSrc;
if (tablesData)
{
- tablesSrc = new source_mgr(tablesData,tablesLen);
+ tablesSrc = new jpeg_source_mgr();
- tablesSrc->init_source = init_source;
+ tablesSrc->next_input_byte = (const JOCTET*)tablesData;
+ tablesSrc->bytes_in_buffer = tablesLen;
+ tablesSrc->init_source = init_source_nop;
tablesSrc->fill_input_buffer = fill_input_buffer;
tablesSrc->skip_input_data = skip_input_data;
tablesSrc->resync_to_restart = resync_to_restart;
@@ -204,20 +200,30 @@ uint8_t* ImageDecoder::decodeJPEGImpl(jpeg_source_mgr *src, jpeg_source_mgr *hea
jpeg_create_decompress(&cinfo);
if (headerTables)
- {
cinfo.src = headerTables;
- jpeg_read_header(&cinfo, FALSE);
- }
+ else
+ cinfo.src = src;
- cinfo.src = src;
+ //DefineBits tag may contain "abbreviated datastreams" (as
+ //they are called in the libjpeg documentation), i.e. streams
+ //with only compression tables and no image data. The first
+ //jpeg_read_header accepts table-only streams.
+ int headerStatus = jpeg_read_header(&cinfo, FALSE);
if (headerTables)
{
// Must call init_source manually after switching src
+ // Check this. Doesn't jpeg_read_header call
+ // init_source anyway?
+ cinfo.src = src;
src->init_source(&cinfo);
}
- jpeg_read_header(&cinfo, TRUE);
+ //If the first jpeg_read_header got tables-only datastream,
+ //a second call is needed to read the real image header.
+ if (headerStatus == JPEG_HEADER_TABLES_ONLY)
+ jpeg_read_header(&cinfo, TRUE);
+
#ifdef JCS_EXTENSIONS
//JCS_EXT_XRGB is a fast decoder that outputs alpha channel,
//but is only available on libjpeg-turbo

0 comments on commit 9231bb4

Please sign in to comment.