Coverage Report

Created: 2025-06-10 07:15

/src/ghostpdl/obj/jcsample.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * jcsample.c
3
 *
4
 * Copyright (C) 1991-1996, Thomas G. Lane.
5
 * Modified 2003-2020 by Guido Vollbeding.
6
 * This file is part of the Independent JPEG Group's software.
7
 * For conditions of distribution and use, see the accompanying README file.
8
 *
9
 * This file contains downsampling routines.
10
 *
11
 * Downsampling input data is counted in "row groups".  A row group
12
 * is defined to be max_v_samp_factor pixel rows of each component,
13
 * from which the downsampler produces v_samp_factor sample rows.
14
 * A single row group is processed in each call to the downsampler module.
15
 *
16
 * The downsampler is responsible for edge-expansion of its output data
17
 * to fill an integral number of DCT blocks horizontally.  The source buffer
18
 * may be modified if it is helpful for this purpose (the source buffer is
19
 * allocated wide enough to correspond to the desired output width).
20
 * The caller (the prep controller) is responsible for vertical padding.
21
 *
22
 * The downsampler may request "context rows" by setting need_context_rows
23
 * during startup.  In this case, the input arrays will contain at least
24
 * one row group's worth of pixels above and below the passed-in data;
25
 * the caller will create dummy rows at image top and bottom by replicating
26
 * the first or last real pixel row.
27
 *
28
 * An excellent reference for image resampling is
29
 *   Digital Image Warping, George Wolberg, 1990.
30
 *   Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
31
 *
32
 * The downsampling algorithm used here is a simple average of the source
33
 * pixels covered by the output pixel.  The hi-falutin sampling literature
34
 * refers to this as a "box filter".  In general the characteristics of a box
35
 * filter are not very good, but for the specific cases we normally use (1:1
36
 * and 2:1 ratios) the box is equivalent to a "triangle filter" which is not
37
 * nearly so bad.  If you intend to use other sampling ratios, you'd be well
38
 * advised to improve this code.
39
 *
40
 * A simple input-smoothing capability is provided.  This is mainly intended
41
 * for cleaning up color-dithered GIF input files (if you find it inadequate,
42
 * we suggest using an external filtering program such as pnmconvol).  When
43
 * enabled, each input pixel P is replaced by a weighted sum of itself and its
44
 * eight neighbors.  P's weight is 1-8*SF and each neighbor's weight is SF,
45
 * where SF = (smoothing_factor / 1024).
46
 * Currently, smoothing is only supported for 2h2v sampling factors.
47
 */
48
49
#define JPEG_INTERNALS
50
#include "jinclude.h"
51
#include "jpeglib.h"
52
53
54
/* Pointer to routine to downsample a single component */
55
typedef JMETHOD(void, downsample1_ptr,
56
    (j_compress_ptr cinfo, jpeg_component_info * compptr,
57
     JSAMPARRAY input_data, JSAMPARRAY output_data));
58
59
/* Private subobject */
60
61
typedef struct {
62
  struct jpeg_downsampler pub;  /* public fields */
63
64
  /* Downsampling method pointers, one per component */
65
  downsample1_ptr methods[MAX_COMPONENTS];
66
67
  /* Height of an output row group for each component. */
68
  int rowgroup_height[MAX_COMPONENTS];
69
70
  /* These arrays save pixel expansion factors so that int_downsample need not
71
   * recompute them each time.  They are unused for other downsampling methods.
72
   */
73
  UINT8 h_expand[MAX_COMPONENTS];
74
  UINT8 v_expand[MAX_COMPONENTS];
75
} my_downsampler;
76
77
typedef my_downsampler * my_downsample_ptr;
78
79
80
/*
81
 * Initialize for a downsampling pass.
82
 */
83
84
METHODDEF(void)
85
start_pass_downsample (j_compress_ptr cinfo)
86
6
{
87
  /* no work for now */
88
6
}
89
90
91
/*
92
 * Expand a component horizontally from width input_cols to width output_cols,
93
 * by duplicating the rightmost samples.
94
 */
95
96
LOCAL(void)
97
expand_right_edge (JSAMPARRAY image_data, int num_rows,
98
       JDIMENSION input_cols, JDIMENSION output_cols)
99
2.68k
{
100
2.68k
  register JSAMPROW ptr;
101
2.68k
  register JSAMPLE pixval;
102
2.68k
  register int count;
103
2.68k
  int row;
104
2.68k
  int numcols = (int) (output_cols - input_cols);
105
106
2.68k
  if (numcols > 0) {
107
5.37k
    for (row = 0; row < num_rows; row++) {
108
2.68k
      ptr = image_data[row] + input_cols;
109
2.68k
      pixval = ptr[-1];   /* don't need GETJSAMPLE() here */
110
5.37k
      for (count = numcols; count > 0; count--)
111
2.68k
  *ptr++ = pixval;
112
2.68k
    }
113
2.68k
  }
114
2.68k
}
115
116
117
/*
118
 * Do downsampling for a whole row group (all components).
119
 *
120
 * In this version we simply downsample each component independently.
121
 */
122
123
METHODDEF(void)
124
sep_downsample (j_compress_ptr cinfo,
125
    JSAMPIMAGE input_buf, JDIMENSION in_row_index,
126
    JSAMPIMAGE output_buf, JDIMENSION out_row_group_index)
127
896
{
128
896
  my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample;
129
896
  int ci;
130
896
  jpeg_component_info * compptr;
131
896
  JSAMPARRAY in_ptr, out_ptr;
132
133
3.58k
  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
134
2.68k
       ci++, compptr++) {
135
2.68k
    in_ptr = input_buf[ci] + in_row_index;
136
2.68k
    out_ptr = output_buf[ci] +
137
2.68k
        (out_row_group_index * downsample->rowgroup_height[ci]);
138
2.68k
    (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr);
139
2.68k
  }
140
896
}
141
142
143
/*
144
 * Downsample pixel values of a single component.
145
 * One row group is processed per call.
146
 * This version handles arbitrary integral sampling ratios, without smoothing.
147
 * Note that this version is not actually used for customary sampling ratios.
148
 */
149
150
METHODDEF(void)
151
int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
152
    JSAMPARRAY input_data, JSAMPARRAY output_data)
153
0
{
154
0
  my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample;
155
0
  int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v;
156
0
  JDIMENSION outcol, outcol_h;  /* outcol_h == outcol*h_expand */
157
0
  JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size;
158
0
  JSAMPROW inptr, outptr;
159
0
  INT32 outvalue;
160
161
0
  h_expand = downsample->h_expand[compptr->component_index];
162
0
  v_expand = downsample->v_expand[compptr->component_index];
163
0
  numpix = h_expand * v_expand;
164
0
  numpix2 = numpix/2;
165
166
  /* Expand input data enough to let all the output samples be generated
167
   * by the standard loop.  Special-casing padded output would be more
168
   * efficient.
169
   */
170
0
  expand_right_edge(input_data, cinfo->max_v_samp_factor,
171
0
        cinfo->image_width, output_cols * h_expand);
172
173
0
  inrow = outrow = 0;
174
0
  while (inrow < cinfo->max_v_samp_factor) {
175
0
    outptr = output_data[outrow];
176
0
    for (outcol = 0, outcol_h = 0; outcol < output_cols;
177
0
   outcol++, outcol_h += h_expand) {
178
0
      outvalue = 0;
179
0
      for (v = 0; v < v_expand; v++) {
180
0
  inptr = input_data[inrow+v] + outcol_h;
181
0
  for (h = 0; h < h_expand; h++) {
182
0
    outvalue += (INT32) GETJSAMPLE(*inptr++);
183
0
  }
184
0
      }
185
0
      *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix);
186
0
    }
187
0
    inrow += v_expand;
188
0
    outrow++;
189
0
  }
190
0
}
191
192
193
/*
194
 * Downsample pixel values of a single component.
195
 * This version handles the special case of a full-size component,
196
 * without smoothing.
197
 */
198
199
METHODDEF(void)
200
fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
201
         JSAMPARRAY input_data, JSAMPARRAY output_data)
202
2.68k
{
203
  /* Copy the data */
204
2.68k
  jcopy_sample_rows(input_data, output_data,
205
2.68k
        cinfo->max_v_samp_factor, cinfo->image_width);
206
  /* Edge-expand */
207
2.68k
  expand_right_edge(output_data, cinfo->max_v_samp_factor, cinfo->image_width,
208
2.68k
        compptr->width_in_blocks * compptr->DCT_h_scaled_size);
209
2.68k
}
210
211
212
/*
213
 * Downsample pixel values of a single component.
214
 * This version handles the common case of 2:1 horizontal and 1:1 vertical,
215
 * without smoothing.
216
 *
217
 * A note about the "bias" calculations: when rounding fractional values to
218
 * integer, we do not want to always round 0.5 up to the next integer.
219
 * If we did that, we'd introduce a noticeable bias towards larger values.
220
 * Instead, this code is arranged so that 0.5 will be rounded up or down at
221
 * alternate pixel locations (a simple ordered dither pattern).
222
 */
223
224
METHODDEF(void)
225
h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
226
     JSAMPARRAY input_data, JSAMPARRAY output_data)
227
0
{
228
0
  int inrow;
229
0
  JDIMENSION outcol;
230
0
  JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size;
231
0
  register JSAMPROW inptr, outptr;
232
0
  register int bias;
233
234
  /* Expand input data enough to let all the output samples be generated
235
   * by the standard loop.  Special-casing padded output would be more
236
   * efficient.
237
   */
238
0
  expand_right_edge(input_data, cinfo->max_v_samp_factor,
239
0
        cinfo->image_width, output_cols * 2);
240
241
0
  for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) {
242
0
    outptr = output_data[inrow];
243
0
    inptr = input_data[inrow];
244
0
    bias = 0;     /* bias = 0,1,0,1,... for successive samples */
245
0
    for (outcol = 0; outcol < output_cols; outcol++) {
246
0
      *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1])
247
0
            + bias) >> 1);
248
0
      bias ^= 1;    /* 0=>1, 1=>0 */
249
0
      inptr += 2;
250
0
    }
251
0
  }
252
0
}
253
254
255
/*
256
 * Downsample pixel values of a single component.
257
 * This version handles the standard case of 2:1 horizontal and 2:1 vertical,
258
 * without smoothing.
259
 */
260
261
METHODDEF(void)
262
h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
263
     JSAMPARRAY input_data, JSAMPARRAY output_data)
264
0
{
265
0
  int inrow, outrow;
266
0
  JDIMENSION outcol;
267
0
  JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size;
268
0
  register JSAMPROW inptr0, inptr1, outptr;
269
0
  register int bias;
270
271
  /* Expand input data enough to let all the output samples be generated
272
   * by the standard loop.  Special-casing padded output would be more
273
   * efficient.
274
   */
275
0
  expand_right_edge(input_data, cinfo->max_v_samp_factor,
276
0
        cinfo->image_width, output_cols * 2);
277
278
0
  inrow = outrow = 0;
279
0
  while (inrow < cinfo->max_v_samp_factor) {
280
0
    outptr = output_data[outrow];
281
0
    inptr0 = input_data[inrow];
282
0
    inptr1 = input_data[inrow+1];
283
0
    bias = 1;     /* bias = 1,2,1,2,... for successive samples */
284
0
    for (outcol = 0; outcol < output_cols; outcol++) {
285
0
      *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
286
0
            GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1])
287
0
            + bias) >> 2);
288
0
      bias ^= 3;    /* 1=>2, 2=>1 */
289
0
      inptr0 += 2; inptr1 += 2;
290
0
    }
291
0
    inrow += 2;
292
0
    outrow++;
293
0
  }
294
0
}
295
296
297
#ifdef INPUT_SMOOTHING_SUPPORTED
298
299
/*
300
 * Downsample pixel values of a single component.
301
 * This version handles the standard case of 2:1 horizontal and 2:1 vertical,
302
 * with smoothing.  One row of context is required.
303
 */
304
305
METHODDEF(void)
306
h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
307
      JSAMPARRAY input_data, JSAMPARRAY output_data)
308
{
309
  int inrow, outrow;
310
  JDIMENSION colctr;
311
  JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size;
312
  register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr;
313
  INT32 membersum, neighsum, memberscale, neighscale;
314
315
  /* Expand input data enough to let all the output samples be generated
316
   * by the standard loop.  Special-casing padded output would be more
317
   * efficient.
318
   */
319
  expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
320
        cinfo->image_width, output_cols * 2);
321
322
  /* We don't bother to form the individual "smoothed" input pixel values;
323
   * we can directly compute the output which is the average of the four
324
   * smoothed values.  Each of the four member pixels contributes a fraction
325
   * (1-8*SF) to its own smoothed image and a fraction SF to each of the three
326
   * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final
327
   * output.  The four corner-adjacent neighbor pixels contribute a fraction
328
   * SF to just one smoothed pixel, or SF/4 to the final output; while the
329
   * eight edge-adjacent neighbors contribute SF to each of two smoothed
330
   * pixels, or SF/2 overall.  In order to use integer arithmetic, these
331
   * factors are scaled by 2^16 = 65536.
332
   * Also recall that SF = smoothing_factor / 1024.
333
   */
334
335
  memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */
336
  neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */
337
338
  inrow = outrow = 0;
339
  while (inrow < cinfo->max_v_samp_factor) {
340
    outptr = output_data[outrow];
341
    inptr0 = input_data[inrow];
342
    inptr1 = input_data[inrow+1];
343
    above_ptr = input_data[inrow-1];
344
    below_ptr = input_data[inrow+2];
345
346
    /* Special case for first column: pretend column -1 is same as column 0 */
347
    membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
348
    GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
349
    neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
350
         GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
351
         GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) +
352
         GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]);
353
    neighsum += neighsum;
354
    neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) +
355
    GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]);
356
    membersum = membersum * memberscale + neighsum * neighscale;
357
    *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
358
    inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
359
360
    for (colctr = output_cols - 2; colctr > 0; colctr--) {
361
      /* sum of pixels directly mapped to this output element */
362
      membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
363
      GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
364
      /* sum of edge-neighbor pixels */
365
      neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
366
     GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
367
     GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) +
368
     GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]);
369
      /* The edge-neighbors count twice as much as corner-neighbors */
370
      neighsum += neighsum;
371
      /* Add in the corner-neighbors */
372
      neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) +
373
      GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]);
374
      /* form final output scaled up by 2^16 */
375
      membersum = membersum * memberscale + neighsum * neighscale;
376
      /* round, descale and output it */
377
      *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
378
      inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
379
    }
380
381
    /* Special case for last column */
382
    membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
383
    GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
384
    neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
385
         GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
386
         GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) +
387
         GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]);
388
    neighsum += neighsum;
389
    neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) +
390
    GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]);
391
    membersum = membersum * memberscale + neighsum * neighscale;
392
    *outptr = (JSAMPLE) ((membersum + 32768) >> 16);
393
394
    inrow += 2;
395
    outrow++;
396
  }
397
}
398
399
400
/*
401
 * Downsample pixel values of a single component.
402
 * This version handles the special case of a full-size component,
403
 * with smoothing.  One row of context is required.
404
 */
405
406
METHODDEF(void)
407
fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
408
          JSAMPARRAY input_data, JSAMPARRAY output_data)
409
{
410
  int inrow;
411
  JDIMENSION colctr;
412
  JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size;
413
  register JSAMPROW inptr, above_ptr, below_ptr, outptr;
414
  INT32 membersum, neighsum, memberscale, neighscale;
415
  int colsum, lastcolsum, nextcolsum;
416
417
  /* Expand input data enough to let all the output samples be generated
418
   * by the standard loop.  Special-casing padded output would be more
419
   * efficient.
420
   */
421
  expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
422
        cinfo->image_width, output_cols);
423
424
  /* Each of the eight neighbor pixels contributes a fraction SF to the
425
   * smoothed pixel, while the main pixel contributes (1-8*SF).  In order
426
   * to use integer arithmetic, these factors are multiplied by 2^16 = 65536.
427
   * Also recall that SF = smoothing_factor / 1024.
428
   */
429
430
  memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */
431
  neighscale = cinfo->smoothing_factor * 64; /* scaled SF */
432
433
  for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) {
434
    outptr = output_data[inrow];
435
    inptr = input_data[inrow];
436
    above_ptr = input_data[inrow-1];
437
    below_ptr = input_data[inrow+1];
438
439
    /* Special case for first column */
440
    colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) +
441
       GETJSAMPLE(*inptr);
442
    membersum = GETJSAMPLE(*inptr++);
443
    nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
444
     GETJSAMPLE(*inptr);
445
    neighsum = colsum + (colsum - membersum) + nextcolsum;
446
    membersum = membersum * memberscale + neighsum * neighscale;
447
    *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
448
    lastcolsum = colsum; colsum = nextcolsum;
449
450
    for (colctr = output_cols - 2; colctr > 0; colctr--) {
451
      membersum = GETJSAMPLE(*inptr++);
452
      above_ptr++; below_ptr++;
453
      nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
454
       GETJSAMPLE(*inptr);
455
      neighsum = lastcolsum + (colsum - membersum) + nextcolsum;
456
      membersum = membersum * memberscale + neighsum * neighscale;
457
      *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
458
      lastcolsum = colsum; colsum = nextcolsum;
459
    }
460
461
    /* Special case for last column */
462
    membersum = GETJSAMPLE(*inptr);
463
    neighsum = lastcolsum + (colsum - membersum) + colsum;
464
    membersum = membersum * memberscale + neighsum * neighscale;
465
    *outptr = (JSAMPLE) ((membersum + 32768) >> 16);
466
467
  }
468
}
469
470
#endif /* INPUT_SMOOTHING_SUPPORTED */
471
472
473
/*
474
 * Module initialization routine for downsampling.
475
 * Note that we must select a routine for each component.
476
 */
477
478
GLOBAL(void)
479
jinit_downsampler (j_compress_ptr cinfo)
480
6
{
481
6
  my_downsample_ptr downsample;
482
6
  int ci;
483
6
  jpeg_component_info * compptr;
484
6
  boolean smoothok = TRUE;
485
6
  int h_in_group, v_in_group, h_out_group, v_out_group;
486
487
6
  downsample = (my_downsample_ptr) (*cinfo->mem->alloc_small)
488
6
    ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_downsampler));
489
6
  cinfo->downsample = &downsample->pub;
490
6
  downsample->pub.start_pass = start_pass_downsample;
491
6
  downsample->pub.downsample = sep_downsample;
492
6
  downsample->pub.need_context_rows = FALSE;
493
494
6
  if (cinfo->CCIR601_sampling)
495
0
    ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
496
497
  /* Verify we can handle the sampling factors, and set up method pointers */
498
24
  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
499
18
       ci++, compptr++) {
500
    /* Compute size of an "output group" for DCT scaling.  This many samples
501
     * are to be converted from max_h_samp_factor * max_v_samp_factor pixels.
502
     */
503
18
    h_out_group = (compptr->h_samp_factor * compptr->DCT_h_scaled_size) /
504
18
      cinfo->min_DCT_h_scaled_size;
505
18
    v_out_group = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) /
506
18
      cinfo->min_DCT_v_scaled_size;
507
18
    h_in_group = cinfo->max_h_samp_factor;
508
18
    v_in_group = cinfo->max_v_samp_factor;
509
18
    downsample->rowgroup_height[ci] = v_out_group; /* save for use later */
510
18
    if (h_in_group == h_out_group && v_in_group == v_out_group) {
511
#ifdef INPUT_SMOOTHING_SUPPORTED
512
      if (cinfo->smoothing_factor) {
513
  downsample->methods[ci] = fullsize_smooth_downsample;
514
  downsample->pub.need_context_rows = TRUE;
515
      } else
516
#endif
517
18
  downsample->methods[ci] = fullsize_downsample;
518
18
    } else if (h_in_group == h_out_group * 2 &&
519
0
         v_in_group == v_out_group) {
520
0
      smoothok = FALSE;
521
0
      downsample->methods[ci] = h2v1_downsample;
522
0
    } else if (h_in_group == h_out_group * 2 &&
523
0
         v_in_group == v_out_group * 2) {
524
#ifdef INPUT_SMOOTHING_SUPPORTED
525
      if (cinfo->smoothing_factor) {
526
  downsample->methods[ci] = h2v2_smooth_downsample;
527
  downsample->pub.need_context_rows = TRUE;
528
      } else
529
#endif
530
0
  downsample->methods[ci] = h2v2_downsample;
531
0
    } else if ((h_in_group % h_out_group) == 0 &&
532
0
         (v_in_group % v_out_group) == 0) {
533
0
      smoothok = FALSE;
534
0
      downsample->methods[ci] = int_downsample;
535
0
      downsample->h_expand[ci] = (UINT8) (h_in_group / h_out_group);
536
0
      downsample->v_expand[ci] = (UINT8) (v_in_group / v_out_group);
537
0
    } else
538
0
      ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
539
18
  }
540
541
#ifdef INPUT_SMOOTHING_SUPPORTED
542
  if (cinfo->smoothing_factor && !smoothok)
543
    TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL);
544
#endif
545
6
}