📄 tif_ojpeg.c
字号:
(int)sp->photometric);
return 0;
/* TIFF 6.0 forbids subsampling of all other color spaces */
default: sp->h_sampling = sp->v_sampling = 1;
};
sp->cinfo.c.data_precision = td->td_bitspersample;
if (isTiled(tif))
{
if (td->td_tilelength % (sp->v_sampling*DCTSIZE))
{
TIFFError(module,"JPEG tile height must be multiple of %d",
sp->v_sampling*DCTSIZE);
return 0;
};
if (td->td_tilewidth % (sp->h_sampling*DCTSIZE))
{
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))
)
{
TIFFError(module,"RowsPerStrip must be multiple of %d for JPEG",
sp->v_sampling*DCTSIZE);
return 0;
};
if (sp->jpegtablesmode & (JPEGTABLESMODE_QUANT|JPEGTABLESMODE_HUFF))
{ /* create a JPEGTables field */
if (!prepare_JPEGTables(tif)) return 0;
/* Mark the field "present". We can't use "TIFFSetField()" because
"BEENWRITING" is already set!
*/
TIFFSetFieldBit(tif,FIELD_JPEGTABLES);
tif->tif_flags |= TIFF_DIRTYDIRECT;
}
else
/* We do not support application-supplied JPEG tables, so mark the field
"not present".
*/
TIFFClrFieldBit(tif,FIELD_JPEGTABLES);
TIFFojpeg_data_dest(sp,tif); /* send JPEG output to TIFF Library's buffer */
return 1;
# undef td
}
/*ARGSUSED*/ static int
OJPEGEncode(register TIFF *tif,tidata_t buf,tsize_t cc,tsample_t s)
{ 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);
cc /= sp->bytesperline;
while (--cc >= 0)
{ JSAMPROW bufptr = (JSAMPROW)buf;
if (TIFFojpeg_write_scanlines(sp,&bufptr,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)
{ 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
multiples.
*/
if (cc % sp->bytesperline) TIFFWarning(tif->tif_name,no_write_frac);
cc /= sp->bytesperline;
while (--cc >= 0)
{
if (sp->cinfo.c.num_components > 0)
{ int ci = 0, clumpoffset = 0;
register jpeg_component_info *compptr = sp->cinfo.c.comp_info;
/* The fastest way to separate the data is to make 1 pass over the scan
line for each row of each component.
*/
do
{ int ypos = 0;
do
{ int padding;
register JSAMPLE *inptr = (JSAMPLE*)buf + clumpoffset,
*outptr =
sp->ds_buffer[ci][sp->scancount*compptr->v_samp_factor+ypos];
/* Cb,Cr both have sampling factors 1, so this is correct */
register int clumps_per_line =
sp->cinfo.c.comp_info[1].downsampled_width,
xpos;
padding = (int)
( compptr->width_in_blocks * DCTSIZE
- clumps_per_line * compptr->h_samp_factor
);
if (compptr->h_samp_factor == 1) /* Cb & Cr fast path */
do
{
*outptr++ = inptr[0];
inptr += sp->samplesperclump;
}
while (--clumps_per_line > 0);
else /* general case */
do
{
xpos = 0;
do *outptr++ = inptr[xpos];
while (++xpos < compptr->h_samp_factor);
inptr += sp->samplesperclump;
}
while (--clumps_per_line > 0);
xpos = 0; /* Pad each scan line as needed */
do outptr[0]=outptr[-1]; while (++outptr,++xpos < padding);
clumpoffset += compptr->h_samp_factor;
}
while (++ypos < compptr->v_samp_factor);
}
while (++compptr,++ci < sp->cinfo.c.num_components);
};
if (++sp->scancount >= DCTSIZE)
{ int n = sp->cinfo.c.max_v_samp_factor*DCTSIZE;
if (TIFFojpeg_write_raw_data(sp,sp->ds_buffer,n) != n) return 0;
sp->scancount = 0;
};
++tif->tif_row++
buf += sp->bytesperline;
};
return 1;
}
static int
OJPEGPreEncode(register TIFF *tif,tsample_t s)
{ static const char module[]={"OJPEGPreEncode"};
uint32 segment_width, segment_height;
int downsampled_input = FALSE;
register OJPEGState *sp = OJState(tif);
# define td (&tif->tif_dir)
/* Set encoding state at the start of a strip or tile. */
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 (!TIFFojpeg_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 (!TIFFojpeg_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 (!TIFFojpeg_set_colorspace(sp,JCS_UNKNOWN)) return 0;
sp->cinfo.c.comp_info[0].component_id = s;
/* "jpeg_set_colorspace()" set all sampling factors to 1. */
if (sp->photometric == PHOTOMETRIC_YCBCR && s > 0)
sp->cinfo.c.comp_info[0].quant_tbl_no =
sp->cinfo.c.comp_info[0].dc_tbl_no =
sp->cinfo.c.comp_info[0].ac_tbl_no = 1;
};
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)
{
/* Scale the expected 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;
sp->cinfo.c.write_JFIF_header = /* Don't write extraneous markers */
sp->cinfo.c.write_Adobe_marker = FALSE;
if (!(sp->jpegtablesmode & JPEGTABLESMODE_QUANT)) /* setup table handling */
{
if (!TIFFojpeg_set_quality(sp,sp->jpegquality,FALSE)) return 0;
unsuppress_quant_table(sp,0);
unsuppress_quant_table(sp,1);
};
sp->cinfo.c.optimize_coding = !(sp->jpegtablesmode & JPEGTABLESMODE_HUFF);
tif->tif_encoderow = tif->tif_encodestrip = tif->tif_encodetile =
(sp->cinfo.c.raw_data_in = downsampled_input)
? OJPEGEncodeRaw : OJPEGEncode;
if ( !TIFFojpeg_start_compress(sp,FALSE) /* start JPEG compressor */
|| downsampled_input /* allocate downsampled-data buffers */
&& !alloc_downsampled_buffers(tif,sp->cinfo.c.comp_info,
sp->cinfo.c.num_components)
) return 0;
sp->scancount = 0;
return 1;
# undef td
}
static int
OJPEGPostEncode(register TIFF *tif)
{ register OJPEGState *sp = OJState(tif);
/* Finish up at the end of a strip or tile. */
if (sp->scancount > 0) /* emit partial buffer of down-sampled data */
{
if (sp->scancount < DCTSIZE && sp->cinfo.c.num_components > 0)
{ int ci = 0, n; /* Pad the data vertically */
register jpeg_component_info *compptr = sp->cinfo.c.comp_info;
do
{ tsize_t row_width =
compptr->width_in_blocks*DCTSIZE*sizeof(JSAMPLE);
int ypos = sp->scancount*compptr->v_samp_factor;
do _TIFFmemcpy( (tdata_t)sp->ds_buffer[ci][ypos]
, (tdata_t)sp->ds_buffer[ci][ypos-1]
, row_width
);
while (++ypos < compptr->v_samp_factor*DCTSIZE);
}
while (++compptr,++ci < sp->cinfo.c.num_components);
};
n = sp->cinfo.c.max_v_samp_factor*DCTSIZE;
if (TIFFojpeg_write_raw_data(sp,sp->ds_buffer,n) != n) return 0;
};
return TIFFojpeg_finish_compress(sp);
}
#endif /* never */
/* JPEG Decoding begins here. */
static int
OJPEGSetupDecode(register TIFF *tif)
{ static const char module[]={"OJPEGSetupDecode"};
register OJPEGState *sp = OJState(tif);
# define td (&tif->tif_dir)
/* Verify miscellaneous parameters. This will need work if the TIFF Library
ever supports different depths for different components, or if the JPEG
Library ever supports run-time depth selection. Neither seems imminent.
*/
if (td->td_bitspersample != BITS_IN_JSAMPLE)
{
TIFFError(module,bad_bps,td->td_bitspersample);
return 0;
};
/* Almost all old JPEG-in-TIFF encapsulations use 8 bits per sample, but the
following is just a "sanity check", since "OJPEGPreDecode()" actually
depends upon this assumption in certain cases.
*/
if (td->td_bitspersample != 8)
{
TIFFError(module,"Cannot decompress %u bits per sample");
return 0;
};
/* Grab parameters that are same for all strips/tiles. */
if ((sp->photometric = td->td_photometric) == PHOTOMETRIC_YCBCR)
{
sp->h_sampling = td->td_ycbcrsubsampling[0];
sp->v_sampling = td->td_ycbcrsubsampling[1];
}
else /* TIFF 6.0 forbids subsampling of all other color spaces */
sp->h_sampling = sp->v_sampling = 1;
sp->cinfo.d.src = &sp->src;
sp->src.init_source = std_init_source;
sp->src.fill_input_buffer = std_fill_input_buffer;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -