~dcow90/myro-c++/extern-c

« back to all changes in this revision

Viewing changes to jpeg/jdsample.c

  • Committer: John Hoare
  • Date: 2011-05-15 12:49:43 UTC
  • mfrom: (81.1.19 cimg-backend)
  • Revision ID: john@johnami.com-20110515124943-2twlnindkrt1zeo9
Changed backend to CImg, added Graphics Library, added a rudimentary joystick control program using the Drawing Library. 

Put in our own version of libjpeg so we no longer rely on the system's libjpeg. 

Picture object's show() method is no longer necessarily a blocking call now. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * jdsample.c
 
3
 *
 
4
 * Copyright (C) 1991-1996, Thomas G. Lane.
 
5
 * This file is part of the Independent JPEG Group's software.
 
6
 * For conditions of distribution and use, see the accompanying README file.
 
7
 *
 
8
 * This file contains upsampling routines.
 
9
 *
 
10
 * Upsampling input data is counted in "row groups".  A row group
 
11
 * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size)
 
12
 * sample rows of each component.  Upsampling will normally produce
 
13
 * max_v_samp_factor pixel rows from each row group (but this could vary
 
14
 * if the upsampler is applying a scale factor of its own).
 
15
 *
 
16
 * An excellent reference for image resampling is
 
17
 *   Digital Image Warping, George Wolberg, 1990.
 
18
 *   Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
 
19
 */
 
20
 
 
21
#define JPEG_INTERNALS
 
22
#include "myrojinclude.h"
 
23
#include "myrojpeglib.h"
 
24
 
 
25
 
 
26
/* Pointer to routine to upsample a single component */
 
27
typedef JMETHOD(void, upsample1_ptr,
 
28
                (j_decompress_ptr cinfo, jpeg_component_info * compptr,
 
29
                 JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr));
 
30
 
 
31
/* Private subobject */
 
32
 
 
33
typedef struct {
 
34
  struct jpeg_upsampler pub;    /* public fields */
 
35
 
 
36
  /* Color conversion buffer.  When using separate upsampling and color
 
37
   * conversion steps, this buffer holds one upsampled row group until it
 
38
   * has been color converted and output.
 
39
   * Note: we do not allocate any storage for component(s) which are full-size,
 
40
   * ie do not need rescaling.  The corresponding entry of color_buf[] is
 
41
   * simply set to point to the input data array, thereby avoiding copying.
 
42
   */
 
43
  JSAMPARRAY color_buf[MAX_COMPONENTS];
 
44
 
 
45
  /* Per-component upsampling method pointers */
 
46
  upsample1_ptr methods[MAX_COMPONENTS];
 
47
 
 
48
  int next_row_out;             /* counts rows emitted from color_buf */
 
49
  JDIMENSION rows_to_go;        /* counts rows remaining in image */
 
50
 
 
51
  /* Height of an input row group for each component. */
 
52
  int rowgroup_height[MAX_COMPONENTS];
 
53
 
 
54
  /* These arrays save pixel expansion factors so that int_expand need not
 
55
   * recompute them each time.  They are unused for other upsampling methods.
 
56
   */
 
57
  UINT8 h_expand[MAX_COMPONENTS];
 
58
  UINT8 v_expand[MAX_COMPONENTS];
 
59
} my_upsampler;
 
60
 
 
61
typedef my_upsampler * my_upsample_ptr;
 
62
 
 
63
 
 
64
/*
 
65
 * Initialize for an upsampling pass.
 
66
 */
 
67
 
 
68
METHODDEF(void)
 
69
start_pass_upsample (j_decompress_ptr cinfo)
 
70
{
 
71
  my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
 
72
 
 
73
  /* Mark the conversion buffer empty */
 
74
  upsample->next_row_out = cinfo->max_v_samp_factor;
 
75
  /* Initialize total-height counter for detecting bottom of image */
 
76
  upsample->rows_to_go = cinfo->output_height;
 
77
}
 
78
 
 
79
 
 
80
/*
 
81
 * Control routine to do upsampling (and color conversion).
 
82
 *
 
83
 * In this version we upsample each component independently.
 
84
 * We upsample one row group into the conversion buffer, then apply
 
85
 * color conversion a row at a time.
 
86
 */
 
87
 
 
88
METHODDEF(void)
 
89
sep_upsample (j_decompress_ptr cinfo,
 
90
              JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
 
91
              JDIMENSION in_row_groups_avail,
 
92
              JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
 
93
              JDIMENSION out_rows_avail)
 
94
{
 
95
  my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
 
96
  int ci;
 
97
  jpeg_component_info * compptr;
 
98
  JDIMENSION num_rows;
 
99
 
 
100
  /* Fill the conversion buffer, if it's empty */
 
101
  if (upsample->next_row_out >= cinfo->max_v_samp_factor) {
 
102
    for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
 
103
         ci++, compptr++) {
 
104
      /* Invoke per-component upsample method.  Notice we pass a POINTER
 
105
       * to color_buf[ci], so that fullsize_upsample can change it.
 
106
       */
 
107
      (*upsample->methods[ci]) (cinfo, compptr,
 
108
        input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]),
 
109
        upsample->color_buf + ci);
 
110
    }
 
111
    upsample->next_row_out = 0;
 
112
  }
 
113
 
 
114
  /* Color-convert and emit rows */
 
115
 
 
116
  /* How many we have in the buffer: */
 
117
  num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out);
 
118
  /* Not more than the distance to the end of the image.  Need this test
 
119
   * in case the image height is not a multiple of max_v_samp_factor:
 
120
   */
 
121
  if (num_rows > upsample->rows_to_go) 
 
122
    num_rows = upsample->rows_to_go;
 
123
  /* And not more than what the client can accept: */
 
124
  out_rows_avail -= *out_row_ctr;
 
125
  if (num_rows > out_rows_avail)
 
126
    num_rows = out_rows_avail;
 
127
 
 
128
  (*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf,
 
129
                                     (JDIMENSION) upsample->next_row_out,
 
130
                                     output_buf + *out_row_ctr,
 
131
                                     (int) num_rows);
 
132
 
 
133
  /* Adjust counts */
 
134
  *out_row_ctr += num_rows;
 
135
  upsample->rows_to_go -= num_rows;
 
136
  upsample->next_row_out += num_rows;
 
137
  /* When the buffer is emptied, declare this input row group consumed */
 
138
  if (upsample->next_row_out >= cinfo->max_v_samp_factor)
 
139
    (*in_row_group_ctr)++;
 
140
}
 
141
 
 
142
 
 
143
/*
 
144
 * These are the routines invoked by sep_upsample to upsample pixel values
 
145
 * of a single component.  One row group is processed per call.
 
146
 */
 
147
 
 
148
 
 
149
/*
 
150
 * For full-size components, we just make color_buf[ci] point at the
 
151
 * input buffer, and thus avoid copying any data.  Note that this is
 
152
 * safe only because sep_upsample doesn't declare the input row group
 
153
 * "consumed" until we are done color converting and emitting it.
 
154
 */
 
155
 
 
156
METHODDEF(void)
 
157
fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
 
158
                   JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
 
159
{
 
160
  *output_data_ptr = input_data;
 
161
}
 
162
 
 
163
 
 
164
/*
 
165
 * This is a no-op version used for "uninteresting" components.
 
166
 * These components will not be referenced by color conversion.
 
167
 */
 
168
 
 
169
METHODDEF(void)
 
170
noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
 
171
               JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
 
172
{
 
173
  *output_data_ptr = NULL;      /* safety check */
 
174
}
 
175
 
 
176
 
 
177
/*
 
178
 * This version handles any integral sampling ratios.
 
179
 * This is not used for typical JPEG files, so it need not be fast.
 
180
 * Nor, for that matter, is it particularly accurate: the algorithm is
 
181
 * simple replication of the input pixel onto the corresponding output
 
182
 * pixels.  The hi-falutin sampling literature refers to this as a
 
183
 * "box filter".  A box filter tends to introduce visible artifacts,
 
184
 * so if you are actually going to use 3:1 or 4:1 sampling ratios
 
185
 * you would be well advised to improve this code.
 
186
 */
 
187
 
 
188
METHODDEF(void)
 
