📄 tif_jpeg.c
字号:
/* $Header: /cvsroot/osrs/libtiff/libtiff/tif_jpeg.c,v 1.5 2001/07/20 15:00:35 warmerda Exp $ *//* * Copyright (c) 1994-1997 Sam Leffler * Copyright (c) 1994-1997 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */#include "tiffiop.h"#ifdef JPEG_SUPPORT/* * TIFF Library * * JPEG Compression support per TIFF Technical Note #2 * (*not* per the original TIFF 6.0 spec). * * This file is simply an interface to the libjpeg library written by * the Independent JPEG Group. You need release 5 or later of the IJG * code, which you can find on the Internet at ftp.uu.net:/graphics/jpeg/. * * Contributed by Tom Lane <tgl@sss.pgh.pa.us>. */#include <assert.h>#include <stdio.h>#include <setjmp.h>/* We undefine FAR to avoid conflict with JPEG definition */#ifdef FAR#undef FAR#endif/* The windows RPCNDR.H file defines boolean. */#ifdef __RPCNDR_H__#define HAVE_BOOLEAN#endif#include "..\jpeg\jpeglib.h"#include "..\jpeg\jerror.h"/* * On some machines it may be worthwhile to use _setjmp or sigsetjmp * in place of plain setjmp. These macros will make it easier. */#define SETJMP(jbuf) setjmp(jbuf)#define LONGJMP(jbuf,code) longjmp(jbuf,code)#define JMP_BUF jmp_buftypedef struct jpeg_destination_mgr jpeg_destination_mgr;typedef struct jpeg_source_mgr jpeg_source_mgr;typedef struct jpeg_error_mgr jpeg_error_mgr;/* * State block for each open TIFF file using * libjpeg to do JPEG compression/decompression. * * libjpeg's visible state is either a jpeg_compress_struct * or jpeg_decompress_struct depending on which way we * are going. comm can be used to refer to the fields * which are common to both. * * NB: cinfo is required to be the first member of JPEGState, * so we can safely cast JPEGState* -> jpeg_xxx_struct* * and vice versa! */typedef struct { union { struct jpeg_compress_struct c; struct jpeg_decompress_struct d; struct jpeg_common_struct comm; } cinfo; /* NB: must be first */ jpeg_error_mgr err; /* libjpeg error manager */ JMP_BUF exit_jmpbuf; /* for catching libjpeg failures */ /* * The following two members could be a union, but * they're small enough that it's not worth the effort. */ jpeg_destination_mgr dest; /* data dest for compression */ jpeg_source_mgr src; /* data source for decompression */ /* private state */ TIFF* tif; /* back link needed by some code */ uint16 photometric; /* copy of PhotometricInterpretation */ uint16 h_sampling; /* luminance sampling factors */ uint16 v_sampling; tsize_t bytesperline; /* decompressed bytes per scanline */ /* pointers to intermediate buffers when processing downsampled data */ JSAMPARRAY ds_buffer[MAX_COMPONENTS]; int scancount; /* number of "scanlines" accumulated */ int samplesperclump; TIFFVGetMethod vgetparent; /* super-class method */ TIFFVSetMethod vsetparent; /* super-class method */ TIFFStripMethod defsparent; /* super-class method */ TIFFTileMethod deftparent; /* super-class method */ /* pseudo-tag fields */ void* jpegtables; /* JPEGTables tag value, or NULL */ uint32 jpegtables_length; /* number of bytes in same */ int jpegquality; /* Compression quality level */ int jpegcolormode; /* Auto RGB<=>YCbCr convert? */ int jpegtablesmode; /* What to put in JPEGTables */} JPEGState;#define JState(tif) ((JPEGState*)(tif)->tif_data)static int JPEGDecode(TIFF*, tidata_t, tsize_t, tsample_t);static int JPEGDecodeRaw(TIFF*, tidata_t, tsize_t, tsample_t);static int JPEGEncode(TIFF*, tidata_t, tsize_t, tsample_t);static int JPEGEncodeRaw(TIFF*, tidata_t, tsize_t, tsample_t);#define FIELD_JPEGTABLES (FIELD_CODEC+0)static const TIFFFieldInfo jpegFieldInfo[] = { { TIFFTAG_JPEGTABLES, -1,-1, TIFF_UNDEFINED, FIELD_JPEGTABLES, FALSE, TRUE, "JPEGTables" }, { TIFFTAG_JPEGQUALITY, 0, 0, TIFF_ANY, FIELD_PSEUDO, TRUE, FALSE, "" }, { TIFFTAG_JPEGCOLORMODE, 0, 0, TIFF_ANY, FIELD_PSEUDO, FALSE, FALSE, "" }, { TIFFTAG_JPEGTABLESMODE, 0, 0, TIFF_ANY, FIELD_PSEUDO, FALSE, FALSE, "" },};#define N(a) (sizeof (a) / sizeof (a[0]))/* * libjpeg interface layer. * * We use setjmp/longjmp to return control to libtiff * when a fatal error is encountered within the JPEG * library. We also direct libjpeg error and warning * messages through the appropriate libtiff handlers. *//* * Error handling routines (these replace corresponding * IJG routines from jerror.c). These are used for both * compression and decompression. */static voidTIFFjpeg_error_exit(j_common_ptr cinfo){ JPEGState *sp = (JPEGState *) cinfo; /* NB: cinfo assumed first */ char buffer[JMSG_LENGTH_MAX]; (*cinfo->err->format_message) (cinfo, buffer); TIFFError("JPEGLib", buffer); /* display the error message */ jpeg_abort(cinfo); /* clean up libjpeg state */ LONGJMP(sp->exit_jmpbuf, 1); /* return to libtiff caller */}/* * This routine is invoked only for warning messages, * since error_exit does its own thing and trace_level * is never set > 0. */static voidTIFFjpeg_output_message(j_common_ptr cinfo){ char buffer[JMSG_LENGTH_MAX]; (*cinfo->err->format_message) (cinfo, buffer); TIFFWarning("JPEGLib", buffer);}/* * Interface routines. This layer of routines exists * primarily to limit side-effects from using setjmp. * Also, normal/error returns are converted into return * values per libtiff practice. */#define CALLJPEG(sp, fail, op) (SETJMP((sp)->exit_jmpbuf) ? (fail) : (op))#define CALLVJPEG(sp, op) CALLJPEG(sp, 0, ((op),1))static intTIFFjpeg_create_compress(JPEGState* sp){ /* initialize JPEG error handling */ sp->cinfo.c.err = jpeg_std_error(&sp->err); sp->err.error_exit = TIFFjpeg_error_exit; sp->err.output_message = TIFFjpeg_output_message; return CALLVJPEG(sp, jpeg_create_compress(&sp->cinfo.c));}static intTIFFjpeg_create_decompress(JPEGState* sp){ /* initialize JPEG error handling */ sp->cinfo.d.err = jpeg_std_error(&sp->err); sp->err.error_exit = TIFFjpeg_error_exit; sp->err.output_message = TIFFjpeg_output_message; return CALLVJPEG(sp, jpeg_create_decompress(&sp->cinfo.d));}static intTIFFjpeg_set_defaults(JPEGState* sp){ return CALLVJPEG(sp, jpeg_set_defaults(&sp->cinfo.c));}static intTIFFjpeg_set_colorspace(JPEGState* sp, J_COLOR_SPACE colorspace){ return CALLVJPEG(sp, jpeg_set_colorspace(&sp->cinfo.c, colorspace));}static intTIFFjpeg_set_quality(JPEGState* sp, int quality, boolean force_baseline){ return CALLVJPEG(sp, jpeg_set_quality(&sp->cinfo.c, quality, force_baseline));}static intTIFFjpeg_suppress_tables(JPEGState* sp, boolean suppress){ return CALLVJPEG(sp, jpeg_suppress_tables(&sp->cinfo.c, suppress));}static intTIFFjpeg_start_compress(JPEGState* sp, boolean write_all_tables){ return CALLVJPEG(sp, jpeg_start_compress(&sp->cinfo.c, write_all_tables));}static intTIFFjpeg_write_scanlines(JPEGState* sp, JSAMPARRAY scanlines, int num_lines){ return CALLJPEG(sp, -1, (int) jpeg_write_scanlines(&sp->cinfo.c, scanlines, (JDIMENSION) num_lines));}static intTIFFjpeg_write_raw_data(JPEGState* sp, JSAMPIMAGE data, int num_lines){ return CALLJPEG(sp, -1, (int) jpeg_write_raw_data(&sp->cinfo.c, data, (JDIMENSION) num_lines));}static intTIFFjpeg_finish_compress(JPEGState* sp){ return CALLVJPEG(sp, jpeg_finish_compress(&sp->cinfo.c));}static intTIFFjpeg_write_tables(JPEGState* sp){ return CALLVJPEG(sp, jpeg_write_tables(&sp->cinfo.c));}static intTIFFjpeg_read_header(JPEGState* sp, boolean require_image){ return CALLJPEG(sp, -1, jpeg_read_header(&sp->cinfo.d, require_image));}static intTIFFjpeg_start_decompress(JPEGState* sp){ return CALLVJPEG(sp, jpeg_start_decompress(&sp->cinfo.d));}static intTIFFjpeg_read_scanlines(JPEGState* sp, JSAMPARRAY scanlines, int max_lines){ return CALLJPEG(sp, -1, (int) jpeg_read_scanlines(&sp->cinfo.d, scanlines, (JDIMENSION) max_lines));}static intTIFFjpeg_read_raw_data(JPEGState* sp, JSAMPIMAGE data, int max_lines){ return CALLJPEG(sp, -1, (int) jpeg_read_raw_data(&sp->cinfo.d, data, (JDIMENSION) max_lines));}static intTIFFjpeg_finish_decompress(JPEGState* sp){ return CALLJPEG(sp, -1, (int) jpeg_finish_decompress(&sp->cinfo.d));}static intTIFFjpeg_abort(JPEGState* sp){ return CALLVJPEG(sp, jpeg_abort(&sp->cinfo.comm));}static intTIFFjpeg_destroy(JPEGState* sp){ return CALLVJPEG(sp, jpeg_destroy(&sp->cinfo.comm));}static JSAMPARRAYTIFFjpeg_alloc_sarray(JPEGState* sp, int pool_id, JDIMENSION samplesperrow, JDIMENSION numrows){ return CALLJPEG(sp, (JSAMPARRAY) NULL, (*sp->cinfo.comm.mem->alloc_sarray) (&sp->cinfo.comm, pool_id, samplesperrow, numrows));}/* * JPEG library destination data manager. * These routines direct compressed data from libjpeg into the * libtiff output buffer. */static voidstd_init_destination(j_compress_ptr cinfo){ JPEGState* sp = (JPEGState*) cinfo; TIFF* tif = sp->tif; sp->dest.next_output_byte = (JOCTET*) tif->tif_rawdata; sp->dest.free_in_buffer = (size_t) tif->tif_rawdatasize;}static booleanstd_empty_output_buffer(j_compress_ptr cinfo){ JPEGState* sp = (JPEGState*) cinfo; TIFF* tif = sp->tif; /* the entire buffer has been filled */ tif->tif_rawcc = tif->tif_rawdatasize; TIFFFlushData1(tif); sp->dest.next_output_byte = (JOCTET*) tif->tif_rawdata; sp->dest.free_in_buffer = (size_t) tif->tif_rawdatasize; return (TRUE);}static voidstd_term_destination(j_compress_ptr cinfo){ JPEGState* sp = (JPEGState*) cinfo; TIFF* tif = sp->tif; tif->tif_rawcp = (tidata_t) sp->dest.next_output_byte; tif->tif_rawcc = tif->tif_rawdatasize - (tsize_t) sp->dest.free_in_buffer; /* NB: libtiff does the final buffer flush */}static voidTIFFjpeg_data_dest(JPEGState* sp, TIFF* tif){ (void) tif; sp->cinfo.c.dest = &sp->dest; sp->dest.init_destination = std_init_destination; sp->dest.empty_output_buffer = std_empty_output_buffer; sp->dest.term_destination = std_term_destination;}/* * Alternate destination manager for outputting to JPEGTables field. */static voidtables_init_destination(j_compress_ptr cinfo){ JPEGState* sp = (JPEGState*) cinfo; /* while building, jpegtables_length is allocated buffer size */ sp->dest.next_output_byte = (JOCTET*) sp->jpegtables; sp->dest.free_in_buffer = (size_t) sp->jpegtables_length;}static booleantables_empty_output_buffer(j_compress_ptr cinfo){ JPEGState* sp = (JPEGState*) cinfo; void* newbuf; /* the entire buffer has been filled; enlarge it by 1000 bytes */ newbuf = _TIFFrealloc((tdata_t) sp->jpegtables, (tsize_t) (sp->jpegtables_length + 1000)); if (newbuf == NULL) ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 100); sp->dest.next_output_byte = (JOCTET*) newbuf + sp->jpegtables_length; sp->dest.free_in_buffer = (size_t) 1000; sp->jpegtables = newbuf; sp->jpegtables_length += 1000; return (TRUE);}static voidtables_term_destination(j_compress_ptr cinfo){ JPEGState* sp = (JPEGState*) cinfo; /* set tables length to number of bytes actually emitted */ sp->jpegtables_length -= sp->dest.free_in_buffer;}static intTIFFjpeg_tables_dest(JPEGState* sp, TIFF* tif){ (void) tif; /* * Allocate a working buffer for building tables. * Initial size is 1000 bytes, which is usually adequate. */ if (sp->jpegtables) _TIFFfree(sp->jpegtables); sp->jpegtables_length = 1000; sp->jpegtables = (void*) _TIFFmalloc((tsize_t) sp->jpegtables_length); if (sp->jpegtables == NULL) { sp->jpegtables_length = 0; TIFFError("TIFFjpeg_tables_dest", "No space for JPEGTables"); return (0); } sp->cinfo.c.dest = &sp->dest; sp->dest.init_destination = tables_init_destination; sp->dest.empty_output_buffer = tables_empty_output_buffer; sp->dest.term_destination = tables_term_destination; return (1);}/* * JPEG library source data manager. * These routines supply compressed data to libjpeg. */static voidstd_init_source(j_decompress_ptr cinfo){ JPEGState* sp = (JPEGState*) cinfo; TIFF* tif = sp->tif; sp->src.next_input_byte = (const JOCTET*) tif->tif_rawdata; sp->src.bytes_in_buffer = (size_t) tif->tif_rawcc;}static booleanstd_fill_input_buffer(j_decompress_ptr cinfo){ JPEGState* sp = (JPEGState* ) cinfo; static const JOCTET dummy_EOI[2] = { 0xFF, JPEG_EOI }; /* * Should never get here since entire strip/tile is * read into memory before the decompressor is called, * and thus was supplied by init_source. */ WARNMS(cinfo, JWRN_JPEG_EOF); /* insert a fake EOI marker */ sp->src.next_input_byte = dummy_EOI; sp->src.bytes_in_buffer = 2; return (TRUE);}static voidstd_skip_input_data(j_decompress_ptr cinfo, long num_bytes){ JPEGState* sp = (JPEGState*) cinfo; if (num_bytes > 0) { if (num_bytes > (long) sp->src.bytes_in_buffer) { /* oops, buffer overrun */ (void) std_fill_input_buffer(cinfo); } else { sp->src.next_input_byte += (size_t) num_bytes; sp->src.bytes_in_buffer -= (size_t) num_bytes; } }}static voidstd_term_source(j_decompress_ptr cinfo){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -