Main MRPT website > C++ reference for MRPT 1.5.6
jcprepct.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 /* At present, jcsample.c can request context rows only for smoothing.
16  * In the future, we might also need context rows for CCIR601 sampling
17  * or other more-complex downsampling procedures. The code to support
18  * context rows should be compiled only if needed.
19  */
20 #ifdef INPUT_SMOOTHING_SUPPORTED
21 #define CONTEXT_ROWS_SUPPORTED
22 #endif
23 
24 
25 /*
26  * For the simple (no-context-row) case, we just need to buffer one
27  * row group's worth of pixels for the downsampling step. At the bottom of
28  * the image, we pad to a full row group by replicating the last pixel row.
29  * The downsampler's last output row is then replicated if needed to pad
30  * out to a full iMCU row.
31  *
32  * When providing context rows, we must buffer three row groups' worth of
33  * pixels. Three row groups are physically allocated, but the row pointer
34  * arrays are made five row groups high, with the extra pointers above and
35  * below "wrapping around" to point to the last and first real row groups.
36  * This allows the downsampler to access the proper context rows.
37  * At the top and bottom of the image, we create dummy context rows by
38  * copying the first or last real pixel row. This copying could be avoided
39  * by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the
40  * trouble on the compression side.
41  */
42 
43 
44 /* Private buffer controller object */
45 
46 typedef struct {
47  struct jpeg_c_prep_controller pub; /* public fields */
48 
49  /* Downsampling input buffer. This buffer holds color-converted data
50  * until we have enough to do a downsample step.
51  */
53 
54  JDIMENSION rows_to_go; /* counts rows remaining in source image */
55  int next_buf_row; /* index of next row to store in color_buf */
56 
57 #ifdef CONTEXT_ROWS_SUPPORTED /* only needed for context case */
58  int this_row_group; /* starting row index of group to process */
59  int next_buf_stop; /* downsample when we reach this index */
60 #endif
62 
64 
65 
66 /*
67  * Initialize for a processing pass.
68  */
69 
70 METHODDEF(void)
72 {
73  my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
74 
75  if (pass_mode != JBUF_PASS_THRU)
76  ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
77 
78  /* Initialize total-height counter for detecting bottom of image */
79  prep->rows_to_go = cinfo->image_height;
80  /* Mark the conversion buffer empty */
81  prep->next_buf_row = 0;
82 #ifdef CONTEXT_ROWS_SUPPORTED
83  /* Preset additional state variables for context mode.
84  * These aren't used in non-context mode, so we needn't test which mode.
85  */
86  prep->this_row_group = 0;
87  /* Set next_buf_stop to stop after two row groups have been read in. */
88  prep->next_buf_stop = 2 * cinfo->max_v_samp_factor;
89 #endif
90 }
91 
92 
93 /*
94  * Expand an image vertically from height input_rows to height output_rows,
95  * by duplicating the bottom row.
96  */
97 
98 LOCAL(void)
100  int input_rows, int output_rows)
101 {
102  int row;
103 
104  for (row = input_rows; row < output_rows; row++) {
105  jcopy_sample_rows(image_data, input_rows-1, image_data, row,
106  1, num_cols);
107  }
108 }
109 
110 
111 /*
112  * Process some data in the simple no-context case.
113  *
114  * Preprocessor output data is counted in "row groups". A row group
115  * is defined to be v_samp_factor sample rows of each component.
116  * Downsampling will produce this much data from each max_v_samp_factor
117  * input rows.
118  */
119 
120 METHODDEF(void)
124  JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
125  JDIMENSION out_row_groups_avail)
126 {
127  my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
128  int numrows, ci;
129  JDIMENSION inrows;
131 
132  while (*in_row_ctr < in_rows_avail &&
133  *out_row_group_ctr < out_row_groups_avail) {
134  /* Do color conversion to fill the conversion buffer. */
135  inrows = in_rows_avail - *in_row_ctr;
136  numrows = cinfo->max_v_samp_factor - prep->next_buf_row;
137  numrows = (int) MIN((JDIMENSION) numrows, inrows);
138  (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
139  prep->color_buf,
140  (JDIMENSION) prep->next_buf_row,
141  numrows);
142  *in_row_ctr += numrows;
143  prep->next_buf_row += numrows;
144  prep->rows_to_go -= numrows;
145  /* If at bottom of image, pad to fill the conversion buffer. */
146  if (prep->rows_to_go == 0 &&
147  prep->next_buf_row < cinfo->max_v_samp_factor) {
148  for (ci = 0; ci < cinfo->num_components; ci++) {
149  expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,
150  prep->next_buf_row, cinfo->max_v_samp_factor);
151  }
152  prep->next_buf_row = cinfo->max_v_samp_factor;
153  }
154  /* If we've filled the conversion buffer, empty it. */
155  if (prep->next_buf_row == cinfo->max_v_samp_factor) {
156  (*cinfo->downsample->downsample) (cinfo,
157  prep->color_buf, (JDIMENSION) 0,
158  output_buf, *out_row_group_ctr);
159  prep->next_buf_row = 0;
160  (*out_row_group_ctr)++;
161  }
162  /* If at bottom of image, pad the output to a full iMCU height.
163  * Note we assume the caller is providing a one-iMCU-height output buffer!
164  */
165  if (prep->rows_to_go == 0 &&
166  *out_row_group_ctr < out_row_groups_avail) {
167  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
168  ci++, compptr++) {
171  (int) (*out_row_group_ctr * compptr->v_samp_factor),
172  (int) (out_row_groups_avail * compptr->v_samp_factor));
173  }
174  *out_row_group_ctr = out_row_groups_avail;
175  break; /* can exit outer loop without test */
176  }
177  }
178 }
179 
180 
181 #ifdef CONTEXT_ROWS_SUPPORTED
182 
183 /*
184  * Process some data in the context case.
185  */
186 
187 METHODDEF(void)
191  JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
192  JDIMENSION out_row_groups_avail)
193 {
194  my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
195  int numrows, ci;
196  int buf_height = cinfo->max_v_samp_factor * 3;
197  JDIMENSION inrows;
198 
199  while (*out_row_group_ctr < out_row_groups_avail) {
200  if (*in_row_ctr < in_rows_avail) {
201  /* Do color conversion to fill the conversion buffer. */
202  inrows = in_rows_avail - *in_row_ctr;
203  numrows = prep->next_buf_stop - prep->next_buf_row;
204  numrows = (int) MIN((JDIMENSION) numrows, inrows);
205  (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
206  prep->color_buf,
207  (JDIMENSION) prep->next_buf_row,
208  numrows);
209  /* Pad at top of image, if first time through */
210  if (prep->rows_to_go == cinfo->image_height) {
211  for (ci = 0; ci < cinfo->num_components; ci++) {
212  int row;
213  for (row = 1; row <= cinfo->max_v_samp_factor; row++) {
214  jcopy_sample_rows(prep->color_buf[ci], 0,
215  prep->color_buf[ci], -row,
216  1, cinfo->image_width);
217  }
218  }
219  }
220  *in_row_ctr += numrows;
221  prep->next_buf_row += numrows;
222  prep->rows_to_go -= numrows;
223  } else {
224  /* Return for more data, unless we are at the bottom of the image. */
225  if (prep->rows_to_go != 0)
226  break;
227  /* When at bottom of image, pad to fill the conversion buffer. */
228  if (prep->next_buf_row < prep->next_buf_stop) {
229  for (ci = 0; ci < cinfo->num_components; ci++) {
230  expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,
231  prep->next_buf_row, prep->next_buf_stop);
232  }
233  prep->next_buf_row = prep->next_buf_stop;
234  }
235  }
236  /* If we've gotten enough data, downsample a row group. */
237  if (prep->next_buf_row == prep->next_buf_stop) {
238  (*cinfo->downsample->downsample) (cinfo,
239  prep->color_buf,
240  (JDIMENSION) prep->this_row_group,
241  output_buf, *out_row_group_ctr);
242  (*out_row_group_ctr)++;
243  /* Advance pointers with wraparound as necessary. */
244  prep->this_row_group += cinfo->max_v_samp_factor;
245  if (prep->this_row_group >= buf_height)
246  prep->this_row_group = 0;
247  if (prep->next_buf_row >= buf_height)
248  prep->next_buf_row = 0;
249  prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor;
250  }
251  }
252 }
253 
254 
255 /*
256  * Create the wrapped-around downsampling input buffer needed for context mode.
257  */
258 
259 LOCAL(void)
261 {
262  my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
263  int rgroup_height = cinfo->max_v_samp_factor;
264  int ci, i;
266  JSAMPARRAY true_buffer, fake_buffer;
267 
268  /* Grab enough space for fake row pointers for all the components;
269  * we need five row groups' worth of pointers for each component.
270  */
271  fake_buffer = (JSAMPARRAY)
272  (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
273  (cinfo->num_components * 5 * rgroup_height) *
274  SIZEOF(JSAMPROW));
275 
276  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
277  ci++, compptr++) {
278  /* Allocate the actual buffer space (3 row groups) for this component.
279  * We make the buffer wide enough to allow the downsampler to edge-expand
280  * horizontally within the buffer, if it so chooses.
281  */
282  true_buffer = (*cinfo->mem->alloc_sarray)
283  ((j_common_ptr) cinfo, JPOOL_IMAGE,
284  (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE *
285  cinfo->max_h_samp_factor) / compptr->h_samp_factor),
286  (JDIMENSION) (3 * rgroup_height));
287  /* Copy true buffer row pointers into the middle of the fake row array */
288  MEMCOPY(fake_buffer + rgroup_height, true_buffer,
289  3 * rgroup_height * SIZEOF(JSAMPROW));
290  /* Fill in the above and below wraparound pointers */
291  for (i = 0; i < rgroup_height; i++) {
292  fake_buffer[i] = true_buffer[2 * rgroup_height + i];
293  fake_buffer[4 * rgroup_height + i] = true_buffer[i];
294  }
295  prep->color_buf[ci] = fake_buffer + rgroup_height;
296  fake_buffer += 5 * rgroup_height; /* point to space for next component */
297  }
298 }
299 
300 #endif /* CONTEXT_ROWS_SUPPORTED */
301 
302 
303 /*
304  * Initialize preprocessing controller.
305  */
306 
307 GLOBAL(void)
309 {
310  my_prep_ptr prep;
311  int ci;
313 
314  if (need_full_buffer) /* safety check */
315  ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
316 
317  prep = (my_prep_ptr)
318  (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
320  cinfo->prep = (struct jpeg_c_prep_controller *) prep;
321  prep->pub.start_pass = start_pass_prep;
322 
323  /* Allocate the color conversion buffer.
324  * We make the buffer wide enough to allow the downsampler to edge-expand
325  * horizontally within the buffer, if it so chooses.
326  */
327  if (cinfo->downsample->need_context_rows) {
328  /* Set up to provide context rows */
329 #ifdef CONTEXT_ROWS_SUPPORTED
330  prep->pub.pre_process_data = pre_process_context;
331  create_context_buffer(cinfo);
332 #else
333  ERREXIT(cinfo, JERR_NOT_COMPILED);
334 #endif
335  } else {
336  /* No context, just make it tall enough for one row group */
337  prep->pub.pre_process_data = pre_process_data;
338  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
339  ci++, compptr++) {
340  prep->color_buf[ci] = (*cinfo->mem->alloc_sarray)
341  ((j_common_ptr) cinfo, JPOOL_IMAGE,
342  (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE *
343  cinfo->max_h_samp_factor) / compptr->h_samp_factor),
344  (JDIMENSION) cinfo->max_v_samp_factor);
345  }
346  }
347 }
#define DCTSIZE
Definition: mrpt_jpeglib.h:38
JSAMPARRAY color_buf[MAX_COMPONENTS]
Definition: jcprepct.cpp:52
struct jpeg_common_struct * j_common_ptr
Definition: mrpt_jpeglib.h:258
#define MAX_COMPONENTS
Definition: jmorecfg.h:32
#define MIN(a, b)
Definition: jpegint.h:266
#define ERREXIT(cinfo, code)
Definition: jerror.h:199
#define SIZEOF(object)
Definition: jinclude.h:73
boolean need_full_buffer
Definition: jpegint.h:335
JSAMPLE FAR * JSAMPROW
Definition: mrpt_jpeglib.h:63
jpeg_component_info * compptr
Definition: jdct.h:97
JDIMENSION width_in_blocks
Definition: mrpt_jpeglib.h:136
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
JSAMPIMAGE input_buf
Definition: jccoefct.cpp:59
#define MEMCOPY(dest, src, size)
Definition: jinclude.h:61
expand_bottom_edge(JSAMPARRAY image_data, JDIMENSION num_cols, int input_rows, int output_rows)
Definition: jcprepct.cpp:99
struct jpeg_c_prep_controller pub
Definition: jcprepct.cpp:47
#define JPOOL_IMAGE
Definition: mrpt_jpeglib.h:746
#define LOCAL(type)
Definition: jmorecfg.h:183
JSAMPROW * JSAMPARRAY
Definition: mrpt_jpeglib.h:64
jinit_c_prep_controller(j_compress_ptr cinfo, boolean need_full_buffer)
Definition: jcprepct.cpp:308
int JSAMPARRAY int int JDIMENSION num_cols
Definition: jpegint.h:370
create_context_buffer(j_compress_ptr cinfo)
Definition: jcprepct.cpp:260
pre_process_context(j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail, JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, JDIMENSION out_row_groups_avail)
Definition: jcprepct.cpp:188
JSAMPARRAY * JSAMPIMAGE
Definition: mrpt_jpeglib.h:65
pre_process_data(j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail, JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, JDIMENSION out_row_groups_avail)
Definition: jcprepct.cpp:121
JSAMPIMAGE output_buf
Definition: jdcoefct.cpp:59
#define GLOBAL(type)
Definition: jmorecfg.h:185
GLenum GLenum GLvoid * row
Definition: glext.h:3533
#define METHODDEF(type)
Definition: jmorecfg.h:181
my_prep_controller * my_prep_ptr
Definition: jcprepct.cpp:63
start_pass_prep(j_compress_ptr cinfo, J_BUF_MODE pass_mode)
Definition: jcprepct.cpp:71
JSAMPARRAY JDIMENSION JDIMENSION in_rows_avail
Definition: jcmainct.cpp:52
J_BUF_MODE
Definition: jpegint.h:13
unsigned int JDIMENSION
Definition: jmorecfg.h:168
JSAMPARRAY JDIMENSION * in_row_ctr
Definition: jcmainct.cpp:52
JDIMENSION rows_to_go
Definition: jcprepct.cpp:54



Page generated by Doxygen 1.8.14 for MRPT 1.5.6 Git: 4c65e8431 Tue Apr 24 08:18:17 2018 +0200 at lun oct 28 01:35:26 CET 2019