📄 jpg2.c
字号:
/* webimage/dll_jpeg/jpg2.c *//* Co-operatively multi-tasked JPEG decoding * Copyright (C) ANT Limited 1999 -- All Rights Reserved -- Confidential * $Header: /cvs/repos/src/webimage/dll_jpeg/layers/jpg2.c,v 1.1.4.3 2003/09/12 09:35:37 simonp Exp $ * * Only webimage2_jpeg_recognise() (the JPEG decoder factory) is exported from * this file. * * Based on libjpeg example code. Should be read in conjunction with the IJG * documentation, libjpeg.doc. */#include "layers.h"#include "layers_assert.h"#include "layers_bmp.h"#include "memwatch.h"#include <setjmp.h>#ifdef DYNAMIC_LIBJPEG #include <jpeglib.h> #include <jerror.h> #else #include "../jpeglib.h" #include "../jerror.h" #endif#include "../../image.h"#include "wrsprite.h"typedef enum { jpegstate_START, jpegstate_HEADER, jpegstate_STARTIMAGE, jpegstate_IMAGE, jpegstate_FINISHING, jpegstate_FINISHED, jpegstate_PROGRESSIVE, jpegstate_PROGRESSIVE_STARTSCAN, jpegstate_PROGRESSIVE_IMAGE, jpegstate_PROGRESSIVE_STARTINGSCAN, jpegstate_PROGRESSIVE_FINISHINGSCAN, jpegstate_ERROR} jpegstate;#if LAYERS_FB_32BITS/* represents the Y/U/V subsampling in the image */typedef enum{ jpeg_yuv_422, /* U,V subsampled 2:1 horizontally */ jpeg_yuv_420, /* U,V subsampled 2:1 horizontall and vertically */ jpeg_yuv_111, /* U,V not subsampled */ jpeg_yuv_GREY, /* Y component only */ jpeg_yuv_OTHER /* some other subsampling arrangement */} jpeg_yuv_mode;#endif#define WEBIMAGE2_JPEGMAGIC 0x26423599/** This is what the decoderhandle in the webimage2str points to */struct webimage2_jpegstr { unsigned int magic; /* for checking this is one of ours */ struct jpeg_decompress_struct cinfo; /* libjpeg control structure */ webimage2 w; /* parent webimage2 handle */ jpegstate state; int skipping; /* for when skipping input bytes */ void *buf; /* values passed to current feed fn */ int nBytes; BOOL eof; BOOL new_buffer; /* TRUE first time through on each buffer */ djpeg_dest_ptr sink; /* Bitmap output */ int image_offset; /* Offset of start of bitmap data within sprite */ struct { int oldscan; BOOL final_pass; BOOL nextscan; } prog; /* Additional state information for progressive JPEGs */ struct jpeg_progress_mgr progress; /* for progress info */ webimage_rotate rotate;#if LAYERS_FB_32BITS jpeg_yuv_mode yuv_mode; /* when outputting YUV */ JSAMPARRAY component_array[3]; struct /* effective sampling factors when */ { /* scaling is in use */ int h_samp_factor; int v_samp_factor; } sampling[3]; int max_h_samp_factor; int max_v_samp_factor;#endif};typedef struct webimage2_jpegstr *webimage2_jpeg;/* Override libjpeg's error handler to longjmp back into webimage2_jpeg_feed */struct webimage2_error_mgr { struct jpeg_error_mgr base; jmp_buf jmpbuf;}; /*=================================* * jpeglib image source object * *=================================*/typedef struct { struct jpeg_source_mgr base; webimage2_jpeg j;} webimage2_jpegsource;/** jpeglib image source method: init */static void webimage2__init_source( j_decompress_ptr cinfo ){ NOT_USED(cinfo);}/** jpeglib image source method: fill */static boolean webimage2__fill_input_buffer( j_decompress_ptr cinfo ){ webimage2_jpegsource *source = (webimage2_jpegsource*) cinfo->src; webimage2_jpeg j = source->j; if ( j->new_buffer && j->nBytes ) { j->new_buffer = FALSE; source->base.next_input_byte = j->buf; source->base.bytes_in_buffer = j->nBytes; WIDBG(("wi%p: jpeg new buffer, nBytes=%d\n", j->w, j->nBytes )); /* Assume it used all of it, unless it tells us otherwise */ j->nBytes = 0; return TRUE; } if ( j->eof ) { /* No more data is ever going to arrive, so keep returning EOI markers * until libjpeg gets the message */ static const JOCTET fakeEOI[2] = { 0xFF, JPEG_EOI }; source->base.next_input_byte = fakeEOI; source->base.bytes_in_buffer = 2; return TRUE; } /* Otherwise we suspend */ WIDBG(("wi%p: jpeg suspending with nBytes=%d\n", j->w, source->base.bytes_in_buffer )); j->nBytes = source->base.bytes_in_buffer; /* Ensure we get called again */ source->base.bytes_in_buffer = 0; return FALSE;}/** jpeglib image source method: skip some input */static void webimage2__skip_input_data( j_decompress_ptr cinfo, long nBytes ){ webimage2_jpegsource *source = (webimage2_jpegsource*) cinfo->src; webimage2_jpeg j = source->j; size_t lump = (size_t)nBytes; WIDBG(("wi%p: webimage2__skip_input_data[jpeg] asked to skip %d\n", j->w, lump)); if ( lump <= source->base.bytes_in_buffer ) { source->base.bytes_in_buffer -= lump; source->base.next_input_byte += lump; return; } /* tricky case, we must tell webimage2_jpeg_feed to skip the remaining * bytes */ j->skipping = (int)nBytes - source->base.bytes_in_buffer; WIDBG(("wi%p: webimage2__skip_input_data[jpeg] skipping whole buffer (%d) with %d remaining\n", j->w, source->base.bytes_in_buffer, j->skipping )); source->base.next_input_byte += source->base.bytes_in_buffer; source->base.bytes_in_buffer = 0; /* When we return, libjpeg will observe that bytes_in_buffer is 0 and * call fill_input_buffer. This will then suspend. */}/** jpeglib image source method: finish */static void webimage2__term_source( j_decompress_ptr cinfo ){ NOT_USED(cinfo);}#define JALLOC(n) ((void*)(cinfo->mem->alloc_small)( (j_common_ptr)cinfo, \ JPOOL_IMAGE, n ))/** Image source constructor */static void webimage2__src( j_decompress_ptr cinfo, webimage2_jpeg j ){ webimage2_jpegsource *theSource; theSource = JALLOC( sizeof(webimage2_jpegsource) ); theSource->base.init_source = webimage2__init_source; theSource->base.fill_input_buffer = webimage2__fill_input_buffer; theSource->base.skip_input_data = webimage2__skip_input_data; theSource->base.resync_to_restart = jpeg_resync_to_restart; /* default */ theSource->base.term_source = webimage2__term_source; theSource->j = j; theSource->base.bytes_in_buffer = 0; theSource->base.next_input_byte = NULL; cinfo->src = &theSource->base;} /*============================* * jpeglib error handlers * *============================*/void webimage2__jpeg_error( j_common_ptr cinfo ){ struct webimage2_error_mgr *emgr = (struct webimage2_error_mgr*) cinfo->err; longjmp( emgr->jmpbuf, 1 );}void webimage2__jpeg_message( j_common_ptr cinfo ){ /* If error is premature EOF then abort translation */ if ( cinfo->err->msg_code == JWRN_JPEG_EOF ) webimage2__jpeg_error( cinfo );} /*===============================* * Initialise decoder object * *===============================*/static void* webimage2__jpeg_init( webimage2 w ){ webimage2_jpeg result = NULL; result = mm_weakmalloc( sizeof(*result) ); if ( !result ) return NULL; memset( result, 0, sizeof(*result) ); result->magic = WEBIMAGE2_JPEGMAGIC; result->state = jpegstate_START; result->w = w; result->skipping = 0; ASSERT((w->flags & webimage_JPEG32) == 0 || (w->flags & webimage_JPEGYUV422) == 0); ASSERT((w->flags & (webimage_ROTATE_180 | webimage_ROTATE_90)) == 0 || (w->flags & webimage_JPEG32) != 0 || (w->flags & webimage_JPEGYUV422) != 0 ); result->rotate = webimage_rotate_NONE;#if LAYERS_FB_32BITS if (w->flags & webimage_ROTATE_180) { result->rotate += webimage_rotate_LEFT_180; } if (w->flags & webimage_ROTATE_90) { result->rotate += webimage_rotate_LEFT_90; }#endif /* Don't initialise the decompressor here as we need the error handler * set up. */ return (void*)result;}/* Get information about resulting output sprite. (Copied from jpg.c) * A return value of NULL indicates EITHER failure (bad source image), or that * not enough of the source data has been read yet to return a valid image_rec * pointer. */static webimage2_rc webimage2__jpeg_info( webimage2_jpeg j, j_decompress_ptr cinfo){ int width_in_bytes; /* word-aligned */ int palettesize = 0; image_rec ir; int depth; /* Initialise image_rec struct */ memset( &ir, 0, sizeof(image_rec) );#if LAYERS_FB_32BITS if (j->rotate == webimage_rotate_LEFT_90 || j->rotate == webimage_rotate_LEFT_270) { ir.x = ir.x_logical = cinfo->output_height; ir.y = ir.y_logical = cinfo->output_width; } else#endif { ir.x = ir.x_logical = cinfo->output_width; ir.y = ir.y_logical = cinfo->output_height; } ir.interlaced = jpeg_has_multiple_scans(cinfo); ir.mask = FALSE; ir.jfif = cinfo->saw_JFIF_marker; if (cinfo->quantize_colors) { if (cinfo->out_color_space == JCS_GRAYSCALE) { if (cinfo->desired_number_of_colors <= 16) { /* 4bpp, 16 colour fixed greyscale palette */ palettesize = 128;/* ir.*/depth = 4; } else { /* 8bpp, 256 colour greyscale palette */ palettesize = 2048; /* ir.*/depth = 8; } ir.palette = TRUE; } else { /* 8bpp, 256 colour fixed palette */ /*ir.*/depth = 8;#if !RISCOS palettesize = 2048; /* We need a full palette when not on RISCOS */#endif } } else {#if LAYERS_FB_32BITS depth = j->w->flags & webimage_JPEG32 ? 32 : 16;#else depth = 16;#endif } ir.palette = (palettesize > 0 ); width_in_bytes = ((ir.x * /*ir.*/depth + 31) >> 5) * 4; ir.size = sizeof(sprite_header)*CHAR_BIT/8 + palettesize + width_in_bytes*ir.y; /* Used by jpg2sprite_start() if progressive scans */ j->image_offset = sizeof(sprite_header)*CHAR_BIT/8 + palettesize; /* Tell calling program about image size, etc */ if ( !j->w->irec(&ir, j->w->handle) ) { return webimage2_ABORTED; } return webimage2_OK;}#if LAYERS_FB_32BITS/* Process YUV data so that it's 24bit, so that the put code doesn't * have to worry about it having y, u or v subsampling. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -