183 lines
4.1 KiB
C
183 lines
4.1 KiB
C
/*
|
|
* A simple wrapper of JPEG decoder.
|
|
*
|
|
* Copyright (C) Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "ijgdec.h"
|
|
|
|
#if defined(HAVE_LIBJPEG) && defined(HAVE_JPEGLIB_H)
|
|
|
|
#include <jpeglib.h>
|
|
#include <jerror.h>
|
|
#include <setjmp.h>
|
|
|
|
typedef struct IJGSrcImpl IJGSrcImpl;
|
|
typedef struct IJGErrImpl IJGErrImpl;
|
|
struct IJGSrcImpl
|
|
{
|
|
struct jpeg_source_mgr pub; /* must be first */
|
|
|
|
const char** ppsrcs;
|
|
const int* plenofsrcs;
|
|
int srccount;
|
|
int srcindex;
|
|
};
|
|
|
|
struct IJGErrImpl
|
|
{
|
|
struct jpeg_error_mgr err;
|
|
|
|
jmp_buf env;
|
|
};
|
|
|
|
|
|
/* for the jpeg decompressor source manager. */
|
|
static void IJGDec_init_source(j_decompress_ptr cinfo) {}
|
|
|
|
static boolean IJGDec_fill_input_buffer(j_decompress_ptr cinfo)
|
|
{
|
|
IJGSrcImpl* pImpl = (IJGSrcImpl*)cinfo->src;
|
|
|
|
if ( pImpl->srcindex >= pImpl->srccount )
|
|
{
|
|
ERREXIT(cinfo, JERR_INPUT_EMPTY);
|
|
}
|
|
pImpl->pub.next_input_byte = pImpl->ppsrcs[pImpl->srcindex];
|
|
pImpl->pub.bytes_in_buffer = pImpl->plenofsrcs[pImpl->srcindex];
|
|
pImpl->srcindex ++;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void IJGDec_skip_input_data(j_decompress_ptr cinfo,long num_bytes)
|
|
{
|
|
IJGSrcImpl* pImpl = (IJGSrcImpl*)cinfo->src;
|
|
|
|
if ( num_bytes <= 0 ) return;
|
|
|
|
while ( num_bytes > pImpl->pub.bytes_in_buffer )
|
|
{
|
|
num_bytes -= pImpl->pub.bytes_in_buffer;
|
|
if ( !IJGDec_fill_input_buffer(cinfo) )
|
|
{
|
|
ERREXIT(cinfo, JERR_INPUT_EMPTY);
|
|
}
|
|
}
|
|
|
|
pImpl->pub.next_input_byte += num_bytes;
|
|
pImpl->pub.bytes_in_buffer -= num_bytes;
|
|
}
|
|
|
|
static void IJGDec_term_source(j_decompress_ptr cinfo)
|
|
{
|
|
}
|
|
|
|
static void IJGDec_error_exit(j_common_ptr cinfo)
|
|
{
|
|
IJGErrImpl* pImpl = (IJGErrImpl*)cinfo->err;
|
|
|
|
longjmp(pImpl->env,1);
|
|
}
|
|
|
|
static void rgb_to_bgr(char* pdata,int width)
|
|
{
|
|
int x;
|
|
char c;
|
|
|
|
for(x=0;x<width;x++)
|
|
{
|
|
c = pdata[0];
|
|
pdata[0] = pdata[2];
|
|
pdata[2] = c;
|
|
pdata += 3;
|
|
}
|
|
}
|
|
|
|
int IJGDEC_Decode( char* pdst, int dstpitch, int dstwidth, int dstheight, int dstbpp, const char** ppsrcs, const int* plenofsrcs, int srccount )
|
|
{
|
|
IJGSrcImpl jsrc;
|
|
IJGErrImpl jerr;
|
|
struct jpeg_decompress_struct jdec;
|
|
int ret = -1;
|
|
|
|
jsrc.ppsrcs = ppsrcs;
|
|
jsrc.plenofsrcs = plenofsrcs;
|
|
jsrc.srccount = srccount;
|
|
jsrc.srcindex = 0;
|
|
jsrc.pub.bytes_in_buffer = 0;
|
|
jsrc.pub.next_input_byte = NULL;
|
|
jsrc.pub.init_source = IJGDec_init_source;
|
|
jsrc.pub.fill_input_buffer = IJGDec_fill_input_buffer;
|
|
jsrc.pub.skip_input_data = IJGDec_skip_input_data;
|
|
jsrc.pub.resync_to_restart = jpeg_resync_to_restart;
|
|
jsrc.pub.term_source = IJGDec_term_source;
|
|
|
|
jdec.err = jpeg_std_error(&jerr.err);
|
|
jerr.err.error_exit = IJGDec_error_exit;
|
|
|
|
if ( setjmp(jerr.env) != 0 )
|
|
{
|
|
jpeg_destroy_decompress(&jdec);
|
|
return -1;
|
|
}
|
|
|
|
jpeg_create_decompress(&jdec);
|
|
jdec.src = &jsrc.pub;
|
|
|
|
ret = jpeg_read_header(&jdec,TRUE);
|
|
if ( ret != JPEG_HEADER_OK ) goto err;
|
|
|
|
jpeg_start_decompress(&jdec);
|
|
|
|
if ( jdec.output_width != dstwidth ||
|
|
jdec.output_height != dstheight ||
|
|
(jdec.output_components*8) != dstbpp ) goto err;
|
|
|
|
while (jdec.output_scanline < jdec.output_height)
|
|
{
|
|
jpeg_read_scanlines(&jdec,(JSAMPLE**)&pdst,1);
|
|
rgb_to_bgr(pdst,dstwidth);
|
|
pdst += dstpitch;
|
|
}
|
|
|
|
jpeg_finish_decompress(&jdec);
|
|
ret = 0;
|
|
err:
|
|
jpeg_destroy_decompress(&jdec);
|
|
|
|
return ret;
|
|
}
|
|
|
|
#else
|
|
|
|
int IJGDEC_Decode( char* pdst, int dstpitch, int dstwidth, int dstheight, int dstbpp, const char** ppsrcs, const int* plenofsrcs, int srccount )
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
#endif
|
|
|
|
|