189
int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
 
190
              JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
 
191
{
 
192
  my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
 
193
  JSAMPARRAY output_data = *output_data_ptr;
 
194
  register JSAMPROW inptr, outptr;
 
195
  register JSAMPLE invalue;
 
196
  register int h;
 
197
  JSAMPROW outend;
 
198
  int h_expand, v_expand;
 
199
  int inrow, outrow;
 
200
 
 
201
  h_expand = upsample->h_expand[compptr->component_index];
 
202
  v_expand = upsample->v_expand[compptr->component_index];
 
203
 
 
204
  inrow = outrow = 0;
 
205
  while (outrow < cinfo->max_v_samp_factor) {
 
206
    /* Generate one output row with proper horizontal expansion */
 
207
    inptr = input_data[inrow];
 
208
    outptr = output_data[outrow];
 
209
    outend = outptr + cinfo->output_width;
 
210
    while (outptr < outend) {
 
211
      invalue = *inptr++;       /* don't need GETJSAMPLE() here */
 
212
      for (h = h_expand; h > 0; h--) {
 
213
        *outptr++ = invalue;
 
214
      }
 
215
    }
 
216
    /* Generate any additional output rows by duplicating the first one */
 
217
    if (v_expand > 1) {
 
218
      jcopy_sample_rows(output_data, outrow, output_data, outrow+1,
 
219
                        v_expand-1, cinfo->output_width);
 
220
    }
 
221
    inrow++;
 
222
    outrow += v_expand;
 
223
  }
 
224
}
 
225
 
 
226
 
 
227
/*
 
228
 * Fast processing for the common case of 2:1 horizontal and 1:1 vertical.
 
229
 * It's still a box filter.
 
230
 */
 
231
 
 
232
METHODDEF(void)
 
233
h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
 
234
               JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
 
235
{
 
236
  JSAMPARRAY output_data = *output_data_ptr;
 
237
  register JSAMPROW inptr, outptr;
 
238
  register JSAMPLE invalue;
 
239
  JSAMPROW outend;
 
240
  int inrow;
 
241
 
 
242
  for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) {
 
243
    inptr = input_data[inrow];
 
244
    outptr = output_data[inrow];
 
245
    outend = outptr + cinfo->output_width;
 
246
    while (outptr < outend) {
 
247
      invalue = *inptr++;       /* don't need GETJSAMPLE() here */
 
248
      *outptr++ = invalue;
 
249
      *outptr++ = invalue;
 
250
    }
 
251
  }
 
252
}
 
253
 
 
254
 
 
255
/*
 
256
 * Fast processing for the common case of 2:1 horizontal and 2:1 vertical.
 
257
 * It's still a box filter.
 
258
 */
 
259
 
 
260
METHODDEF(void)
 
261
h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
 
262
               JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
 
263
{
 
264
  JSAMPARRAY output_data = *output_data_ptr;
 
265
  register JSAMPROW inptr, outptr;
 
266
  register JSAMPLE invalue;
 
267
  JSAMPROW outend;
 
268
  int inrow, outrow;
 
269
 
 
270
  inrow = outrow = 0;
 
271
  while (outrow < cinfo->max_v_samp_factor) {
 
272
    inptr = input_data[inrow];
 
273
    outptr = output_data[outrow];
 
274
    outend = outptr + cinfo->output_width;
 
275
    while (outptr < outend) {
 
276
      invalue = *inptr++;       /* don't need GETJSAMPLE() here */
 
277
      *outptr++ = invalue;
 
278
      *outptr++ = invalue;
 
279
    }
 
280
    jcopy_sample_rows(output_data, outrow, output_data, outrow+1,
 
281
                      1, cinfo->output_width);
 
282
    inrow++;
 
283
    outrow += 2;
 
284
  }
 
285
}
 
286
 
 
287
 
 
288
/*
 
289
 * Fancy processing for the common case of 2:1 horizontal and 1:1 vertical.
 
290
 *
 
291
 * The upsampling algorithm is linear interpolation between pixel centers,
 
292
 * also known as a "triangle filter".  This is a good compromise between
 
293
 * speed and visual quality.  The centers of the output pixels are 1/4 and 3/4
 
294
 * of the way between input pixel centers.
 
295
 *
 
296
 * A note about the "bias" calculations: when rounding fractional values to
 
297
 * integer, we do not want to always round 0.5 up to the next integer.
 
298
 * If we did that, we'd introduce a noticeable bias towards larger values.
 
299
 * Instead, this code is arranged so that 0.5 will be rounded up or down at
 
300
 * alternate pixel locations (a simple ordered dither pattern).
 
301
 */
 
302
 
 
303
METHODDEF(void)
 
304
h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
 
305
                     JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
 
306
{
 
307
  JSAMPARRAY output_data = *output_data_ptr;
 
308
  register JSAMPROW inptr, outptr;
 
309
  register int invalue;
 
310
  register JDIMENSION colctr;
 
311
  int inrow;
 
312
 
 
313
  for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) {
 
314
    inptr = input_data[inrow];
 
315
    outptr = output_data[inrow];
 
316
    /* Special case for first column */
 
317
    invalue = GETJSAMPLE(*inptr++);
 
318
    *outptr++ = (JSAMPLE) invalue;
 
319
    *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2);
 
320
 
 
321
    for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) {
 
322
      /* General case: 3/4 * nearer pixel + 1/4 * further pixel */
 
323
      invalue = GETJSAMPLE(*inptr++) * 3;
 
324
      *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2);
 
325
      *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2);
 
326
    }
 
327
 
 
328
    /* Special case for last column */
 
329
    invalue = GETJSAMPLE(*inptr);
 
330
    *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2);
 
331
    *outptr++ = (JSAMPLE) invalue;
 
332
  }
 
333
}
 
334
 
 
335
 
 
336
/*
 
337
 * Fancy processing for the common case of 2:1 horizontal and 2:1 vertical.
 
338
 * Again a triangle filter; see comments for h2v1 case, above.
 
339
 *
 
340
 * It is OK for us to reference the adjacent input rows because we demanded
 
341
 * context from the main buffer controller (see initialization code).
 
342
 */
 
343
 
 
344
METHODDEF(void)
 
345
h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
 
346
                     JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
 
347
{
 
348
  JSAMPARRAY output_data = *output_data_ptr;
 
349
  register JSAMPROW inptr0, inptr1, outptr;
 
350
#if BITS_IN_JSAMPLE == 8
 
351
  register int thiscolsum, lastcolsum, nextcolsum;
 
352
#else
 
353
  register INT32 thiscolsum, lastcolsum, nextcolsum;
 
354
#endif
 
355
  register JDIMENSION colctr;
 
356
  int inrow, outrow, v;
 
357
 
 
358
  inrow = outrow = 0;
 
359
  while (outrow < cinfo->max_v_samp_factor) {
 
360
    for (v = 0; v < 2; v++) {
 
361
      /* inptr0 points to nearest input row, inptr1 points to next nearest */
 
362
      inptr0 = input_data[inrow];
 
363
      if (v == 0)               /* next nearest is row above */
 
364
        inptr1 = input_data[inrow-1];
 
365
      else                      /* next nearest is row below */
 
366
        inptr1 = input_data[inrow+1];
 
367
      outptr = output_data[outrow++];
 
368
 
 
369
      /* Special case for first column */
 
370
      thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
 
371
      nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
 
372
      *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4);
 
373
      *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4);
 
374
      lastcolsum = thiscolsum; thiscolsum = nextcolsum;
 
375
 
 
376
      for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) {
 
377
        /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */
 
378
        /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */
 
379
        nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
 
380
        *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
 
381
        *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4);
 
382
        lastcolsum = thiscolsum; thiscolsum = nextcolsum;
 
383
      }
 
384
 
 
385
      /* Special case for last column */
 
386
      *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
 
387
      *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4);
 
388
    }
 
389
    inrow++;
 
390
  }
 
391
}
 
392
 
 
393
 
 
394
/*
 
395
 * Module initialization routine for upsampling.
 
396
 */
 
397
 
 
398
GLOBAL(void)
 
399
jinit_upsampler (j_decompress_ptr cinfo)
 
400
{
 
401
  my_upsample_ptr upsample;
 
402
  int ci;
 
403
  jpeg_component_info * compptr;
 
404
  boolean need_buffer, do_fancy;
 
405
  int h_in_group, v_in_group, h_out_group, v_out_group;
 
406
 
 
407
  upsample = (my_upsample_ptr)
 
408
    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
 
409
                                SIZEOF(my_upsampler));
 
410
  cinfo->upsample = (struct jpeg_upsampler *) upsample;
 
411
  upsample->pub.start_pass = start_pass_upsample;
 
412
  upsample->pub.upsample = sep_upsample;
 
413
  upsample->pub.need_context_rows = FALSE; /* until we find out differently */
 
414
 
 
415
  if (cinfo->CCIR601_sampling)  /* this isn't supported */
 
416
    ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
 
417
 
 
418
  /* jdmainct.c doesn't support context rows when min_DCT_scaled_size = 1,
 
419
   * so don't ask for it.
 
420
   */
 
421
  do_fancy = cinfo->do_fancy_upsampling && cinfo->min_DCT_scaled_size > 1;
 
422
 
 
423
  /* Verify we can handle the sampling factors, select per-component methods,
 
424
   * and create storage as needed.
 
425
   */
 
426
  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
 
427
       ci++, compptr++) {
 
428
    /* Compute size of an "input group" after IDCT scaling.  This many samples
 
429
     * are to be converted to max_h_samp_factor * max_v_samp_factor pixels.
 
430
     */
 
431
    h_in_group = (compptr->h_samp_factor * compptr->DCT_scaled_size) /
 
432
                 cinfo->min_DCT_scaled_size;
 
433
    v_in_group = (compptr->v_samp_factor * compptr->DCT_scaled_size) /
 
434
                 cinfo->min_DCT_scaled_size;
 
435
    h_out_group = cinfo->max_h_samp_factor;
 
436
    v_out_group = cinfo->max_v_samp_factor;
 
437
    upsample->rowgroup_height[ci] = v_in_group; /* save for use later */
 
438
    need_buffer = TRUE;
 
439
    if (! compptr->component_needed) {
 
440
      /* Don't bother to upsample an uninteresting component. */
 
441
      upsample->methods[ci] = noop_upsample;
 
442
      need_buffer = FALSE;
 
443
    } else if (h_in_group == h_out_group && v_in_group == v_out_group) {
 
444
      /* Fullsize components can be processed without any work. */
 
445
      upsample->methods[ci] = fullsize_upsample;
 
446
      need_buffer = FALSE;
 
447
    } else if (h_in_group * 2 == h_out_group &&
 
448
               v_in_group == v_out_group) {
 
449
      /* Special cases for 2h1v upsampling */
 
450
      if (do_fancy && compptr->downsampled_width > 2)
 
451
        upsample->methods[ci] = h2v1_fancy_upsample;
 
452
      else
 
453
        upsample->methods[ci] = h2v1_upsample;
 
454
    } else if (h_in_group * 2 == h_out_group &&
 
455
               v_in_group * 2 == v_out_group) {
 
456
      /* Special cases for 2h2v upsampling */
 
457
      if (do_fancy && compptr->downsampled_width > 2) {
 
458
        upsample->methods[ci] = h2v2_fancy_upsample;
 
459
        upsample->pub.need_context_rows = TRUE;
 
460
      } else
 
461
        upsample->methods[ci] = h2v2_upsample;
 
462
    } else if ((h_out_group % h_in_group) == 0 &&
 
463
               (v_out_group % v_in_group) == 0) {
 
464
      /* Generic integral-factors upsampling method */
 
465
      upsample->methods[ci] = int_upsample;
 
466
      upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group);
 
467
      upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group);
 
468
    } else
 
469
      ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
 
470
    if (need_buffer) {
 
471
      upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray)
 
472
        ((j_common_ptr) cinfo, JPOOL_IMAGE,
 
473
         (JDIMENSION) jround_up((long) cinfo->output_width,
 
474
                                (long) cinfo->max_h_samp_factor),
 
475
         (JDIMENSION) cinfo->max_v_samp_factor);
 
476
    }
 
477
  }
 
478
}