* Copyright (C) 1991-1996, Thomas G. Lane.
* libjpeg-turbo Modifications:
* Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
- * Copyright (C) 2010, D. R. Commander.
- * Copyright (C) 2014, MIPS Technologies, Inc., California
- * For conditions of distribution and use, see the accompanying README file.
+ * Copyright (C) 2010, 2015-2016, D. R. Commander.
+ * Copyright (C) 2014, MIPS Technologies, Inc., California.
+ * Copyright (C) 2015, Google, Inc.
+ * For conditions of distribution and use, see the accompanying README.ijg
+ * file.
*
* This file contains upsampling routines.
*
* Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
*/
-#define JPEG_INTERNALS
#include "jinclude.h"
-#include "jpeglib.h"
+#include "jdsample.h"
#include "jsimd.h"
#include "jpegcomp.h"
-/* Pointer to routine to upsample a single component */
-typedef void (*upsample1_ptr) (j_decompress_ptr cinfo,
- jpeg_component_info * compptr,
- JSAMPARRAY input_data,
- JSAMPARRAY * output_data_ptr);
-
-/* Private subobject */
-
-typedef struct {
- struct jpeg_upsampler pub; /* public fields */
-
- /* Color conversion buffer. When using separate upsampling and color
- * conversion steps, this buffer holds one upsampled row group until it
- * has been color converted and output.
- * Note: we do not allocate any storage for component(s) which are full-size,
- * ie do not need rescaling. The corresponding entry of color_buf[] is
- * simply set to point to the input data array, thereby avoiding copying.
- */
- JSAMPARRAY color_buf[MAX_COMPONENTS];
-
- /* Per-component upsampling method pointers */
- upsample1_ptr methods[MAX_COMPONENTS];
-
- int next_row_out; /* counts rows emitted from color_buf */
- JDIMENSION rows_to_go; /* counts rows remaining in image */
-
- /* Height of an input row group for each component. */
- int rowgroup_height[MAX_COMPONENTS];
-
- /* These arrays save pixel expansion factors so that int_expand need not
- * recompute them each time. They are unused for other upsampling methods.
- */
- UINT8 h_expand[MAX_COMPONENTS];
- UINT8 v_expand[MAX_COMPONENTS];
-} my_upsampler;
-
-typedef my_upsampler * my_upsample_ptr;
-
/*
* Initialize for an upsampling pass.
{
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
int ci;
- jpeg_component_info * compptr;
+ jpeg_component_info *compptr;
JDIMENSION num_rows;
/* Fill the conversion buffer, if it's empty */
*/
METHODDEF(void)
-fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
- JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
*output_data_ptr = input_data;
}
*/
METHODDEF(void)
-noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
- JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+noop_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
*output_data_ptr = NULL; /* safety check */
}
*/
METHODDEF(void)
-int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
- JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+int_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
JSAMPARRAY output_data = *output_data_ptr;
*/
METHODDEF(void)
-h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
- JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
JSAMPARRAY output_data = *output_data_ptr;
register JSAMPROW inptr, outptr;
*/
METHODDEF(void)
-h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
- JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
JSAMPARRAY output_data = *output_data_ptr;
register JSAMPROW inptr, outptr;
*/
METHODDEF(void)
-h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
- JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
JSAMPARRAY output_data = *output_data_ptr;
register JSAMPROW inptr, outptr;
/*
+ * Fancy processing for 1:1 horizontal and 2:1 vertical (4:4:0 subsampling).
+ *
+ * This is a less common case, but it can be encountered when losslessly
+ * rotating/transposing a JPEG file that uses 4:2:2 chroma subsampling.
+ */
+
+METHODDEF(void)
+h1v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
+{
+ JSAMPARRAY output_data = *output_data_ptr;
+ JSAMPROW inptr0, inptr1, outptr;
+#if BITS_IN_JSAMPLE == 8
+ int thiscolsum;
+#else
+ JLONG thiscolsum;
+#endif
+ JDIMENSION colctr;
+ int inrow, outrow, v;
+
+ inrow = outrow = 0;
+ while (outrow < cinfo->max_v_samp_factor) {
+ for (v = 0; v < 2; v++) {
+ /* inptr0 points to nearest input row, inptr1 points to next nearest */
+ inptr0 = input_data[inrow];
+ if (v == 0) /* next nearest is row above */
+ inptr1 = input_data[inrow-1];
+ else /* next nearest is row below */
+ inptr1 = input_data[inrow+1];
+ outptr = output_data[outrow++];
+
+ for(colctr = 0; colctr < compptr->downsampled_width; colctr++) {
+ thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
+ *outptr++ = (JSAMPLE) ((thiscolsum + 1) >> 2);
+ }
+ }
+ inrow++;
+ }
+}
+
+
+/*
* Fancy processing for the common case of 2:1 horizontal and 2:1 vertical.
* Again a triangle filter; see comments for h2v1 case, above.
*
*/
METHODDEF(void)
-h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
- JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY *output_data_ptr)
{
JSAMPARRAY output_data = *output_data_ptr;
register JSAMPROW inptr0, inptr1, outptr;
#if BITS_IN_JSAMPLE == 8
register int thiscolsum, lastcolsum, nextcolsum;
#else
- register INT32 thiscolsum, lastcolsum, nextcolsum;
+ register JLONG thiscolsum, lastcolsum, nextcolsum;
#endif
register JDIMENSION colctr;
int inrow, outrow, v;
{
my_upsample_ptr upsample;
int ci;
- jpeg_component_info * compptr;
+ jpeg_component_info *compptr;
boolean need_buffer, do_fancy;
int h_in_group, v_in_group, h_out_group, v_out_group;
- upsample = (my_upsample_ptr)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
- sizeof(my_upsampler));
- cinfo->upsample = (struct jpeg_upsampler *) upsample;
- upsample->pub.start_pass = start_pass_upsample;
- upsample->pub.upsample = sep_upsample;
- upsample->pub.need_context_rows = FALSE; /* until we find out differently */
+ if (!cinfo->master->jinit_upsampler_no_alloc) {
+ upsample = (my_upsample_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ sizeof(my_upsampler));
+ cinfo->upsample = (struct jpeg_upsampler *) upsample;
+ upsample->pub.start_pass = start_pass_upsample;
+ upsample->pub.upsample = sep_upsample;
+ upsample->pub.need_context_rows = FALSE; /* until we find out differently */
+ } else
+ upsample = (my_upsample_ptr) cinfo->upsample;
if (cinfo->CCIR601_sampling) /* this isn't supported */
ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
else
upsample->methods[ci] = h2v1_upsample;
}
+ } else if (h_in_group == h_out_group &&
+ v_in_group * 2 == v_out_group && do_fancy) {
+ /* Non-fancy upsampling is handled by the generic method */
+ upsample->methods[ci] = h1v2_fancy_upsample;
+ upsample->pub.need_context_rows = TRUE;
} else if (h_in_group * 2 == h_out_group &&
v_in_group * 2 == v_out_group) {
/* Special cases for 2h2v upsampling */
upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group);
} else
ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
- if (need_buffer) {
+ if (need_buffer && !cinfo->master->jinit_upsampler_no_alloc) {
upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray)
((j_common_ptr) cinfo, JPOOL_IMAGE,
(JDIMENSION) jround_up((long) cinfo->output_width,