12cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane/*
22cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane * jcsample.c
32cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane *
4da13af6b8d5427af89bbdc5698b4e09d0ea814feDRC * This file was part of the Independent JPEG Group's software:
5489583f5165e05d37302e8eeec58104ea0109127Thomas G. Lane * Copyright (C) 1991-1996, Thomas G. Lane.
6da13af6b8d5427af89bbdc5698b4e09d0ea814feDRC * libjpeg-turbo Modifications:
759a3938b2e3f6c49730a57935f389078219a8fabPierre Ossman * Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
85ef463056ae22f24c3915ba7ab03eefd5bb6fde7DRC * Copyright (C) 2014, MIPS Technologies, Inc., California
92cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane * For conditions of distribution and use, see the accompanying README file.
102cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane *
1188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * This file contains downsampling routines.
1236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane *
1336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * Downsampling input data is counted in "row groups".  A row group
1436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * is defined to be max_v_samp_factor pixel rows of each component,
1536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * from which the downsampler produces v_samp_factor sample rows.
1636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * A single row group is processed in each call to the downsampler module.
1736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane *
1836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * The downsampler is responsible for edge-expansion of its output data
1936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * to fill an integral number of DCT blocks horizontally.  The source buffer
2036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * may be modified if it is helpful for this purpose (the source buffer is
2136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * allocated wide enough to correspond to the desired output width).
2236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * The caller (the prep controller) is responsible for vertical padding.
2336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane *
2436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * The downsampler may request "context rows" by setting need_context_rows
2536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * during startup.  In this case, the input arrays will contain at least
2636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * one row group's worth of pixels above and below the passed-in data;
2736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * the caller will create dummy rows at image top and bottom by replicating
2836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * the first or last real pixel row.
2988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane *
3088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * An excellent reference for image resampling is
3188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane *   Digital Image Warping, George Wolberg, 1990.
3288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane *   Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
3388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane *
3488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * The downsampling algorithm used here is a simple average of the source
3588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * pixels covered by the output pixel.  The hi-falutin sampling literature
3688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * refers to this as a "box filter".  In general the characteristics of a box
3788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * filter are not very good, but for the specific cases we normally use (1:1
3888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * and 2:1 ratios) the box is equivalent to a "triangle filter" which is not
3988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * nearly so bad.  If you intend to use other sampling ratios, you'd be well
4088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * advised to improve this code.
4188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane *
4288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * A simple input-smoothing capability is provided.  This is mainly intended
4388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * for cleaning up color-dithered GIF input files (if you find it inadequate,
4488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * we suggest using an external filtering program such as pnmconvol).  When
4588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * enabled, each input pixel P is replaced by a weighted sum of itself and its
4688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * eight neighbors.  P's weight is 1-8*SF and each neighbor's weight is SF,
4788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * where SF = (smoothing_factor / 1024).
4888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * Currently, smoothing is only supported for 2h2v sampling factors.
492cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane */
502cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane
5136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#define JPEG_INTERNALS
522cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane#include "jinclude.h"
5336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane#include "jpeglib.h"
5459a3938b2e3f6c49730a57935f389078219a8fabPierre Ossman#include "jsimd.h"
5536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
5636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
5736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane/* Pointer to routine to downsample a single component */
58bc56b754e1a6a1db9ccadf64d6dda8a74140e1a3DRCtypedef void (*downsample1_ptr) (j_compress_ptr cinfo,
59bc56b754e1a6a1db9ccadf64d6dda8a74140e1a3DRC                                 jpeg_component_info * compptr,
60bc56b754e1a6a1db9ccadf64d6dda8a74140e1a3DRC                                 JSAMPARRAY input_data,
61bc56b754e1a6a1db9ccadf64d6dda8a74140e1a3DRC                                 JSAMPARRAY output_data);
6236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
6336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane/* Private subobject */
6436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
6536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lanetypedef struct {
66b775351012af176720429ac21d11682a0b75b4b7DRC  struct jpeg_downsampler pub;  /* public fields */
6736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
6836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Downsampling method pointers, one per component */
6936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  downsample1_ptr methods[MAX_COMPONENTS];
7036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane} my_downsampler;
7136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
7236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lanetypedef my_downsampler * my_downsample_ptr;
732cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane
742cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane
752cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane/*
7636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * Initialize for a downsampling pass.
772cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane */
782cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane
79489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneMETHODDEF(void)
8036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lanestart_pass_downsample (j_compress_ptr cinfo)
812cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane{
822cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane  /* no work for now */
832cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane}
842cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane
852cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane
862cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane/*
8736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * Expand a component horizontally from width input_cols to width output_cols,
8836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * by duplicating the rightmost samples.
8936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane */
9036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
91489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneLOCAL(void)
9236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Laneexpand_right_edge (JSAMPARRAY image_data, int num_rows,
93b775351012af176720429ac21d11682a0b75b4b7DRC                   JDIMENSION input_cols, JDIMENSION output_cols)
9436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane{
9536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  register JSAMPROW ptr;
9636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  register JSAMPLE pixval;
9736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  register int count;
9836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  int row;
9936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  int numcols = (int) (output_cols - input_cols);
10036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
10136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  if (numcols > 0) {
10236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    for (row = 0; row < num_rows; row++) {
10336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      ptr = image_data[row] + input_cols;
104b775351012af176720429ac21d11682a0b75b4b7DRC      pixval = ptr[-1];         /* don't need GETJSAMPLE() here */
10536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      for (count = numcols; count > 0; count--)
106b775351012af176720429ac21d11682a0b75b4b7DRC        *ptr++ = pixval;
10736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    }
10836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  }
10936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane}
11036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
11136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
11236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane/*
11336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * Do downsampling for a whole row group (all components).
11436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane *
11536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * In this version we simply downsample each component independently.
11636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane */
11736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
118489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneMETHODDEF(void)
11936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lanesep_downsample (j_compress_ptr cinfo,
120b775351012af176720429ac21d11682a0b75b4b7DRC                JSAMPIMAGE input_buf, JDIMENSION in_row_index,
121b775351012af176720429ac21d11682a0b75b4b7DRC                JSAMPIMAGE output_buf, JDIMENSION out_row_group_index)
12236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane{
12336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample;
12436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  int ci;
12536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  jpeg_component_info * compptr;
12636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  JSAMPARRAY in_ptr, out_ptr;
12736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
12836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
12936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane       ci++, compptr++) {
13036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    in_ptr = input_buf[ci] + in_row_index;
13136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor);
13236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr);
13336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  }
13436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane}
13536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
13636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
13736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane/*
13888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * Downsample pixel values of a single component.
13936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * One row group is processed per call.
14088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * This version handles arbitrary integral sampling ratios, without smoothing.
14188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * Note that this version is not actually used for customary sampling ratios.
1422cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane */
1432cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane
144489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneMETHODDEF(void)
14536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Laneint_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
146b775351012af176720429ac21d11682a0b75b4b7DRC                JSAMPARRAY input_data, JSAMPARRAY output_data)
1472cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane{
1482cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane  int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v;
149b775351012af176720429ac21d11682a0b75b4b7DRC  JDIMENSION outcol, outcol_h;  /* outcol_h == outcol*h_expand */
15036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
1512cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane  JSAMPROW inptr, outptr;
1522cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane  INT32 outvalue;
1532cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane
1542cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane  h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor;
1552cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane  v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor;
1562cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane  numpix = h_expand * v_expand;
1572cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane  numpix2 = numpix/2;
1582cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane
15936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Expand input data enough to let all the output samples be generated
16036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   * by the standard loop.  Special-casing padded output would be more
16136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   * efficient.
16236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   */
16336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  expand_right_edge(input_data, cinfo->max_v_samp_factor,
164b775351012af176720429ac21d11682a0b75b4b7DRC                    cinfo->image_width, output_cols * h_expand);
16536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
1662cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane  inrow = 0;
16736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
1682cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane    outptr = output_data[outrow];
16988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    for (outcol = 0, outcol_h = 0; outcol < output_cols;
170b775351012af176720429ac21d11682a0b75b4b7DRC         outcol++, outcol_h += h_expand) {
1712cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane      outvalue = 0;
1722cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane      for (v = 0; v < v_expand; v++) {
173b775351012af176720429ac21d11682a0b75b4b7DRC        inptr = input_data[inrow+v] + outcol_h;
174b775351012af176720429ac21d11682a0b75b4b7DRC        for (h = 0; h < h_expand; h++) {
175b775351012af176720429ac21d11682a0b75b4b7DRC          outvalue += (INT32) GETJSAMPLE(*inptr++);
176b775351012af176720429ac21d11682a0b75b4b7DRC        }
1772cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane      }
178bd543f030e7e435c2c6a6a7d52ad927ae97cd927Thomas G. Lane      *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix);
1792cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane    }
1802cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane    inrow += v_expand;
1812cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane  }
1822cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane}
1832cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane
1842cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane
1852cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane/*
18688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * Downsample pixel values of a single component.
18736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * This version handles the special case of a full-size component,
18836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * without smoothing.
18936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane */
19036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
191489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneMETHODDEF(void)
19236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lanefullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
193b775351012af176720429ac21d11682a0b75b4b7DRC                     JSAMPARRAY input_data, JSAMPARRAY output_data)
19436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane{
19536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Copy the data */
19636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  jcopy_sample_rows(input_data, 0, output_data, 0,
197b775351012af176720429ac21d11682a0b75b4b7DRC                    cinfo->max_v_samp_factor, cinfo->image_width);
19836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Edge-expand */
19936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  expand_right_edge(output_data, cinfo->max_v_samp_factor,
200b775351012af176720429ac21d11682a0b75b4b7DRC                    cinfo->image_width, compptr->width_in_blocks * DCTSIZE);
20136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane}
20236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
20336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
20436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane/*
20536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * Downsample pixel values of a single component.
20688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * This version handles the common case of 2:1 horizontal and 1:1 vertical,
20788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * without smoothing.
20836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane *
20936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * A note about the "bias" calculations: when rounding fractional values to
21036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * integer, we do not want to always round 0.5 up to the next integer.
21136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * If we did that, we'd introduce a noticeable bias towards larger values.
21236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * Instead, this code is arranged so that 0.5 will be rounded up or down at
21336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * alternate pixel locations (a simple ordered dither pattern).
21488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane */
21588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
216489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneMETHODDEF(void)
21736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Laneh2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
218b775351012af176720429ac21d11682a0b75b4b7DRC                 JSAMPARRAY input_data, JSAMPARRAY output_data)
21988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane{
22088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane  int outrow;
22136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  JDIMENSION outcol;
22236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
22388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane  register JSAMPROW inptr, outptr;
22436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  register int bias;
22588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
22636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Expand input data enough to let all the output samples be generated
22736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   * by the standard loop.  Special-casing padded output would be more
22836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   * efficient.
22936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   */
23036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  expand_right_edge(input_data, cinfo->max_v_samp_factor,
231b775351012af176720429ac21d11682a0b75b4b7DRC                    cinfo->image_width, output_cols * 2);
23288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
23336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
23488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    outptr = output_data[outrow];
23588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    inptr = input_data[outrow];
236b775351012af176720429ac21d11682a0b75b4b7DRC    bias = 0;                   /* bias = 0,1,0,1,... for successive samples */
23788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    for (outcol = 0; outcol < output_cols; outcol++) {
23888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane      *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1])
239b775351012af176720429ac21d11682a0b75b4b7DRC                              + bias) >> 1);
240b775351012af176720429ac21d11682a0b75b4b7DRC      bias ^= 1;                /* 0=>1, 1=>0 */
24188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane      inptr += 2;
24288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    }
24388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane  }
24488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane}
24588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
24688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
24788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane/*
24888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * Downsample pixel values of a single component.
24988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * This version handles the standard case of 2:1 horizontal and 2:1 vertical,
25088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * without smoothing.
2512cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane */
2522cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane
253489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneMETHODDEF(void)
25436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Laneh2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
255b775351012af176720429ac21d11682a0b75b4b7DRC                 JSAMPARRAY input_data, JSAMPARRAY output_data)
2562cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane{
25788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane  int inrow, outrow;
25836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  JDIMENSION outcol;
25936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
26088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane  register JSAMPROW inptr0, inptr1, outptr;
26136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  register int bias;
26288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
26336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Expand input data enough to let all the output samples be generated
26436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   * by the standard loop.  Special-casing padded output would be more
26536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   * efficient.
26636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   */
26736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  expand_right_edge(input_data, cinfo->max_v_samp_factor,
268b775351012af176720429ac21d11682a0b75b4b7DRC                    cinfo->image_width, output_cols * 2);
26988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
27088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane  inrow = 0;
27136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
27288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    outptr = output_data[outrow];
27388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    inptr0 = input_data[inrow];
27488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    inptr1 = input_data[inrow+1];
275b775351012af176720429ac21d11682a0b75b4b7DRC    bias = 1;                   /* bias = 1,2,1,2,... for successive samples */
27688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    for (outcol = 0; outcol < output_cols; outcol++) {
27788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane      *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
278b775351012af176720429ac21d11682a0b75b4b7DRC                              GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1])
279b775351012af176720429ac21d11682a0b75b4b7DRC                              + bias) >> 2);
280b775351012af176720429ac21d11682a0b75b4b7DRC      bias ^= 3;                /* 1=>2, 2=>1 */
28188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane      inptr0 += 2; inptr1 += 2;
28288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    }
28388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    inrow += 2;
28488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane  }
28588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane}
28688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
28788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
28888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane#ifdef INPUT_SMOOTHING_SUPPORTED
28988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
29088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane/*
29188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * Downsample pixel values of a single component.
29288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * This version handles the standard case of 2:1 horizontal and 2:1 vertical,
29336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * with smoothing.  One row of context is required.
29488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane */
29588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
296489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneMETHODDEF(void)
29736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Laneh2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
298b775351012af176720429ac21d11682a0b75b4b7DRC                        JSAMPARRAY input_data, JSAMPARRAY output_data)
29988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane{
30088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane  int inrow, outrow;
30136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  JDIMENSION colctr;
30236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
30388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane  register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr;
30488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane  INT32 membersum, neighsum, memberscale, neighscale;
30588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
30636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Expand input data enough to let all the output samples be generated
30736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   * by the standard loop.  Special-casing padded output would be more
30836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   * efficient.
30936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   */
31036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
311b775351012af176720429ac21d11682a0b75b4b7DRC                    cinfo->image_width, output_cols * 2);
31288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
31388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane  /* We don't bother to form the individual "smoothed" input pixel values;
31488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane   * we can directly compute the output which is the average of the four
31588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane   * smoothed values.  Each of the four member pixels contributes a fraction
31688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane   * (1-8*SF) to its own smoothed image and a fraction SF to each of the three
31788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane   * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final
31888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane   * output.  The four corner-adjacent neighbor pixels contribute a fraction
31988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane   * SF to just one smoothed pixel, or SF/4 to the final output; while the
32088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane   * eight edge-adjacent neighbors contribute SF to each of two smoothed
32188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane   * pixels, or SF/2 overall.  In order to use integer arithmetic, these
32288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane   * factors are scaled by 2^16 = 65536.
32388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane   * Also recall that SF = smoothing_factor / 1024.
32488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane   */
32588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
32688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane  memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */
32788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane  neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */
32888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
32988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane  inrow = 0;
33036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
33188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    outptr = output_data[outrow];
33288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    inptr0 = input_data[inrow];
33388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    inptr1 = input_data[inrow+1];
33436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    above_ptr = input_data[inrow-1];
33536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    below_ptr = input_data[inrow+2];
33688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
33788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    /* Special case for first column: pretend column -1 is same as column 0 */
33888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
339b775351012af176720429ac21d11682a0b75b4b7DRC                GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
34088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
341b775351012af176720429ac21d11682a0b75b4b7DRC               GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
342b775351012af176720429ac21d11682a0b75b4b7DRC               GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) +
343b775351012af176720429ac21d11682a0b75b4b7DRC               GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]);
34488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    neighsum += neighsum;
34588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) +
346b775351012af176720429ac21d11682a0b75b4b7DRC                GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]);
34788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    membersum = membersum * memberscale + neighsum * neighscale;
34836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
34988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
35088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
35188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    for (colctr = output_cols - 2; colctr > 0; colctr--) {
35288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane      /* sum of pixels directly mapped to this output element */
35388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane      membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
354b775351012af176720429ac21d11682a0b75b4b7DRC                  GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
35588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane      /* sum of edge-neighbor pixels */
35688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane      neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
357b775351012af176720429ac21d11682a0b75b4b7DRC                 GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
358b775351012af176720429ac21d11682a0b75b4b7DRC                 GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) +
359b775351012af176720429ac21d11682a0b75b4b7DRC                 GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]);
36088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane      /* The edge-neighbors count twice as much as corner-neighbors */
36188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane      neighsum += neighsum;
36288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane      /* Add in the corner-neighbors */
36388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane      neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) +
364b775351012af176720429ac21d11682a0b75b4b7DRC                  GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]);
36588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane      /* form final output scaled up by 2^16 */
36688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane      membersum = membersum * memberscale + neighsum * neighscale;
36788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane      /* round, descale and output it */
36836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
36988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane      inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
37088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    }
37188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
37288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    /* Special case for last column */
37388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
374b775351012af176720429ac21d11682a0b75b4b7DRC                GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
37588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
376b775351012af176720429ac21d11682a0b75b4b7DRC               GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
377b775351012af176720429ac21d11682a0b75b4b7DRC               GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) +
378b775351012af176720429ac21d11682a0b75b4b7DRC               GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]);
37988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    neighsum += neighsum;
38088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) +
381b775351012af176720429ac21d11682a0b75b4b7DRC                GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]);
38288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    membersum = membersum * memberscale + neighsum * neighscale;
38336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    *outptr = (JSAMPLE) ((membersum + 32768) >> 16);
38488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
38588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    inrow += 2;
38688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane  }
38788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane}
38888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
38988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
39088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane/*
39188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * Downsample pixel values of a single component.
39288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane * This version handles the special case of a full-size component,
39336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * with smoothing.  One row of context is required.
39488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane */
39588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
396489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneMETHODDEF(void)
39736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lanefullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
398b775351012af176720429ac21d11682a0b75b4b7DRC                            JSAMPARRAY input_data, JSAMPARRAY output_data)
39988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane{
40088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane  int outrow;
40136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  JDIMENSION colctr;
40236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE;
40388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane  register JSAMPROW inptr, above_ptr, below_ptr, outptr;
40488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane  INT32 membersum, neighsum, memberscale, neighscale;
40588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane  int colsum, lastcolsum, nextcolsum;
40688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
40736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Expand input data enough to let all the output samples be generated
40836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   * by the standard loop.  Special-casing padded output would be more
40936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   * efficient.
41036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane   */
41136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
412b775351012af176720429ac21d11682a0b75b4b7DRC                    cinfo->image_width, output_cols);
41388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
41488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane  /* Each of the eight neighbor pixels contributes a fraction SF to the
41588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane   * smoothed pixel, while the main pixel contributes (1-8*SF).  In order
41688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane   * to use integer arithmetic, these factors are multiplied by 2^16 = 65536.
41788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane   * Also recall that SF = smoothing_factor / 1024.
41888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane   */
41988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
42088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane  memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */
42188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane  neighscale = cinfo->smoothing_factor * 64; /* scaled SF */
42288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
42336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
42488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    outptr = output_data[outrow];
42588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    inptr = input_data[outrow];
42636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    above_ptr = input_data[outrow-1];
42736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    below_ptr = input_data[outrow+1];
42888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
42988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    /* Special case for first column */
43088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) +
431b775351012af176720429ac21d11682a0b75b4b7DRC             GETJSAMPLE(*inptr);
43288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    membersum = GETJSAMPLE(*inptr++);
43388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
434b775351012af176720429ac21d11682a0b75b4b7DRC                 GETJSAMPLE(*inptr);
43588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    neighsum = colsum + (colsum - membersum) + nextcolsum;
43688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    membersum = membersum * memberscale + neighsum * neighscale;
43736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
43888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    lastcolsum = colsum; colsum = nextcolsum;
43988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
44088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    for (colctr = output_cols - 2; colctr > 0; colctr--) {
44188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane      membersum = GETJSAMPLE(*inptr++);
44288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane      above_ptr++; below_ptr++;
44388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane      nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
444b775351012af176720429ac21d11682a0b75b4b7DRC                   GETJSAMPLE(*inptr);
44588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane      neighsum = lastcolsum + (colsum - membersum) + nextcolsum;
44688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane      membersum = membersum * memberscale + neighsum * neighscale;
44736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
44888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane      lastcolsum = colsum; colsum = nextcolsum;
44988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    }
45088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
45188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    /* Special case for last column */
45288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    membersum = GETJSAMPLE(*inptr);
45388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    neighsum = lastcolsum + (colsum - membersum) + colsum;
45488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    membersum = membersum * memberscale + neighsum * neighscale;
45536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    *outptr = (JSAMPLE) ((membersum + 32768) >> 16);
45688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
45788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane  }
45888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane}
45988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
46088aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane#endif /* INPUT_SMOOTHING_SUPPORTED */
46188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
46288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane
4632cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane/*
46436a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane * Module initialization routine for downsampling.
4652cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane * Note that we must select a routine for each component.
4662cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane */
4672cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane
468489583f5165e05d37302e8eeec58104ea0109127Thomas G. LaneGLOBAL(void)
46936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lanejinit_downsampler (j_compress_ptr cinfo)
4702cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane{
47136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  my_downsample_ptr downsample;
47236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  int ci;
4732cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane  jpeg_component_info * compptr;
47488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane  boolean smoothok = TRUE;
4752cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane
47636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  downsample = (my_downsample_ptr)
47736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
4785de454b291f48382648a5d1dc2aa0fca8b5786d4DRC                                sizeof(my_downsampler));
47936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  cinfo->downsample = (struct jpeg_downsampler *) downsample;
48036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  downsample->pub.start_pass = start_pass_downsample;
48136a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  downsample->pub.downsample = sep_downsample;
48236a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  downsample->pub.need_context_rows = FALSE;
48336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane
4842cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane  if (cinfo->CCIR601_sampling)
48536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
4862cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane
48736a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  /* Verify we can handle the sampling factors, and set up method pointers */
48836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
48936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane       ci++, compptr++) {
4902cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane    if (compptr->h_samp_factor == cinfo->max_h_samp_factor &&
491b775351012af176720429ac21d11682a0b75b4b7DRC        compptr->v_samp_factor == cinfo->max_v_samp_factor) {
49288aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane#ifdef INPUT_SMOOTHING_SUPPORTED
49336a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      if (cinfo->smoothing_factor) {
494b775351012af176720429ac21d11682a0b75b4b7DRC        downsample->methods[ci] = fullsize_smooth_downsample;
495b775351012af176720429ac21d11682a0b75b4b7DRC        downsample->pub.need_context_rows = TRUE;
49636a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      } else
49788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane#endif
498b775351012af176720429ac21d11682a0b75b4b7DRC        downsample->methods[ci] = fullsize_downsample;
49988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&
500b775351012af176720429ac21d11682a0b75b4b7DRC               compptr->v_samp_factor == cinfo->max_v_samp_factor) {
50188aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane      smoothok = FALSE;
50259a3938b2e3f6c49730a57935f389078219a8fabPierre Ossman      if (jsimd_can_h2v1_downsample())
50359a3938b2e3f6c49730a57935f389078219a8fabPierre Ossman        downsample->methods[ci] = jsimd_h2v1_downsample;
50459a3938b2e3f6c49730a57935f389078219a8fabPierre Ossman      else
50559a3938b2e3f6c49730a57935f389078219a8fabPierre Ossman        downsample->methods[ci] = h2v1_downsample;
50688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&
507b775351012af176720429ac21d11682a0b75b4b7DRC               compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) {
50888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane#ifdef INPUT_SMOOTHING_SUPPORTED
50936a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      if (cinfo->smoothing_factor) {
510a3c3bbc2f43074900fb4c5062c0e1b9286f113e7DRC#if defined(__mips__)
5116a61c1e6dc0263148e8e8e1a13da8624cc5a065fDRC        if (jsimd_can_h2v2_smooth_downsample())
5126a61c1e6dc0263148e8e8e1a13da8624cc5a065fDRC          downsample->methods[ci] = jsimd_h2v2_smooth_downsample;
5136a61c1e6dc0263148e8e8e1a13da8624cc5a065fDRC        else
514a3c3bbc2f43074900fb4c5062c0e1b9286f113e7DRC#endif
5156a61c1e6dc0263148e8e8e1a13da8624cc5a065fDRC          downsample->methods[ci] = h2v2_smooth_downsample;
516b775351012af176720429ac21d11682a0b75b4b7DRC        downsample->pub.need_context_rows = TRUE;
517b329697ded0b8cdc6d00bcaf39f56c779b9182f6DRC      } else
51888aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane#endif
519b329697ded0b8cdc6d00bcaf39f56c779b9182f6DRC      {
520b775351012af176720429ac21d11682a0b75b4b7DRC        if (jsimd_can_h2v2_downsample())
521b775351012af176720429ac21d11682a0b75b4b7DRC          downsample->methods[ci] = jsimd_h2v2_downsample;
522b775351012af176720429ac21d11682a0b75b4b7DRC        else
523b775351012af176720429ac21d11682a0b75b4b7DRC          downsample->methods[ci] = h2v2_downsample;
5243b489c3af780cfd1c9243eb58eb12f76a76491eeDRC      }
52588aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 &&
526b775351012af176720429ac21d11682a0b75b4b7DRC               (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) {
52788aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane      smoothok = FALSE;
52836a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      downsample->methods[ci] = int_downsample;
52988aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane    } else
53036a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane      ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
5312cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane  }
5322cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane
53388aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane#ifdef INPUT_SMOOTHING_SUPPORTED
53488aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane  if (cinfo->smoothing_factor && !smoothok)
53536a4ccccd33f5cc9df62949554af87129ced7f84Thomas G. Lane    TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL);
53688aeed428fd820659e3ae00292cb84ecfc05dd23Thomas G. Lane#endif
5372cbeb8abd92d5ad8a1bd415b51b3816213b15f3Thomas G. Lane}
538