?? tif_jpeg.c
字號:
/* Reload downsampled-data buffer if needed */
if (sp->scancount >= DCTSIZE) {
int n = sp->cinfo.d.max_v_samp_factor * DCTSIZE;
if (TIFFjpeg_read_raw_data(sp, sp->ds_buffer, n)
!= n)
return (0);
sp->scancount = 0;
}
/*
* Fastest way to unseparate data is to make one pass
* over the scanline for each row of each component.
*/
clumpoffset = 0; /* first sample in clump */
for (ci = 0, compptr = sp->cinfo.d.comp_info;
ci < sp->cinfo.d.num_components;
ci++, compptr++) {
int hsamp = compptr->h_samp_factor;
int vsamp = compptr->v_samp_factor;
int ypos;
for (ypos = 0; ypos < vsamp; ypos++) {
JSAMPLE *inptr = sp->ds_buffer[ci][sp->scancount*vsamp + ypos];
JSAMPLE *outptr = (JSAMPLE*)buf + clumpoffset;
JDIMENSION nclump;
if (hsamp == 1) {
/* fast path for at least Cb and Cr */
for (nclump = clumps_per_line; nclump-- > 0; ) {
outptr[0] = *inptr++;
outptr += samples_per_clump;
}
} else {
int xpos;
/* general case */
for (nclump = clumps_per_line; nclump-- > 0; ) {
for (xpos = 0; xpos < hsamp; xpos++)
outptr[xpos] = *inptr++;
outptr += samples_per_clump;
}
}
clumpoffset += hsamp;
}
}
++sp->scancount;
++tif->tif_row;
buf += sp->bytesperline;
cc -= sp->bytesperline;
} while (--nrows > 0);
}
/* Close down the decompressor if done. */
return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height
|| TIFFjpeg_finish_decompress(sp);
}
/*
* JPEG Encoding.
*/
static void
unsuppress_quant_table (JPEGState* sp, int tblno)
{
JQUANT_TBL* qtbl;
if ((qtbl = sp->cinfo.c.quant_tbl_ptrs[tblno]) != NULL)
qtbl->sent_table = FALSE;
}
static void
unsuppress_huff_table (JPEGState* sp, int tblno)
{
JHUFF_TBL* htbl;
if ((htbl = sp->cinfo.c.dc_huff_tbl_ptrs[tblno]) != NULL)
htbl->sent_table = FALSE;
if ((htbl = sp->cinfo.c.ac_huff_tbl_ptrs[tblno]) != NULL)
htbl->sent_table = FALSE;
}
static int
prepare_JPEGTables(TIFF* tif)
{
JPEGState* sp = JState(tif);
JPEGInitializeLibJPEG( tif );
/* Initialize quant tables for current quality setting */
if (!TIFFjpeg_set_quality(sp, sp->jpegquality, FALSE))
return (0);
/* Mark only the tables we want for output */
/* NB: chrominance tables are currently used only with YCbCr */
if (!TIFFjpeg_suppress_tables(sp, TRUE))
return (0);
if (sp->jpegtablesmode & JPEGTABLESMODE_QUANT) {
unsuppress_quant_table(sp, 0);
if (sp->photometric == PHOTOMETRIC_YCBCR)
unsuppress_quant_table(sp, 1);
}
if (sp->jpegtablesmode & JPEGTABLESMODE_HUFF) {
unsuppress_huff_table(sp, 0);
if (sp->photometric == PHOTOMETRIC_YCBCR)
unsuppress_huff_table(sp, 1);
}
/* Direct libjpeg output into jpegtables */
if (!TIFFjpeg_tables_dest(sp, tif))
return (0);
/* Emit tables-only datastream */
if (!TIFFjpeg_write_tables(sp))
return (0);
return (1);
}
static int
JPEGSetupEncode(TIFF* tif)
{
JPEGState* sp = JState(tif);
TIFFDirectory *td = &tif->tif_dir;
static const char module[] = "JPEGSetupEncode";
JPEGInitializeLibJPEG( tif );
assert(sp != NULL);
assert(!sp->cinfo.comm.is_decompressor);
/*
* Initialize all JPEG parameters to default values.
* Note that jpeg_set_defaults needs legal values for
* in_color_space and input_components.
*/
sp->cinfo.c.in_color_space = JCS_UNKNOWN;
sp->cinfo.c.input_components = 1;
if (!TIFFjpeg_set_defaults(sp))
return (0);
/* Set per-file parameters */
sp->photometric = td->td_photometric;
switch (sp->photometric) {
case PHOTOMETRIC_YCBCR:
sp->h_sampling = td->td_ycbcrsubsampling[0];
sp->v_sampling = td->td_ycbcrsubsampling[1];
/*
* A ReferenceBlackWhite field *must* be present since the
* default value is inappropriate for YCbCr. Fill in the
* proper value if application didn't set it.
*/
if (!TIFFFieldSet(tif, FIELD_REFBLACKWHITE)) {
float refbw[6];
long top = 1L << td->td_bitspersample;
refbw[0] = 0;
refbw[1] = (float)(top-1L);
refbw[2] = (float)(top>>1);
refbw[3] = refbw[1];
refbw[4] = refbw[2];
refbw[5] = refbw[1];
TIFFSetField(tif, TIFFTAG_REFERENCEBLACKWHITE, refbw);
}
break;
case PHOTOMETRIC_PALETTE: /* disallowed by Tech Note */
case PHOTOMETRIC_MASK:
TIFFError(module,
"PhotometricInterpretation %d not allowed for JPEG",
(int) sp->photometric);
return (0);
default:
/* TIFF 6.0 forbids subsampling of all other color spaces */
sp->h_sampling = 1;
sp->v_sampling = 1;
break;
}
/* Verify miscellaneous parameters */
/*
* This would need work if libtiff ever supports different
* depths for different components, or if libjpeg ever supports
* run-time selection of depth. Neither is imminent.
*/
if (td->td_bitspersample != BITS_IN_JSAMPLE) {
TIFFError(module, "BitsPerSample %d not allowed for JPEG",
(int) td->td_bitspersample);
return (0);
}
sp->cinfo.c.data_precision = td->td_bitspersample;
if (isTiled(tif)) {
if ((td->td_tilelength % (sp->v_sampling * DCTSIZE)) != 0) {
TIFFError(module,
"JPEG tile height must be multiple of %d",
sp->v_sampling * DCTSIZE);
return (0);
}
if ((td->td_tilewidth % (sp->h_sampling * DCTSIZE)) != 0) {
TIFFError(module,
"JPEG tile width must be multiple of %d",
sp->h_sampling * DCTSIZE);
return (0);
}
} else {
if (td->td_rowsperstrip < td->td_imagelength &&
(td->td_rowsperstrip % (sp->v_sampling * DCTSIZE)) != 0) {
TIFFError(module,
"RowsPerStrip must be multiple of %d for JPEG",
sp->v_sampling * DCTSIZE);
return (0);
}
}
/* Create a JPEGTables field if appropriate */
if (sp->jpegtablesmode & (JPEGTABLESMODE_QUANT|JPEGTABLESMODE_HUFF)) {
if (!prepare_JPEGTables(tif))
return (0);
/* Mark the field present */
/* Can't use TIFFSetField since BEENWRITING is already set! */
TIFFSetFieldBit(tif, FIELD_JPEGTABLES);
tif->tif_flags |= TIFF_DIRTYDIRECT;
} else {
/* We do not support application-supplied JPEGTables, */
/* so mark the field not present */
TIFFClrFieldBit(tif, FIELD_JPEGTABLES);
}
/* Direct libjpeg output to libtiff's output buffer */
TIFFjpeg_data_dest(sp, tif);
return (1);
}
/*
* Set encoding state at the start of a strip or tile.
*/
static int
JPEGPreEncode(TIFF* tif, tsample_t s)
{
JPEGState *sp = JState(tif);
TIFFDirectory *td = &tif->tif_dir;
static const char module[] = "JPEGPreEncode";
uint32 segment_width, segment_height;
int downsampled_input;
assert(sp != NULL);
assert(!sp->cinfo.comm.is_decompressor);
/*
* Set encoding parameters for this strip/tile.
*/
if (isTiled(tif)) {
segment_width = td->td_tilewidth;
segment_height = td->td_tilelength;
sp->bytesperline = TIFFTileRowSize(tif);
} else {
segment_width = td->td_imagewidth;
segment_height = td->td_imagelength - tif->tif_row;
if (segment_height > td->td_rowsperstrip)
segment_height = td->td_rowsperstrip;
sp->bytesperline = TIFFScanlineSize(tif);
}
if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0) {
/* for PC 2, scale down the strip/tile size
* to match a downsampled component
*/
segment_width = TIFFhowmany(segment_width, sp->h_sampling);
segment_height = TIFFhowmany(segment_height, sp->v_sampling);
}
if (segment_width > 65535 || segment_height > 65535) {
TIFFError(module, "Strip/tile too large for JPEG");
return (0);
}
sp->cinfo.c.image_width = segment_width;
sp->cinfo.c.image_height = segment_height;
downsampled_input = FALSE;
if (td->td_planarconfig == PLANARCONFIG_CONTIG) {
sp->cinfo.c.input_components = td->td_samplesperpixel;
if (sp->photometric == PHOTOMETRIC_YCBCR) {
if (sp->jpegcolormode == JPEGCOLORMODE_RGB) {
sp->cinfo.c.in_color_space = JCS_RGB;
} else {
sp->cinfo.c.in_color_space = JCS_YCbCr;
if (sp->h_sampling != 1 || sp->v_sampling != 1)
downsampled_input = TRUE;
}
if (!TIFFjpeg_set_colorspace(sp, JCS_YCbCr))
return (0);
/*
* Set Y sampling factors;
* we assume jpeg_set_colorspace() set the rest to 1
*/
sp->cinfo.c.comp_info[0].h_samp_factor = sp->h_sampling;
sp->cinfo.c.comp_info[0].v_samp_factor = sp->v_sampling;
} else {
sp->cinfo.c.in_color_space = JCS_UNKNOWN;
if (!TIFFjpeg_set_colorspace(sp, JCS_UNKNOWN))
return (0);
/* jpeg_set_colorspace set all sampling factors to 1 */
}
} else {
sp->cinfo.c.input_components = 1;
sp->cinfo.c.in_color_space = JCS_UNKNOWN;
if (!TIFFjpeg_set_colorspace(sp, JCS_UNKNOWN))
return (0);
sp->cinfo.c.comp_info[0].component_id = s;
/* jpeg_set_colorspace() set sampling factors to 1 */
if (sp->photometric == PHOTOMETRIC_YCBCR && s > 0) {
sp->cinfo.c.comp_info[0].quant_tbl_no = 1;
sp->cinfo.c.comp_info[0].dc_tbl_no = 1;
sp->cinfo.c.comp_info[0].ac_tbl_no = 1;
}
}
/* ensure libjpeg won't write any extraneous markers */
sp->cinfo.c.write_JFIF_header = FALSE;
sp->cinfo.c.write_Adobe_marker = FALSE;
/* set up table handling correctly */
if (! (sp->jpegtablesmode & JPEGTABLESMODE_QUANT)) {
if (!TIFFjpeg_set_quality(sp, sp->jpegquality, FALSE))
return (0);
unsuppress_quant_table(sp, 0);
unsuppress_quant_table(sp, 1);
}
if (sp->jpegtablesmode & JPEGTABLESMODE_HUFF)
sp->cinfo.c.optimize_coding = FALSE;
else
sp->cinfo.c.optimize_coding = TRUE;
if (downsampled_input) {
/* Need to use raw-data interface to libjpeg */
sp->cinfo.c.raw_data_in = TRUE;
tif->tif_encoderow = JPEGEncodeRaw;
tif->tif_encodestrip = JPEGEncodeRaw;
tif->tif_encodetile = JPEGEncodeRaw;
} else {
/* Use normal interface to libjpeg */
sp->cinfo.c.raw_data_in = FALSE;
tif->tif_encoderow = JPEGEncode;
tif->tif_encodestrip = JPEGEncode;
tif->tif_encodetile = JPEGEncode;
}
/* Start JPEG compressor */
if (!TIFFjpeg_start_compress(sp, FALSE))
return (0);
/* Allocate downsampled-data buffers if needed */
if (downsampled_input) {
if (!alloc_downsampled_buffers(tif, sp->cinfo.c.comp_info,
sp->cinfo.c.num_components))
return (0);
}
sp->scancount = 0;
return (1);
}
/*
* Encode a chunk of pixels.
* "Standard" case: incoming data is not downsampled.
*/
static int
JPEGEncode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s)
{
JPEGState *sp = JState(tif);
tsize_t nrows;
JSAMPROW bufptr[1];
(void) s;
assert(sp != NULL);
/* data is expected to be supplied in multiples of a scanline */
nrows = cc / sp->bytesperline;
if (cc % sp->bytesperline)
TIFFWarning(tif->tif_name, "fractional scanline discarded");
while (nrows-- > 0) {
bufptr[0] = (JSAMPROW) buf;
if (TIFFjpeg_write_scanlines(sp, bufptr, 1) != 1)
return (0);
if (nrows > 0)
tif->tif_row++;
buf += sp->bytesperline;
}
return (1);
}
/*
* Encode a chunk of pixels.
* Incoming data is expected to be downsampled per sampling factors.
*/
static int
JPEGEncodeRaw(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s)
{
JPEGState *sp = JState(tif);
JSAMPLE* inptr;
JSAMPLE* outptr;
tsize_t nrows;
JDIMENSION clumps_per_line, nclump;
int clumpoffset, ci, xpos, ypos;
jpeg_component_info* compptr;
int samples_per_clump = sp->samplesperclump;
(void) s;
assert(sp != NULL);
/* data is expected to be supplied in multiples of a scanline */
nrows = cc / sp->bytesperline;
if (cc % sp->bytesperline)
TIFFWarning(tif->tif_name, "fractional scanline discarded");
/* Cb,Cr both have sampling factors 1, so this is correct */
clumps_per_line = sp->cinfo.c.comp_info[1].downsampled_width;
while (nrows-- > 0) {
/*
* Fastest way to separate the data is to make one pass
* over the scanline for each row of each component.
*/
clumpoffset = 0; /* first sample in clump */
for (ci = 0, compptr = sp->cinfo.c.comp_info;
ci < sp->cinfo.c.num_components;
ci++, compptr++) {
int hsamp = compptr->h_samp_factor;
int vsamp = compptr->v_samp_factor;
int padding = (int) (compptr->width_in_blocks * DCTSIZE -
clumps_per_line * hsamp);
for (ypos = 0; ypos < vsamp; ypos++) {
inptr = ((JSAMPLE*) buf) + clumpoffset;
outptr = sp->ds_buffer[ci][sp->scancount*vsamp + ypos];
if (hsamp == 1) {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -