mirror of
https://github.com/beard7n/bsdports.git
synced 2026-04-10 18:41:17 +02:00
561 lines
20 KiB
C
561 lines
20 KiB
C
--- transupp.c.orig 2011-10-26 13:20:05.000000000 +0200
|
|
+++ transupp.c 2012-11-15 21:46:57.000000000 +0100
|
|
@@ -51,6 +51,13 @@
|
|
* guarantee we can touch more than one row at a time. So in that case,
|
|
* we have to use a separate destination array.
|
|
*
|
|
+ * If cropping or trimming is involved, the destination arrays may be smaller
|
|
+ * than the source arrays. Note it is not possible to do horizontal flip
|
|
+ * in-place when a nonzero Y crop offset is specified, since we'd have to move
|
|
+ * data from one block row to another but the virtual array manager doesn't
|
|
+ * guarantee we can touch more than one row at a time. So in that case,
|
|
+ * we have to use a separate destination array.
|
|
+ *
|
|
* Some notes about the operating environment of the individual transform
|
|
* routines:
|
|
* 1. Both the source and destination virtual arrays are allocated from the
|
|
@@ -75,6 +82,269 @@
|
|
*/
|
|
|
|
|
|
+/* Drop code may be used with or without virtual memory adaptation code.
|
|
+ * This code has some dependencies on internal library behavior, so you
|
|
+ * may choose to disable it. For example, it doesn't make a difference
|
|
+ * if you only use jmemnobs anyway.
|
|
+ */
|
|
+#ifndef DROP_REQUEST_FROM_SRC
|
|
+#define DROP_REQUEST_FROM_SRC 1 /* 0 disables adaptation */
|
|
+#endif
|
|
+
|
|
+
|
|
+#if DROP_REQUEST_FROM_SRC
|
|
+/* Force jpeg_read_coefficients to request
|
|
+ * the virtual coefficient arrays from
|
|
+ * the source decompression object.
|
|
+ */
|
|
+METHODDEF(jvirt_barray_ptr)
|
|
+drop_request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
|
|
+ JDIMENSION blocksperrow, JDIMENSION numrows,
|
|
+ JDIMENSION maxaccess)
|
|
+{
|
|
+ j_decompress_ptr srcinfo = (j_decompress_ptr) cinfo->client_data;
|
|
+
|
|
+ return (*srcinfo->mem->request_virt_barray)
|
|
+ ((j_common_ptr) srcinfo, pool_id, pre_zero,
|
|
+ blocksperrow, numrows, maxaccess);
|
|
+}
|
|
+
|
|
+
|
|
+/* Force jpeg_read_coefficients to return
|
|
+ * after requesting and before accessing
|
|
+ * the virtual coefficient arrays.
|
|
+ */
|
|
+METHODDEF(int)
|
|
+drop_consume_input (j_decompress_ptr cinfo)
|
|
+{
|
|
+ return JPEG_SUSPENDED;
|
|
+}
|
|
+
|
|
+
|
|
+METHODDEF(void)
|
|
+drop_start_input_pass (j_decompress_ptr cinfo)
|
|
+{
|
|
+ cinfo->inputctl->consume_input = drop_consume_input;
|
|
+}
|
|
+
|
|
+
|
|
+LOCAL(void)
|
|
+drop_request_from_src (j_decompress_ptr dropinfo, j_decompress_ptr srcinfo)
|
|
+{
|
|
+ void *save_client_data;
|
|
+ JMETHOD(jvirt_barray_ptr, save_request_virt_barray,
|
|
+ (j_common_ptr cinfo, int pool_id, boolean pre_zero,
|
|
+ JDIMENSION blocksperrow, JDIMENSION numrows, JDIMENSION maxaccess));
|
|
+ JMETHOD(void, save_start_input_pass, (j_decompress_ptr cinfo));
|
|
+
|
|
+ /* Set custom method pointers, save original pointers */
|
|
+ save_client_data = dropinfo->client_data;
|
|
+ dropinfo->client_data = (void *) srcinfo;
|
|
+ save_request_virt_barray = dropinfo->mem->request_virt_barray;
|
|
+ dropinfo->mem->request_virt_barray = drop_request_virt_barray;
|
|
+ save_start_input_pass = dropinfo->inputctl->start_input_pass;
|
|
+ dropinfo->inputctl->start_input_pass = drop_start_input_pass;
|
|
+
|
|
+ /* Execute only initialization part.
|
|
+ * Requested coefficient arrays will be realized later by the srcinfo object.
|
|
+ * Next call to the same function will then do the actual data reading.
|
|
+ * NB: since we request the coefficient arrays from another object,
|
|
+ * the inherent realization call is effectively a no-op.
|
|
+ */
|
|
+ (void) jpeg_read_coefficients(dropinfo);
|
|
+
|
|
+ /* Reset method pointers */
|
|
+ dropinfo->client_data = save_client_data;
|
|
+ dropinfo->mem->request_virt_barray = save_request_virt_barray;
|
|
+ dropinfo->inputctl->start_input_pass = save_start_input_pass;
|
|
+ /* Do input initialization for first scan now,
|
|
+ * which also resets the consume_input method.
|
|
+ */
|
|
+ (*save_start_input_pass)(dropinfo);
|
|
+}
|
|
+#endif /* DROP_REQUEST_FROM_SRC */
|
|
+
|
|
+
|
|
+LOCAL(void)
|
|
+dequant_comp (j_decompress_ptr cinfo, jpeg_component_info *compptr,
|
|
+ jvirt_barray_ptr coef_array, JQUANT_TBL *qtblptr1)
|
|
+{
|
|
+ JDIMENSION blk_x, blk_y;
|
|
+ int offset_y, k;
|
|
+ JQUANT_TBL *qtblptr;
|
|
+ JBLOCKARRAY buffer;
|
|
+ JBLOCKROW block;
|
|
+ JCOEFPTR ptr;
|
|
+
|
|
+ qtblptr = compptr->quant_table;
|
|
+ for (blk_y = 0; blk_y < compptr->height_in_blocks;
|
|
+ blk_y += compptr->v_samp_factor) {
|
|
+ buffer = (*cinfo->mem->access_virt_barray)
|
|
+ ((j_common_ptr) cinfo, coef_array, blk_y,
|
|
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
|
|
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
|
|
+ block = buffer[offset_y];
|
|
+ for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
|
|
+ ptr = block[blk_x];
|
|
+ for (k = 0; k < DCTSIZE2; k++)
|
|
+ if (qtblptr->quantval[k] != qtblptr1->quantval[k])
|
|
+ ptr[k] *= qtblptr->quantval[k] / qtblptr1->quantval[k];
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+LOCAL(void)
|
|
+requant_comp (j_decompress_ptr cinfo, jpeg_component_info *compptr,
|
|
+ jvirt_barray_ptr coef_array, JQUANT_TBL *qtblptr1)
|
|
+{
|
|
+ JDIMENSION blk_x, blk_y;
|
|
+ int offset_y, k;
|
|
+ JQUANT_TBL *qtblptr;
|
|
+ JBLOCKARRAY buffer;
|
|
+ JBLOCKROW block;
|
|
+ JCOEFPTR ptr;
|
|
+ JCOEF temp, qval;
|
|
+
|
|
+ qtblptr = compptr->quant_table;
|
|
+ for (blk_y = 0; blk_y < compptr->height_in_blocks;
|
|
+ blk_y += compptr->v_samp_factor) {
|
|
+ buffer = (*cinfo->mem->access_virt_barray)
|
|
+ ((j_common_ptr) cinfo, coef_array, blk_y,
|
|
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
|
|
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
|
|
+ block = buffer[offset_y];
|
|
+ for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
|
|
+ ptr = block[blk_x];
|
|
+ for (k = 0; k < DCTSIZE2; k++) {
|
|
+ temp = qtblptr->quantval[k];
|
|
+ qval = qtblptr1->quantval[k];
|
|
+ if (temp != qval) {
|
|
+ temp *= ptr[k];
|
|
+ /* The following quantization code is a copy from jcdctmgr.c */
|
|
+#ifdef FAST_DIVIDE
|
|
+#define DIVIDE_BY(a,b) a /= b
|
|
+#else
|
|
+#define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0
|
|
+#endif
|
|
+ if (temp < 0) {
|
|
+ temp = -temp;
|
|
+ temp += qval>>1; /* for rounding */
|
|
+ DIVIDE_BY(temp, qval);
|
|
+ temp = -temp;
|
|
+ } else {
|
|
+ temp += qval>>1; /* for rounding */
|
|
+ DIVIDE_BY(temp, qval);
|
|
+ }
|
|
+ ptr[k] = temp;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+/* Calculate largest common denominator with Euklid's algorithm.
|
|
+ */
|
|
+LOCAL(JCOEF)
|
|
+largest_common_denominator(JCOEF a, JCOEF b)
|
|
+{
|
|
+ JCOEF c;
|
|
+
|
|
+ do {
|
|
+ c = a % b;
|
|
+ a = b;
|
|
+ b = c;
|
|
+ } while (c);
|
|
+
|
|
+ return a;
|
|
+}
|
|
+
|
|
+
|
|
+LOCAL(void)
|
|
+adjust_quant(j_decompress_ptr srcinfo, jvirt_barray_ptr *src_coef_arrays,
|
|
+ j_decompress_ptr dropinfo, jvirt_barray_ptr *drop_coef_arrays,
|
|
+ boolean trim, j_compress_ptr dstinfo)
|
|
+{
|
|
+ jpeg_component_info *compptr1, *compptr2;
|
|
+ JQUANT_TBL *qtblptr1, *qtblptr2, *qtblptr3;
|
|
+ int ci, k;
|
|
+
|
|
+ for (ci = 0; ci < dstinfo->num_components &&
|
|
+ ci < dropinfo->num_components; ci++) {
|
|
+ compptr1 = srcinfo->comp_info + ci;
|
|
+ compptr2 = dropinfo->comp_info + ci;
|
|
+ qtblptr1 = compptr1->quant_table;
|
|
+ qtblptr2 = compptr2->quant_table;
|
|
+ for (k = 0; k < DCTSIZE2; k++) {
|
|
+ if (qtblptr1->quantval[k] != qtblptr2->quantval[k]) {
|
|
+ if (trim)
|
|
+ requant_comp(dropinfo, compptr2, drop_coef_arrays[ci], qtblptr1);
|
|
+ else {
|
|
+ qtblptr3 = dstinfo->quant_tbl_ptrs[compptr1->quant_tbl_no];
|
|
+ for (k = 0; k < DCTSIZE2; k++)
|
|
+ if (qtblptr1->quantval[k] != qtblptr2->quantval[k])
|
|
+ qtblptr3->quantval[k] = largest_common_denominator
|
|
+ (qtblptr1->quantval[k], qtblptr2->quantval[k]);
|
|
+ dequant_comp(srcinfo, compptr1, src_coef_arrays[ci], qtblptr3);
|
|
+ dequant_comp(dropinfo, compptr2, drop_coef_arrays[ci], qtblptr3);
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+LOCAL(void)
|
|
+do_drop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
|
+ JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
|
|
+ jvirt_barray_ptr *src_coef_arrays,
|
|
+ j_decompress_ptr dropinfo, jvirt_barray_ptr *drop_coef_arrays,
|
|
+ JDIMENSION drop_width, JDIMENSION drop_height)
|
|
+/* Drop. If the dropinfo component number is smaller than the destination's,
|
|
+ * we fill in the remaining components with zero. This provides the feature
|
|
+ * of dropping grayscale into (arbitrarily sampled) color images.
|
|
+ */
|
|
+{
|
|
+ JDIMENSION comp_width, comp_height;
|
|
+ JDIMENSION blk_y, x_drop_blocks, y_drop_blocks;
|
|
+ int ci, offset_y;
|
|
+ JBLOCKARRAY src_buffer, dst_buffer;
|
|
+ jpeg_component_info *compptr;
|
|
+
|
|
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
|
|
+ compptr = dstinfo->comp_info + ci;
|
|
+ comp_width = drop_width * compptr->h_samp_factor;
|
|
+ comp_height = drop_height * compptr->v_samp_factor;
|
|
+ x_drop_blocks = x_crop_offset * compptr->h_samp_factor;
|
|
+ y_drop_blocks = y_crop_offset * compptr->v_samp_factor;
|
|
+ for (blk_y = 0; blk_y < comp_height; blk_y += compptr->v_samp_factor) {
|
|
+ dst_buffer = (*srcinfo->mem->access_virt_barray)
|
|
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y + y_drop_blocks,
|
|
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
|
|
+ if (ci < dropinfo->num_components) {
|
|
+ src_buffer = (*srcinfo->mem->access_virt_barray)
|
|
+ ((j_common_ptr) srcinfo, drop_coef_arrays[ci], blk_y,
|
|
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
|
|
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
|
|
+ jcopy_block_row(src_buffer[offset_y],
|
|
+ dst_buffer[offset_y] + x_drop_blocks,
|
|
+ comp_width);
|
|
+ }
|
|
+ } else {
|
|
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
|
|
+ FMEMZERO(dst_buffer[offset_y] + x_drop_blocks,
|
|
+ comp_width * SIZEOF(JBLOCK));
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
LOCAL(void)
|
|
do_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
|
|
JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
|
|
@@ -82,16 +352,21 @@
|
|
jvirt_barray_ptr *dst_coef_arrays)
|
|
/* Crop. This is only used when no rotate/flip is requested with the crop. */
|
|
{
|
|
+ JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height;
|
|
JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks;
|
|
int ci, offset_y;
|
|
JBLOCKARRAY src_buffer, dst_buffer;
|
|
jpeg_component_info *compptr;
|
|
|
|
+ MCU_cols = srcinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
|
|
+ MCU_rows = srcinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
|
|
/* We simply have to copy the right amount of data (the destination's
|
|
* image size) starting at the given X and Y offsets in the source.
|
|
*/
|
|
for (ci = 0; ci < dstinfo->num_components; ci++) {
|
|
compptr = dstinfo->comp_info + ci;
|
|
+ comp_width = MCU_cols * compptr->h_samp_factor;
|
|
+ comp_height = MCU_rows * compptr->v_samp_factor;
|
|
x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
|
|
y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
|
|
for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
|
|
@@ -99,17 +374,49 @@
|
|
dst_buffer = (*srcinfo->mem->access_virt_barray)
|
|
((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
|
|
(JDIMENSION) compptr->v_samp_factor, TRUE);
|
|
+ if (dstinfo->image_height > srcinfo->image_height) {
|
|
+ if (dst_blk_y < y_crop_blocks ||
|
|
+ dst_blk_y >= comp_height + y_crop_blocks) {
|
|
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
|
|
+ FMEMZERO(dst_buffer[offset_y],
|
|
+ compptr->width_in_blocks * SIZEOF(JBLOCK));
|
|
+ }
|
|
+ continue;
|
|
+ }
|
|
+ src_buffer = (*srcinfo->mem->access_virt_barray)
|
|
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci],
|
|
+ dst_blk_y - y_crop_blocks,
|
|
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
|
|
+ } else {
|
|
src_buffer = (*srcinfo->mem->access_virt_barray)
|
|
((j_common_ptr) srcinfo, src_coef_arrays[ci],
|
|
dst_blk_y + y_crop_blocks,
|
|
(JDIMENSION) compptr->v_samp_factor, FALSE);
|
|
+ }
|
|
for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
|
|
+ if (dstinfo->image_width > srcinfo->image_width) {
|
|
+ if (x_crop_blocks > 0) {
|
|
+ FMEMZERO(dst_buffer[offset_y],
|
|
+ x_crop_blocks * SIZEOF(JBLOCK));
|
|
+ }
|
|
+ jcopy_block_row(src_buffer[offset_y],
|
|
+ dst_buffer[offset_y] + x_crop_blocks,
|
|
+ comp_width);
|
|
+ if (compptr->width_in_blocks > comp_width + x_crop_blocks) {
|
|
+ FMEMZERO(dst_buffer[offset_y] +
|
|
+ comp_width + x_crop_blocks,
|
|
+ (compptr->width_in_blocks -
|
|
+ comp_width - x_crop_blocks) * SIZEOF(JBLOCK));
|
|
+ }
|
|
+ } else {
|
|
+
|
|
jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
|
|
dst_buffer[offset_y],
|
|
compptr->width_in_blocks);
|
|
}
|
|
}
|
|
}
|
|
+ }
|
|
}
|
|
|
|
|
|
@@ -884,7 +1191,9 @@
|
|
JDIMENSION xoffset, yoffset;
|
|
JDIMENSION width_in_iMCUs, height_in_iMCUs;
|
|
JDIMENSION width_in_blocks, height_in_blocks;
|
|
+ JDIMENSION dtemp;
|
|
int ci, h_samp_factor, v_samp_factor;
|
|
+ int itemp;
|
|
|
|
/* Determine number of components in output image */
|
|
if (info->force_grayscale &&
|
|
@@ -965,39 +1274,120 @@
|
|
info->crop_xoffset = 0; /* default to +0 */
|
|
if (info->crop_yoffset_set == JCROP_UNSET)
|
|
info->crop_yoffset = 0; /* default to +0 */
|
|
- if (info->crop_xoffset >= info->output_width ||
|
|
- info->crop_yoffset >= info->output_height)
|
|
+ if (info->crop_width_set == JCROP_UNSET) {
|
|
+ if (info->crop_xoffset >= info->output_width)
|
|
ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
|
|
- if (info->crop_width_set == JCROP_UNSET)
|
|
info->crop_width = info->output_width - info->crop_xoffset;
|
|
- if (info->crop_height_set == JCROP_UNSET)
|
|
+ } else {
|
|
+ /* Check for crop extension */
|
|
+ if (info->crop_width > info->output_width) {
|
|
+ /* Crop extension does not work when transforming! */
|
|
+ if (info->transform != JXFORM_NONE ||
|
|
+ info->crop_xoffset >= info->crop_width ||
|
|
+ info->crop_xoffset > info->crop_width - info->output_width)
|
|
+ ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
|
|
+ } else {
|
|
+ if (info->crop_xoffset >= info->output_width ||
|
|
+ info->crop_width <= 0 ||
|
|
+ info->crop_xoffset > info->output_width - info->crop_width)
|
|
+ ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
|
|
+ }
|
|
+ }
|
|
+ if (info->crop_height_set == JCROP_UNSET) {
|
|
+ if (info->crop_yoffset >= info->output_height)
|
|
+ ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
|
|
info->crop_height = info->output_height - info->crop_yoffset;
|
|
- /* Ensure parameters are valid */
|
|
- if (info->crop_width <= 0 || info->crop_width > info->output_width ||
|
|
- info->crop_height <= 0 || info->crop_height > info->output_height ||
|
|
- info->crop_xoffset > info->output_width - info->crop_width ||
|
|
+ } else {
|
|
+ /* Check for crop extension */
|
|
+ if (info->crop_height > info->output_height) {
|
|
+ /* Crop extension does not work when transforming! */
|
|
+ if (info->transform != JXFORM_NONE ||
|
|
+ info->crop_yoffset >= info->crop_height ||
|
|
+ info->crop_yoffset > info->crop_height - info->output_height)
|
|
+ ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
|
|
+ } else {
|
|
+ if (info->crop_yoffset >= info->output_height ||
|
|
+ info->crop_height <= 0 ||
|
|
info->crop_yoffset > info->output_height - info->crop_height)
|
|
ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
|
|
+ }
|
|
+ }
|
|
/* Convert negative crop offsets into regular offsets */
|
|
- if (info->crop_xoffset_set == JCROP_NEG)
|
|
+ if (info->crop_xoffset_set == JCROP_NEG) {
|
|
+ if (info->crop_width > info->output_width)
|
|
+ xoffset = info->crop_width - info->output_width - info->crop_xoffset;
|
|
+ else
|
|
xoffset = info->output_width - info->crop_width - info->crop_xoffset;
|
|
- else
|
|
+ } else
|
|
xoffset = info->crop_xoffset;
|
|
- if (info->crop_yoffset_set == JCROP_NEG)
|
|
+ if (info->crop_yoffset_set == JCROP_NEG) {
|
|
+ if (info->crop_height > info->output_height)
|
|
+ yoffset = info->crop_height - info->output_height - info->crop_yoffset;
|
|
+ else
|
|
yoffset = info->output_height - info->crop_height - info->crop_yoffset;
|
|
- else
|
|
+ } else
|
|
yoffset = info->crop_yoffset;
|
|
/* Now adjust so that upper left corner falls at an iMCU boundary */
|
|
+ if (info->transform == JXFORM_DROP) {
|
|
+ /* Ensure the effective drop region will not exceed the requested */
|
|
+ itemp = info->iMCU_sample_width;
|
|
+ dtemp = itemp - 1 - ((xoffset + itemp - 1) % itemp);
|
|
+ xoffset += dtemp;
|
|
+ if (info->crop_width > dtemp)
|
|
+ info->drop_width = (info->crop_width - dtemp) / itemp;
|
|
+ else
|
|
+ info->drop_width = 0;
|
|
+ itemp = info->iMCU_sample_height;
|
|
+ dtemp = itemp - 1 - ((yoffset + itemp - 1) % itemp);
|
|
+ yoffset += dtemp;
|
|
+ if (info->crop_height > dtemp)
|
|
+ info->drop_height = (info->crop_height - dtemp) / itemp;
|
|
+ else
|
|
+ info->drop_height = 0;
|
|
+ /* Check if sampling factors match for dropping */
|
|
+ if (info->drop_width != 0 && info->drop_height != 0)
|
|
+ for (ci = 0; ci < info->num_components &&
|
|
+ ci < info->drop_ptr->num_components; ci++) {
|
|
+ if (info->drop_ptr->comp_info[ci].h_samp_factor *
|
|
+ srcinfo->max_h_samp_factor !=
|
|
+ srcinfo->comp_info[ci].h_samp_factor *
|
|
+ info->drop_ptr->max_h_samp_factor)
|
|
+ ERREXIT6(srcinfo, JERR_BAD_DROP_SAMPLING, ci,
|
|
+ info->drop_ptr->comp_info[ci].h_samp_factor,
|
|
+ info->drop_ptr->max_h_samp_factor,
|
|
+ srcinfo->comp_info[ci].h_samp_factor,
|
|
+ srcinfo->max_h_samp_factor, 'h');
|
|
+ if (info->drop_ptr->comp_info[ci].v_samp_factor *
|
|
+ srcinfo->max_v_samp_factor !=
|
|
+ srcinfo->comp_info[ci].v_samp_factor *
|
|
+ info->drop_ptr->max_v_samp_factor)
|
|
+ ERREXIT6(srcinfo, JERR_BAD_DROP_SAMPLING, ci,
|
|
+ info->drop_ptr->comp_info[ci].v_samp_factor,
|
|
+ info->drop_ptr->max_v_samp_factor,
|
|
+ srcinfo->comp_info[ci].v_samp_factor,
|
|
+ srcinfo->max_v_samp_factor, 'v');
|
|
+ }
|
|
+ } else {
|
|
+ /* Ensure the effective crop region will cover the requested */
|
|
+ if (info->crop_width > info->output_width)
|
|
+ info->output_width = info->crop_width;
|
|
+ else {
|
|
if (info->crop_width_set == JCROP_FORCE)
|
|
info->output_width = info->crop_width;
|
|
else
|
|
info->output_width =
|
|
info->crop_width + (xoffset % info->iMCU_sample_width);
|
|
+ }
|
|
+ if (info->crop_height > info->output_height)
|
|
+ info->output_height = info->crop_height;
|
|
+ else {
|
|
if (info->crop_height_set == JCROP_FORCE)
|
|
info->output_height = info->crop_height;
|
|
else
|
|
info->output_height =
|
|
info->crop_height + (yoffset % info->iMCU_sample_height);
|
|
+ }
|
|
+ }
|
|
/* Save x/y offsets measured in iMCUs */
|
|
info->x_crop_offset = xoffset / info->iMCU_sample_width;
|
|
info->y_crop_offset = yoffset / info->iMCU_sample_height;
|
|
@@ -1013,7 +1403,9 @@
|
|
transpose_it = FALSE;
|
|
switch (info->transform) {
|
|
case JXFORM_NONE:
|
|
- if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
|
|
+ if (info->x_crop_offset != 0 || info->y_crop_offset != 0 ||
|
|
+ info->output_width > srcinfo->image_width ||
|
|
+ info->output_height > srcinfo->image_height)
|
|
need_workspace = TRUE;
|
|
/* No workspace needed if neither cropping nor transforming */
|
|
break;
|
|
@@ -1067,6 +1459,11 @@
|
|
need_workspace = TRUE;
|
|
transpose_it = TRUE;
|
|
break;
|
|
+ case JXFORM_DROP:
|
|
+#if DROP_REQUEST_FROM_SRC
|
|
+ drop_request_from_src(info->drop_ptr, srcinfo);
|
|
+#endif
|
|
+ break;
|
|
}
|
|
|
|
/* Allocate workspace if needed.
|
|
@@ -1373,6 +1770,11 @@
|
|
case JXFORM_ROT_270:
|
|
transpose_critical_parameters(dstinfo);
|
|
break;
|
|
+ case JXFORM_DROP:
|
|
+ if (info->drop_width != 0 && info->drop_height != 0)
|
|
+ adjust_quant(srcinfo, src_coef_arrays,
|
|
+ info->drop_ptr, info->drop_coef_arrays,
|
|
+ info->trim, dstinfo);
|
|
default:
|
|
break;
|
|
}
|
|
@@ -1427,7 +1829,9 @@
|
|
*/
|
|
switch (info->transform) {
|
|
case JXFORM_NONE:
|
|
- if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
|
|
+ if (info->x_crop_offset != 0 || info->y_crop_offset != 0 ||
|
|
+ info->output_width > srcinfo->image_width ||
|
|
+ info->output_height > srcinfo->image_height)
|
|
do_crop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
|
|
src_coef_arrays, dst_coef_arrays);
|
|
break;
|
|
@@ -1463,6 +1867,12 @@
|
|
do_rot_270(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
|
|
src_coef_arrays, dst_coef_arrays);
|
|
break;
|
|
+ case JXFORM_DROP:
|
|
+ if (info->drop_width != 0 && info->drop_height != 0)
|
|
+ do_drop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
|
|
+ src_coef_arrays, info->drop_ptr, info->drop_coef_arrays,
|
|
+ info->drop_width, info->drop_height);
|
|
+ break;
|
|
}
|
|
}
|
|
|