60 typedef struct { |
60 typedef struct { |
61 struct jpeg_downsampler pub; /* public fields */ |
61 struct jpeg_downsampler pub; /* public fields */ |
62 |
62 |
63 /* Downsampling method pointers, one per component */ |
63 /* Downsampling method pointers, one per component */ |
64 downsample1_ptr methods[MAX_COMPONENTS]; |
64 downsample1_ptr methods[MAX_COMPONENTS]; |
|
65 |
|
66 /* Height of an output row group for each component. */ |
|
67 int rowgroup_height[MAX_COMPONENTS]; |
|
68 |
|
69 /* These arrays save pixel expansion factors so that int_downsample need not |
|
70 * recompute them each time. They are unused for other downsampling methods. |
|
71 */ |
|
72 UINT8 h_expand[MAX_COMPONENTS]; |
|
73 UINT8 v_expand[MAX_COMPONENTS]; |
65 } my_downsampler; |
74 } my_downsampler; |
66 |
75 |
67 typedef my_downsampler * my_downsample_ptr; |
76 typedef my_downsampler * my_downsample_ptr; |
68 |
77 |
69 |
78 |
121 JSAMPARRAY in_ptr, out_ptr; |
130 JSAMPARRAY in_ptr, out_ptr; |
122 |
131 |
123 for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; |
132 for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; |
124 ci++, compptr++) { |
133 ci++, compptr++) { |
125 in_ptr = input_buf[ci] + in_row_index; |
134 in_ptr = input_buf[ci] + in_row_index; |
126 out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor); |
135 out_ptr = output_buf[ci] + |
|
136 (out_row_group_index * downsample->rowgroup_height[ci]); |
127 (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr); |
137 (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr); |
128 } |
138 } |
129 } |
139 } |
130 |
140 |
131 |
141 |
138 |
148 |
139 METHODDEF(void) |
149 METHODDEF(void) |
140 int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, |
150 int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, |
141 JSAMPARRAY input_data, JSAMPARRAY output_data) |
151 JSAMPARRAY input_data, JSAMPARRAY output_data) |
142 { |
152 { |
|
153 my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample; |
143 int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v; |
154 int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v; |
144 JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */ |
155 JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */ |
145 JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; |
156 JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; |
146 JSAMPROW inptr, outptr; |
157 JSAMPROW inptr, outptr; |
147 INT32 outvalue; |
158 INT32 outvalue; |
148 |
159 |
149 h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor; |
160 h_expand = downsample->h_expand[compptr->component_index]; |
150 v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor; |
161 v_expand = downsample->v_expand[compptr->component_index]; |
151 numpix = h_expand * v_expand; |
162 numpix = h_expand * v_expand; |
152 numpix2 = numpix/2; |
163 numpix2 = numpix/2; |
153 |
164 |
154 /* Expand input data enough to let all the output samples be generated |
165 /* Expand input data enough to let all the output samples be generated |
155 * by the standard loop. Special-casing padded output would be more |
166 * by the standard loop. Special-casing padded output would be more |
156 * efficient. |
167 * efficient. |
157 */ |
168 */ |
158 expand_right_edge(input_data, cinfo->max_v_samp_factor, |
169 expand_right_edge(input_data, cinfo->max_v_samp_factor, |
159 cinfo->image_width, output_cols * h_expand); |
170 cinfo->image_width, output_cols * h_expand); |
160 |
171 |
161 inrow = 0; |
172 inrow = outrow = 0; |
162 for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { |
173 while (inrow < cinfo->max_v_samp_factor) { |
163 outptr = output_data[outrow]; |
174 outptr = output_data[outrow]; |
164 for (outcol = 0, outcol_h = 0; outcol < output_cols; |
175 for (outcol = 0, outcol_h = 0; outcol < output_cols; |
165 outcol++, outcol_h += h_expand) { |
176 outcol++, outcol_h += h_expand) { |
166 outvalue = 0; |
177 outvalue = 0; |
167 for (v = 0; v < v_expand; v++) { |
178 for (v = 0; v < v_expand; v++) { |
189 { |
201 { |
190 /* Copy the data */ |
202 /* Copy the data */ |
191 jcopy_sample_rows(input_data, 0, output_data, 0, |
203 jcopy_sample_rows(input_data, 0, output_data, 0, |
192 cinfo->max_v_samp_factor, cinfo->image_width); |
204 cinfo->max_v_samp_factor, cinfo->image_width); |
193 /* Edge-expand */ |
205 /* Edge-expand */ |
194 expand_right_edge(output_data, cinfo->max_v_samp_factor, |
206 expand_right_edge(output_data, cinfo->max_v_samp_factor, cinfo->image_width, |
195 cinfo->image_width, compptr->width_in_blocks * DCTSIZE); |
207 compptr->width_in_blocks * compptr->DCT_h_scaled_size); |
196 } |
208 } |
197 |
209 |
198 |
210 |
199 /* |
211 /* |
200 * Downsample pixel values of a single component. |
212 * Downsample pixel values of a single component. |
210 |
222 |
211 METHODDEF(void) |
223 METHODDEF(void) |
212 h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, |
224 h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, |
213 JSAMPARRAY input_data, JSAMPARRAY output_data) |
225 JSAMPARRAY input_data, JSAMPARRAY output_data) |
214 { |
226 { |
215 int outrow; |
227 int inrow; |
216 JDIMENSION outcol; |
228 JDIMENSION outcol; |
217 JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; |
229 JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; |
218 register JSAMPROW inptr, outptr; |
230 register JSAMPROW inptr, outptr; |
219 register int bias; |
231 register int bias; |
220 |
232 |
221 /* Expand input data enough to let all the output samples be generated |
233 /* Expand input data enough to let all the output samples be generated |
222 * by the standard loop. Special-casing padded output would be more |
234 * by the standard loop. Special-casing padded output would be more |
223 * efficient. |
235 * efficient. |
224 */ |
236 */ |
225 expand_right_edge(input_data, cinfo->max_v_samp_factor, |
237 expand_right_edge(input_data, cinfo->max_v_samp_factor, |
226 cinfo->image_width, output_cols * 2); |
238 cinfo->image_width, output_cols * 2); |
227 |
239 |
228 for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { |
240 for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { |
229 outptr = output_data[outrow]; |
241 outptr = output_data[inrow]; |
230 inptr = input_data[outrow]; |
242 inptr = input_data[inrow]; |
231 bias = 0; /* bias = 0,1,0,1,... for successive samples */ |
243 bias = 0; /* bias = 0,1,0,1,... for successive samples */ |
232 for (outcol = 0; outcol < output_cols; outcol++) { |
244 for (outcol = 0; outcol < output_cols; outcol++) { |
233 *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) |
245 *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) |
234 + bias) >> 1); |
246 + bias) >> 1); |
235 bias ^= 1; /* 0=>1, 1=>0 */ |
247 bias ^= 1; /* 0=>1, 1=>0 */ |
249 h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, |
261 h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, |
250 JSAMPARRAY input_data, JSAMPARRAY output_data) |
262 JSAMPARRAY input_data, JSAMPARRAY output_data) |
251 { |
263 { |
252 int inrow, outrow; |
264 int inrow, outrow; |
253 JDIMENSION outcol; |
265 JDIMENSION outcol; |
254 JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; |
266 JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; |
255 register JSAMPROW inptr0, inptr1, outptr; |
267 register JSAMPROW inptr0, inptr1, outptr; |
256 register int bias; |
268 register int bias; |
257 |
269 |
258 /* Expand input data enough to let all the output samples be generated |
270 /* Expand input data enough to let all the output samples be generated |
259 * by the standard loop. Special-casing padded output would be more |
271 * by the standard loop. Special-casing padded output would be more |
260 * efficient. |
272 * efficient. |
261 */ |
273 */ |
262 expand_right_edge(input_data, cinfo->max_v_samp_factor, |
274 expand_right_edge(input_data, cinfo->max_v_samp_factor, |
263 cinfo->image_width, output_cols * 2); |
275 cinfo->image_width, output_cols * 2); |
264 |
276 |
265 inrow = 0; |
277 inrow = outrow = 0; |
266 for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { |
278 while (inrow < cinfo->max_v_samp_factor) { |
267 outptr = output_data[outrow]; |
279 outptr = output_data[outrow]; |
268 inptr0 = input_data[inrow]; |
280 inptr0 = input_data[inrow]; |
269 inptr1 = input_data[inrow+1]; |
281 inptr1 = input_data[inrow+1]; |
270 bias = 1; /* bias = 1,2,1,2,... for successive samples */ |
282 bias = 1; /* bias = 1,2,1,2,... for successive samples */ |
271 for (outcol = 0; outcol < output_cols; outcol++) { |
283 for (outcol = 0; outcol < output_cols; outcol++) { |
292 h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, |
305 h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, |
293 JSAMPARRAY input_data, JSAMPARRAY output_data) |
306 JSAMPARRAY input_data, JSAMPARRAY output_data) |
294 { |
307 { |
295 int inrow, outrow; |
308 int inrow, outrow; |
296 JDIMENSION colctr; |
309 JDIMENSION colctr; |
297 JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; |
310 JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; |
298 register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; |
311 register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; |
299 INT32 membersum, neighsum, memberscale, neighscale; |
312 INT32 membersum, neighsum, memberscale, neighscale; |
300 |
313 |
301 /* Expand input data enough to let all the output samples be generated |
314 /* Expand input data enough to let all the output samples be generated |
302 * by the standard loop. Special-casing padded output would be more |
315 * by the standard loop. Special-casing padded output would be more |
319 */ |
332 */ |
320 |
333 |
321 memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */ |
334 memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */ |
322 neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */ |
335 neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */ |
323 |
336 |
324 inrow = 0; |
337 inrow = outrow = 0; |
325 for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { |
338 while (inrow < cinfo->max_v_samp_factor) { |
326 outptr = output_data[outrow]; |
339 outptr = output_data[outrow]; |
327 inptr0 = input_data[inrow]; |
340 inptr0 = input_data[inrow]; |
328 inptr1 = input_data[inrow+1]; |
341 inptr1 = input_data[inrow+1]; |
329 above_ptr = input_data[inrow-1]; |
342 above_ptr = input_data[inrow-1]; |
330 below_ptr = input_data[inrow+2]; |
343 below_ptr = input_data[inrow+2]; |
390 |
404 |
391 METHODDEF(void) |
405 METHODDEF(void) |
392 fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, |
406 fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, |
393 JSAMPARRAY input_data, JSAMPARRAY output_data) |
407 JSAMPARRAY input_data, JSAMPARRAY output_data) |
394 { |
408 { |
395 int outrow; |
409 int inrow; |
396 JDIMENSION colctr; |
410 JDIMENSION colctr; |
397 JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; |
411 JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size; |
398 register JSAMPROW inptr, above_ptr, below_ptr, outptr; |
412 register JSAMPROW inptr, above_ptr, below_ptr, outptr; |
399 INT32 membersum, neighsum, memberscale, neighscale; |
413 INT32 membersum, neighsum, memberscale, neighscale; |
400 int colsum, lastcolsum, nextcolsum; |
414 int colsum, lastcolsum, nextcolsum; |
401 |
415 |
402 /* Expand input data enough to let all the output samples be generated |
416 /* Expand input data enough to let all the output samples be generated |
413 */ |
427 */ |
414 |
428 |
415 memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */ |
429 memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */ |
416 neighscale = cinfo->smoothing_factor * 64; /* scaled SF */ |
430 neighscale = cinfo->smoothing_factor * 64; /* scaled SF */ |
417 |
431 |
418 for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { |
432 for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { |
419 outptr = output_data[outrow]; |
433 outptr = output_data[inrow]; |
420 inptr = input_data[outrow]; |
434 inptr = input_data[inrow]; |
421 above_ptr = input_data[outrow-1]; |
435 above_ptr = input_data[inrow-1]; |
422 below_ptr = input_data[outrow+1]; |
436 below_ptr = input_data[inrow+1]; |
423 |
437 |
424 /* Special case for first column */ |
438 /* Special case for first column */ |
425 colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) + |
439 colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) + |
426 GETJSAMPLE(*inptr); |
440 GETJSAMPLE(*inptr); |
427 membersum = GETJSAMPLE(*inptr++); |
441 membersum = GETJSAMPLE(*inptr++); |
465 { |
479 { |
466 my_downsample_ptr downsample; |
480 my_downsample_ptr downsample; |
467 int ci; |
481 int ci; |
468 jpeg_component_info * compptr; |
482 jpeg_component_info * compptr; |
469 boolean smoothok = TRUE; |
483 boolean smoothok = TRUE; |
|
484 int h_in_group, v_in_group, h_out_group, v_out_group; |
470 |
485 |
471 downsample = (my_downsample_ptr) |
486 downsample = (my_downsample_ptr) |
472 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, |
487 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, |
473 SIZEOF(my_downsampler)); |
488 SIZEOF(my_downsampler)); |
474 cinfo->downsample = (struct jpeg_downsampler *) downsample; |
489 cinfo->downsample = (struct jpeg_downsampler *) downsample; |
480 ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); |
495 ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); |
481 |
496 |
482 /* Verify we can handle the sampling factors, and set up method pointers */ |
497 /* Verify we can handle the sampling factors, and set up method pointers */ |
483 for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; |
498 for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; |
484 ci++, compptr++) { |
499 ci++, compptr++) { |
485 if (compptr->h_samp_factor == cinfo->max_h_samp_factor && |
500 /* Compute size of an "output group" for DCT scaling. This many samples |
486 compptr->v_samp_factor == cinfo->max_v_samp_factor) { |
501 * are to be converted from max_h_samp_factor * max_v_samp_factor pixels. |
|
502 */ |
|
503 h_out_group = (compptr->h_samp_factor * compptr->DCT_h_scaled_size) / |
|
504 cinfo->min_DCT_h_scaled_size; |
|
505 v_out_group = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) / |
|
506 cinfo->min_DCT_v_scaled_size; |
|
507 h_in_group = cinfo->max_h_samp_factor; |
|
508 v_in_group = cinfo->max_v_samp_factor; |
|
509 downsample->rowgroup_height[ci] = v_out_group; /* save for use later */ |
|
510 if (h_in_group == h_out_group && v_in_group == v_out_group) { |
487 #ifdef INPUT_SMOOTHING_SUPPORTED |
511 #ifdef INPUT_SMOOTHING_SUPPORTED |
488 if (cinfo->smoothing_factor) { |
512 if (cinfo->smoothing_factor) { |
489 downsample->methods[ci] = fullsize_smooth_downsample; |
513 downsample->methods[ci] = fullsize_smooth_downsample; |
490 downsample->pub.need_context_rows = TRUE; |
514 downsample->pub.need_context_rows = TRUE; |
491 } else |
515 } else |
492 #endif |
516 #endif |
493 downsample->methods[ci] = fullsize_downsample; |
517 downsample->methods[ci] = fullsize_downsample; |
494 } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && |
518 } else if (h_in_group == h_out_group * 2 && |
495 compptr->v_samp_factor == cinfo->max_v_samp_factor) { |
519 v_in_group == v_out_group) { |
496 smoothok = FALSE; |
520 smoothok = FALSE; |
497 downsample->methods[ci] = h2v1_downsample; |
521 downsample->methods[ci] = h2v1_downsample; |
498 } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && |
522 } else if (h_in_group == h_out_group * 2 && |
499 compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) { |
523 v_in_group == v_out_group * 2) { |
500 #ifdef INPUT_SMOOTHING_SUPPORTED |
524 #ifdef INPUT_SMOOTHING_SUPPORTED |
501 if (cinfo->smoothing_factor) { |
525 if (cinfo->smoothing_factor) { |
502 downsample->methods[ci] = h2v2_smooth_downsample; |
526 downsample->methods[ci] = h2v2_smooth_downsample; |
503 downsample->pub.need_context_rows = TRUE; |
527 downsample->pub.need_context_rows = TRUE; |
504 } else |
528 } else |
505 #endif |
529 #endif |
506 downsample->methods[ci] = h2v2_downsample; |
530 downsample->methods[ci] = h2v2_downsample; |
507 } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 && |
531 } else if ((h_in_group % h_out_group) == 0 && |
508 (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) { |
532 (v_in_group % v_out_group) == 0) { |
509 smoothok = FALSE; |
533 smoothok = FALSE; |
510 downsample->methods[ci] = int_downsample; |
534 downsample->methods[ci] = int_downsample; |
|
535 downsample->h_expand[ci] = (UINT8) (h_in_group / h_out_group); |
|
536 downsample->v_expand[ci] = (UINT8) (v_in_group / v_out_group); |
511 } else |
537 } else |
512 ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); |
538 ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); |
513 } |
539 } |
514 |
540 |
515 #ifdef INPUT_SMOOTHING_SUPPORTED |
541 #ifdef INPUT_SMOOTHING_SUPPORTED |