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



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ae4571287 Thu Nov 23 00:06:53 2017 +0100 at dom oct 27 23:51:55 CET 2019