📄 tif_jpeg.c
字号:
/* $Header: /cvsroot/osrs/libtiff/libtiff/tif_jpeg.c,v 1.16 2003/12/20 13:47:28 dron 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>int TIFFFillStrip(TIFF*, tstrip_t);int TIFFFillTile(TIFF*, ttile_t);/* We undefine FAR to avoid conflict with JPEG definition */#ifdef FAR#undef FAR#endif/* The windows RPCNDR.H file defines boolean, but defines it with the wrong size. So we declare HAVE_BOOLEAN so that the jpeg include file won't try to typedef boolean, but #define it to override the rpcndr.h definition. http://bugzilla.remotesensing.org/show_bug.cgi?id=188*/#if defined(__RPCNDR_H__)#define HAVE_BOOLEAN#define boolean unsigned int#endif#include "jpeglib.h"#include "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 */ int cinfo_initialized; 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 */ int ycbcrsampling_fetched;} 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);static int JPEGInitializeLibJPEG( TIFF * tif );#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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -