tif_jpeg.c
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C语言 代码 · 共 1,668 行 · 第 1/4 页
C
1,668 行
/* $Header: /pack/cvsroots/wxwidgets/wxWindows/src/tiff/tif_jpeg.c,v 1.3 2004/11/19 22:29:44 VZ 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_buf
typedef 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 void
TIFFjpeg_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 void
TIFFjpeg_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 int
TIFFjpeg_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 int
TIFFjpeg_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 int
TIFFjpeg_set_defaults(JPEGState* sp)
{
return CALLVJPEG(sp, jpeg_set_defaults(&sp->cinfo.c));
}
static int
TIFFjpeg_set_colorspace(JPEGState* sp, J_COLOR_SPACE colorspace)
{
return CALLVJPEG(sp, jpeg_set_colorspace(&sp->cinfo.c, colorspace));
}
static int
TIFFjpeg_set_quality(JPEGState* sp, int quality, boolean force_baseline)
{
return CALLVJPEG(sp,
jpeg_set_quality(&sp->cinfo.c, quality, force_baseline));
}
static int
TIFFjpeg_suppress_tables(JPEGState* sp, boolean suppress)
{
return CALLVJPEG(sp, jpeg_suppress_tables(&sp->cinfo.c, suppress));
}
static int
TIFFjpeg_start_compress(JPEGState* sp, boolean write_all_tables)
{
return CALLVJPEG(sp,
jpeg_start_compress(&sp->cinfo.c, write_all_tables));
}
static int
TIFFjpeg_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 int
TIFFjpeg_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 int
TIFFjpeg_finish_compress(JPEGState* sp)
{
return CALLVJPEG(sp, jpeg_finish_compress(&sp->cinfo.c));
}
static int
TIFFjpeg_write_tables(JPEGState* sp)
{
return CALLVJPEG(sp, jpeg_write_tables(&sp->cinfo.c));
}
static int
TIFFjpeg_read_header(JPEGState* sp, boolean require_image)
{
return CALLJPEG(sp, -1, jpeg_read_header(&sp->cinfo.d, require_image));
}
static int
TIFFjpeg_start_decompress(JPEGState* sp)
{
return CALLVJPEG(sp, jpeg_start_decompress(&sp->cinfo.d));
}
static int
TIFFjpeg_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 int
TIFFjpeg_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 int
TIFFjpeg_finish_decompress(JPEGState* sp)
{
return CALLJPEG(sp, -1, (int) jpeg_finish_decompress(&sp->cinfo.d));
}
static int
TIFFjpeg_abort(JPEGState* sp)
{
return CALLVJPEG(sp, jpeg_abort(&sp->cinfo.comm));
}
static int
TIFFjpeg_destroy(JPEGState* sp)
{
return CALLVJPEG(sp, jpeg_destroy(&sp->cinfo.comm));
}
static JSAMPARRAY
TIFFjpeg_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 void
std_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 boolean
std_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 void
std_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 void
TIFFjpeg_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 void
tables_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 boolean
tables_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 + =
减小字号Ctrl + -
显示快捷键?