📄 tif_ojpeg.c
字号:
multiples.
*/
cc /= sp->bytesperline;
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;
# ifdef C_LOSSLESS_SUPPORTED
lines_per_MCU = sp->cinfo.c.max_samp_factor*(size = sp->cinfo.d.data_unit);
# else
lines_per_MCU = sp->cinfo.c.max_samp_factor*(size = DCTSIZE);
# endif
while (--cc >= 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)
# ifdef C_LOSSLESS_SUPPORTED
( compptr->width_in_data_units * size
# else
( compptr->width_in_blocks * size
# endif
- clumps_per_line * compptr->h_samp_factor
);
if (compptr->h_samp_factor == 1) /* Cb & Cr fast path */
do *outptr++ = *inptr;
while ((inptr += sp->samplesperclump),--clumps_per_line > 0);
else /* general case */
do
{
xpos = 0;
do *outptr++ = inptr[xpos];
while (++xpos < compptr->h_samp_factor);
}
while ((inptr += sp->samplesperclump),--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 >= size)
{
if ( CALLJPEG(sp,-1,jpeg_write_raw_data(&sp->cinfo.c,sp->ds_buffer,lines_per_MCU))
!= lines_per_MCU
) return 0;
sp->scancount = 0;
};
++tif->tif_row++
buf += sp->bytesperline;
};
return 1;
}
static int
OJPEGSetupEncode(register TIFF *tif)
{ static const char module[]={"OJPEGSetupEncode"};
uint32 segment_height, segment_width;
int status = 1; /* Assume success by default */
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 != 8)
{
TIFFError(module,bad_bps,td->td_bitspersample);
status = 0;
};
/* The TIFF Version 6.0 specification and IJG JPEG Library accept different
sets of color spaces, so verify that our image belongs to the common subset
and map its photometry code, then initialize to handle subsampling and
optional JPEG Library YCbCr <-> RGB color-space conversion.
*/
switch (td->td_photometric)
{
case PHOTOMETRIC_YCBCR :
/* ISO IS 10918-1 requires that JPEG subsampling factors be 1-4, but
TIFF Version 6.0 is more restrictive: only 1, 2, and 4 are allowed.
*/
if ( ( td->td_ycbcrsubsampling[0] == 1
|| td->td_ycbcrsubsampling[0] == 2
|| td->td_ycbcrsubsampling[0] == 4
)
&& ( td->td_ycbcrsubsampling[1] == 1
|| td->td_ycbcrsubsampling[1] == 2
|| td->td_ycbcrsubsampling[1] == 4
)
)
sp->cinfo.c.raw_data_in =
( (sp->h_sampling = td->td_ycbcrsubsampling[0]) << 3
| (sp->v_sampling = td->td_ycbcrsubsampling[1])
) != 011;
else
{
TIFFError(module,bad_subsampling);
status = 0;
};
/* A ReferenceBlackWhite field MUST be present, since the default value
is inapproriate for YCbCr. Fill in the proper value if the
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);
};
sp->cinfo.c.jpeg_color_space = JCS_YCbCr;
if (sp->jpegcolormode == JPEGCOLORMODE_RGB)
{
sp->cinfo.c.raw_data_in = FALSE;
sp->in_color_space = JCS_RGB;
break;
};
goto L2;
case PHOTOMETRIC_MINISBLACK:
sp->cinfo.c.jpeg_color_space = JCS_GRAYSCALE;
goto L1;
case PHOTOMETRIC_RGB :
sp->cinfo.c.jpeg_color_space = JCS_RGB;
goto L1;
case PHOTOMETRIC_SEPARATED :
sp->cinfo.c.jpeg_color_space = JCS_CMYK;
L1: sp->jpegcolormode = JPEGCOLORMODE_RAW; /* No JPEG Lib. conversion */
L2: sp->cinfo.d.in_color_space = sp->cinfo.d.jpeg_color-space;
break;
default :
TIFFError(module,bad_photometry,td->td_photometric);
status = 0;
};
tif->tif_encoderow = tif->tif_encodestrip = tif->tif_encodetile =
sp->cinfo.c.raw_data_in ? OJPEGEncodeRaw : OJPEGEncode;
if (isTiled(tif))
{ tsize_t size;
# ifdef C_LOSSLESS_SUPPORTED
if ((size = sp->v_sampling*sp->cinfo.c.data_unit) < 16) size = 16;
# else
if ((size = sp->v_sampling*DCTSIZE) < 16) size = 16;
# endif
if ((segment_height = td->td_tilelength) % size)
{
TIFFError(module,"JPEG tile height must be multiple of %d",size);
status = 0;
};
# ifdef C_LOSSLESS_SUPPORTED
if ((size = sp->h_sampling*sp->cinfo.c.data_unit) < 16) size = 16;
# else
if ((size = sp->h_sampling*DCTSIZE) < 16) size = 16;
# endif
if ((segment_width = td->td_tilewidth) % size)
{
TIFFError(module,"JPEG tile width must be multiple of %d",size);
status = 0;
};
sp->bytesperline = TIFFTileRowSize(tif);
}
else
{ tsize_t size;
# ifdef C_LOSSLESS_SUPPORTED
if ((size = sp->v_sampling*sp->cinfo.c.data_unit) < 16) size = 16;
# else
if ((size = sp->v_sampling*DCTSIZE) < 16) size = 16;
# endif
if (td->td_rowsperstrip < (segment_height = td->td_imagelength))
{
if (td->td_rowsperstrip % size)
{
TIFFError(module,"JPEG RowsPerStrip must be multiple of %d",size);
status = 0;
};
segment_height = td->td_rowsperstrip;
};
segment_width = td->td_imagewidth;
sp->bytesperline = tif->tif_scanlinesize;
};
if (segment_width > 65535 || segment_height > 65535)
{
TIFFError(module,"Strip/tile too large for JPEG");
status = 0;
};
/* Initialize all JPEG parameters to default values. Note that the JPEG
Library's "jpeg_set_defaults()" method needs legal values for the
"in_color_space" and "input_components" fields.
*/
sp->cinfo.c.input_components = 1; /* Default for JCS_UNKNOWN */
if (!CALLVJPEG(sp,jpeg_set_defaults(&sp->cinfo.c))) status = 0;
switch (sp->jpegtablesmode & (JPEGTABLESMODE_HUFF|JPEGTABLESMODE_QUANT))
{ register JHUFF_TBL *htbl;
register JQUANT_TBL *qtbl;
case 0 :
sp->cinfo.c.optimize_coding = TRUE;
case JPEGTABLESMODE_HUFF :
if (!CALLVJPEG(sp,jpeg_set_quality(&sp->cinfo.c,sp->jpegquality,FALSE)))
return 0;
if (qtbl = sp->cinfo.c.quant_tbl_ptrs[0]) qtbl->sent_table = FALSE;
if (qtbl = sp->cinfo.c.quant_tbl_ptrs[1]) qtbl->sent_table = FALSE;
goto L3;
case JPEGTABLESMODE_QUANT :
sp->cinfo.c.optimize_coding = TRUE;
/* We do not support application-supplied JPEG tables, so mark the field
"not present".
*/
L3: TIFFClrFieldBit(tif,FIELD_JPEGTABLES);
break;
case JPEGTABLESMODE_HUFF|JPEGTABLESMODE_QUANT:
if ( !CALLVJPEG(sp,jpeg_set_quality(&sp->cinfo.c,sp->jpegquality,FALSE))
|| !CALLVJPEG(sp,jpeg_suppress_tables(&sp->cinfo.c,TRUE))
)
{
status = 0;
break;
};
if (qtbl = sp->cinfo.c.quant_tbl_ptrs[0]) qtbl->sent_table = FALSE;
if (htbl = sp->cinfo.c.dc_huff_tbl_ptrs[0]) htbl->sent_table = FALSE;
if (htbl = sp->cinfo.c.ac_huff_tbl_ptrs[0]) htbl->sent_table = FALSE;
if (sp->cinfo.c.jpeg_color_space == JCS_YCbCr)
{
if (qtbl = sp->cinfo.c.quant_tbl_ptrs[1])
qtbl->sent_table = FALSE;
if (htbl = sp->cinfo.c.dc_huff_tbl_ptrs[1])
htbl->sent_table = FALSE;
if (htbl = sp->cinfo.c.ac_huff_tbl_ptrs[1])
htbl->sent_table = FALSE;
};
if ( TIFFojpeg_tables_dest(sp,tif)
&& CALLVJPEG(sp,jpeg_write_tables(&sp->cinfo.c))
)
{
/* Mark the field "present". We can't use "TIFFSetField()" because
"BEENWRITING" is already set!
*/
TIFFSetFieldBit(tif,FIELD_JPEGTABLES);
tif->tif_flags |= TIFF_DIRTYDIRECT;
}
else status = 0;
};
if ( sp->cinfo.c.raw_data_in
&& !alloc_downsampled_buffers(tif,sp->cinfo.c.comp_info,
sp->cinfo.c.num_components)
) status = 0;
if (status == 0) return 0; /* If TIFF errors, don't bother to continue */
/* Grab parameters that are same for all strips/tiles. */
sp->dest.init_destination = std_init_destination;
sp->dest.empty_output_buffer = std_empty_output_buffer;
sp->dest.term_destination = std_term_destination;
sp->cinfo.c.dest = &sp->dest;
sp->cinfo.c.data_precision = td->td_bitspersample;
sp->cinfo.c.write_JFIF_header = /* Don't write extraneous markers */
sp->cinfo.c.write_Adobe_marker = FALSE;
sp->cinfo.c.image_width = segment_width;
sp->cinfo.c.image_height = segment_height;
sp->cinfo.c.comp_info[0].h_samp_factor =
sp->cinfo.c.comp_info[0].v_samp_factor = 1;
return CALLVJPEG(sp,jpeg_start_compress(&sp->cinfo.c,FALSE));
# undef td
}
static int
OJPEGPreEncode(register TIFF *tif,tsample_t s)
{ register OJPEGState *sp = OJState(tif);
# define td (&tif->tif_dir)
/* If we are about to write the first row of an image plane, which should
coincide with a JPEG "scan", reset the JPEG Library's compressor. Otherwise
let the compressor run "as is" and return a "success" status without further
ado.
*/
if ( (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip)
% td->td_stripsperimage
== 0
)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -