📄 tif_ojpeg.c
字号:
{
TIFFTAG_JPEGCOLORMODE ,0 ,0 ,
TIFF_ANY ,FIELD_PSEUDO ,FALSE,FALSE,"JPEGColorMode"
}
};
static const char JPEGLib_name[]={"JPEG Library"},
bad_bps[]={"%u BitsPerSample not allowed for JPEG"},
bad_photometry[]={"PhotometricInterpretation %u not allowed for JPEG"},
bad_subsampling[]={"invalid YCbCr subsampling factor(s)"},
# ifdef never
no_write_frac[]={"fractional scan line discarded"},
# endif
no_read_frac[]={"fractional scan line not read"},
no_jtable_space[]={"No space for JPEGTables"};
/* The following diagnostic subroutines interface with and replace default
subroutines in the JPEG Library. Our basic strategy is to use "setjmp()"/
"longjmp()" in order to return control to the TIFF Library when the JPEG
library detects an error, and to use TIFF Library subroutines for displaying
diagnostic messages to a client application.
*/
static void
TIFFojpeg_error_exit(register j_common_ptr cinfo)
{
char buffer[JMSG_LENGTH_MAX];
int code = cinfo->err->msg_code;
if (((OJPEGState *)cinfo)->is_WANG) {
if (code == JERR_SOF_DUPLICATE || code == JERR_SOI_DUPLICATE)
return; /* ignore it */
}
(*cinfo->err->format_message)(cinfo,buffer);
TIFFError(JPEGLib_name,buffer); /* Display error message */
jpeg_abort(cinfo); /* Clean up JPEG Library state */
LONGJMP(((OJPEGState *)cinfo)->exit_jmpbuf,1); /* Return to TIFF client */
}
static void
TIFFojpeg_output_message(register j_common_ptr cinfo)
{ char buffer[JMSG_LENGTH_MAX];
/* This subroutine is invoked only for warning messages, since the JPEG
Library's "error_exit" method does its own thing and "trace_level" is never
set > 0.
*/
(*cinfo->err->format_message)(cinfo,buffer);
TIFFWarning(JPEGLib_name,buffer);
}
/* The following subroutines, which also interface with the JPEG Library, exist
mainly in limit the side effects of "setjmp()" and convert JPEG normal/error
conditions into TIFF Library return codes.
*/
#define CALLJPEG(sp,fail,op)(SETJMP((sp)->exit_jmpbuf)?(fail):(op))
#define CALLVJPEG(sp,op)CALLJPEG(sp,0,((op),1))
#ifdef never
static int
TIFFojpeg_create_compress(register OJPEGState *sp)
{
sp->cinfo.c.err = jpeg_std_error(&sp->err); /* Initialize error handling */
sp->err.error_exit = TIFFojpeg_error_exit;
sp->err.output_message = TIFFojpeg_output_message;
return CALLVJPEG(sp,jpeg_create_compress(&sp->cinfo.c));
}
/* The following subroutines comprise a JPEG Library "destination" data manager
by directing compressed data from the JPEG Library to a TIFF Library output
buffer.
*/
static void
std_init_destination(register j_compress_ptr cinfo){} /* "Dummy" stub */
static boolean
std_empty_output_buffer(register j_compress_ptr cinfo)
{
# define sp ((OJPEGState *)cinfo)
register TIFF *tif = sp->tif;
tif->tif_rawcc = tif->tif_rawdatasize; /* Entire buffer has been filled */
TIFFFlushData1(tif);
sp->dest.next_output_byte = (JOCTET *)tif->tif_rawdata;
sp->dest.free_in_buffer = (size_t)tif->tif_rawdatasize;
return TRUE;
# undef sp
}
static void
std_term_destination(register j_compress_ptr cinfo)
{
# define sp ((OJPEGState *)cinfo)
register TIFF *tif = sp->tif;
/* NB: The TIFF Library does the final buffer flush. */
tif->tif_rawcp = (tidata_t)sp->dest.next_output_byte;
tif->tif_rawcc = tif->tif_rawdatasize - (tsize_t)sp->dest.free_in_buffer;
# undef sp
}
/* Alternate destination manager to output JPEGTables field: */
static void
tables_init_destination(register j_compress_ptr cinfo)
{
# define sp ((OJPEGState *)cinfo)
/* The "jpegtables_length" field is the allocated buffer size while building */
sp->dest.next_output_byte = (JOCTET *)sp->jpegtables;
sp->dest.free_in_buffer = (size_t)sp->jpegtables_length;
# undef sp
}
static boolean
tables_empty_output_buffer(register j_compress_ptr cinfo)
{ void *newbuf;
# define sp ((OJPEGState *)cinfo)
/* The entire buffer has been filled, so enlarge it by 1000 bytes. */
if (!( newbuf = _TIFFrealloc( (tdata_t)sp->jpegtables
, (tsize_t)(sp->jpegtables_length + 1000)
)
)
) 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;
# undef sp
}
static void
tables_term_destination(register j_compress_ptr cinfo)
{
# define sp ((OJPEGState *)cinfo)
/* Set tables length to no. of Bytes actually emitted. */
sp->jpegtables_length -= sp->dest.free_in_buffer;
# undef sp
}
/*ARGSUSED*/ static int
TIFFojpeg_tables_dest(register OJPEGState *sp, TIFF *tif)
{
/* Allocate a working buffer for building tables. The initial size is 1000
Bytes, which is usually adequate.
*/
if (sp->jpegtables) _TIFFfree(sp->jpegtables);
if (!(sp->jpegtables = (void*)
_TIFFmalloc((tsize_t)(sp->jpegtables_length = 1000))
)
)
{
sp->jpegtables_length = 0;
TIFFError("TIFFojpeg_tables_dest",no_jtable_space);
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;
}
#else /* well, hardly ever */
static int
_notSupported(register TIFF *tif)
{ const TIFFCodec *c = TIFFFindCODEC(tif->tif_dir.td_compression);
TIFFError(tif->tif_name,"%s compression not supported",c->name);
return 0;
}
#endif /* never */
/* The following subroutines comprise a JPEG Library "source" data manager by
by directing compressed data to the JPEG Library from a TIFF Library input
buffer.
*/
static void
std_init_source(register j_decompress_ptr cinfo)
{
# define sp ((OJPEGState *)cinfo)
register TIFF *tif = sp->tif;
if (sp->src.bytes_in_buffer == 0)
{
sp->src.next_input_byte = (const JOCTET *)tif->tif_rawdata;
sp->src.bytes_in_buffer = (size_t)tif->tif_rawcc;
};
# undef sp
}
static boolean
std_fill_input_buffer(register j_decompress_ptr cinfo)
{ static const JOCTET dummy_EOI[2]={0xFF,JPEG_EOI};
# define sp ((OJPEGState *)cinfo)
/* Control should never get here, since an entire strip/tile is read into
memory before the decompressor is called; thus, data should have been
supplied by the "init_source" method. ...But, sometimes things fail.
*/
WARNMS(cinfo,JWRN_JPEG_EOF);
sp->src.next_input_byte = dummy_EOI; /* Insert a fake EOI marker */
sp->src.bytes_in_buffer = sizeof dummy_EOI;
return TRUE;
# undef sp
}
static void
std_skip_input_data(register j_decompress_ptr cinfo, long num_bytes)
{
# define sp ((OJPEGState *)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;
}
}
# undef sp
}
/*ARGSUSED*/ static void
std_term_source(register j_decompress_ptr cinfo){} /* "Dummy" stub */
/* Allocate temporary I/O buffers for downsampled data, using values computed in
"jpeg_start_{de}compress()". We use the JPEG Library's allocator so that
buffers will be released automatically when done with a strip/tile. This is
also a handy place to compute samplesperclump, bytesperline, etc.
*/
static int
alloc_downsampled_buffers(TIFF *tif,jpeg_component_info *comp_info,
int num_components)
{ register OJPEGState *sp = OJState(tif);
sp->samplesperclump = 0;
if (num_components > 0)
{ tsize_t size = sp->cinfo.comm.is_decompressor
# ifdef D_LOSSLESS_SUPPORTED
? sp->cinfo.d.min_codec_data_unit
# else
? DCTSIZE
# endif
# ifdef C_LOSSLESS_SUPPORTED
: sp->cinfo.c.data_unit;
# else
: DCTSIZE;
# endif
int ci = 0;
register jpeg_component_info *compptr = comp_info;
do
{ JSAMPARRAY buf;
sp->samplesperclump +=
compptr->h_samp_factor * compptr->v_samp_factor;
# if defined(C_LOSSLESS_SUPPORTED) || defined(D_LOSSLESS_SUPPORTED)
if (!(buf = CALLJPEG(sp,0,(*sp->cinfo.comm.mem->alloc_sarray)(&sp->cinfo.comm,JPOOL_IMAGE,compptr->width_in_data_units*size,compptr->v_samp_factor*size))))
# else
if (!(buf = CALLJPEG(sp,0,(*sp->cinfo.comm.mem->alloc_sarray)(&sp->cinfo.comm,JPOOL_IMAGE,compptr->width_in_blocks*size,compptr->v_samp_factor*size))))
# endif
return 0;
sp->ds_buffer[ci] = buf;
}
while (++compptr,++ci < num_components);
};
return 1;
}
#ifdef never
/* JPEG Encoding begins here. */
/*ARGSUSED*/ static int
OJPEGEncode(register TIFF *tif,tidata_t buf,tsize_t cc,tsample_t s)
{ tsize_t rows; /* No. of unprocessed rows in file */
register OJPEGState *sp = OJState(tif);
/* Encode a chunk of pixels, where returned data is NOT down-sampled (the
standard case). The data is expected to be written in scan-line multiples.
*/
if (cc % sp->bytesperline) TIFFWarning(tif->tif_name,no_write_frac);
if ( (cc /= bytesperline) /* No. of complete rows in caller's buffer */
> (rows = sp->cinfo.c.image_height - sp->cinfo.c.next_scanline)
) cc = rows;
while (--cc >= 0)
{
if ( CALLJPEG(sp,-1,jpeg_write_scanlines(&sp->cinfo.c,(JSAMPARRAY)&buf,1))
!= 1
) return 0;
++tif->tif_row;
buf += sp->bytesperline;
};
return 1;
}
/*ARGSUSED*/ static int
OJPEGEncodeRaw(register TIFF *tif,tidata_t buf,tsize_t cc,tsample_t s)
{ tsize_t rows; /* No. of unprocessed rows in file */
JDIMENSION lines_per_MCU, size;
register OJPEGState *sp = OJState(tif);
/* Encode a chunk of pixels, where returned data is down-sampled as per the
sampling factors. The data is expected to be written in scan-line
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -