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



Page generated by Doxygen 1.8.14 for MRPT 1.5.7 Git: 5902e14cc Wed Apr 24 15:04:01 2019 +0200 at lun oct 28 01:39:17 CET 2019