00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 #define JPEG_INTERNALS
00049 #include "jinclude.h"
00050 #include "jpeglib.h"
00051
00052
00053
00054 typedef JMETHOD(void, downsample1_ptr,
00055 (j_compress_ptr cinfo, jpeg_component_info * compptr,
00056 JSAMPARRAY input_data, JSAMPARRAY output_data));
00057
00058
00059
00060 typedef struct {
00061 struct jpeg_downsampler pub;
00062
00063
00064 downsample1_ptr methods[MAX_COMPONENTS];
00065
00066
00067 int rowgroup_height[MAX_COMPONENTS];
00068
00069
00070
00071
00072 UINT8 h_expand[MAX_COMPONENTS];
00073 UINT8 v_expand[MAX_COMPONENTS];
00074 } my_downsampler;
00075
00076 typedef my_downsampler * my_downsample_ptr;
00077
00078
00079
00080
00081
00082
00083 METHODDEF(void)
00084 start_pass_downsample (j_compress_ptr cinfo)
00085 {
00086
00087 }
00088
00089
00090
00091
00092
00093
00094
00095 LOCAL(void)
00096 expand_right_edge (JSAMPARRAY image_data, int num_rows,
00097 JDIMENSION input_cols, JDIMENSION output_cols)
00098 {
00099 register JSAMPROW ptr;
00100 register JSAMPLE pixval;
00101 register int count;
00102 int row;
00103 int numcols = (int) (output_cols - input_cols);
00104
00105 if (numcols > 0) {
00106 for (row = 0; row < num_rows; row++) {
00107 ptr = image_data[row] + input_cols;
00108 pixval = ptr[-1];
00109 for (count = numcols; count > 0; count--)
00110 *ptr++ = pixval;
00111 }
00112 }
00113 }
00114
00115
00116
00117
00118
00119
00120
00121
00122 METHODDEF(void)
00123 sep_downsample (j_compress_ptr cinfo,
00124 JSAMPIMAGE input_buf, JDIMENSION in_row_index,
00125 JSAMPIMAGE output_buf, JDIMENSION out_row_group_index)
00126 {
00127 my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample;
00128 int ci;
00129 jpeg_component_info * compptr;
00130 JSAMPARRAY in_ptr, out_ptr;
00131
00132 for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
00133 ci++, compptr++) {
00134 in_ptr = input_buf[ci] + in_row_index;
00135 out_ptr = output_buf[ci] +
00136 (out_row_group_index * downsample->rowgroup_height[ci]);
00137 (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr);
00138 }
00139 }
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 METHODDEF(void)
00150 int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
00151 JSAMPARRAY input_data, JSAMPARRAY output_data)
00152 {
00153 my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample;
00154 int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v;
00155 JDIMENSION outcol, outcol_h;
00156 JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size;
00157 JSAMPROW inptr, outptr;
00158 INT32 outvalue;
00159
00160 h_expand = downsample->h_expand[compptr->component_index];
00161 v_expand = downsample->v_expand[compptr->component_index];
00162 numpix = h_expand * v_expand;
00163 numpix2 = numpix/2;
00164
00165
00166
00167
00168
00169 expand_right_edge(input_data, cinfo->max_v_samp_factor,
00170 cinfo->image_width, output_cols * h_expand);
00171
00172 inrow = outrow = 0;
00173 while (inrow < cinfo->max_v_samp_factor) {
00174 outptr = output_data[outrow];
00175 for (outcol = 0, outcol_h = 0; outcol < output_cols;
00176 outcol++, outcol_h += h_expand) {
00177 outvalue = 0;
00178 for (v = 0; v < v_expand; v++) {
00179 inptr = input_data[inrow+v] + outcol_h;
00180 for (h = 0; h < h_expand; h++) {
00181 outvalue += (INT32) GETJSAMPLE(*inptr++);
00182 }
00183 }
00184 *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix);
00185 }
00186 inrow += v_expand;
00187 outrow++;
00188 }
00189 }
00190
00191
00192
00193
00194
00195
00196
00197
00198 METHODDEF(void)
00199 fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
00200 JSAMPARRAY input_data, JSAMPARRAY output_data)
00201 {
00202
00203 jcopy_sample_rows(input_data, 0, output_data, 0,
00204 cinfo->max_v_samp_factor, cinfo->image_width);
00205
00206 expand_right_edge(output_data, cinfo->max_v_samp_factor, cinfo->image_width,
00207 compptr->width_in_blocks * compptr->DCT_h_scaled_size);
00208 }
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 METHODDEF(void)
00224 h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
00225 JSAMPARRAY input_data, JSAMPARRAY output_data)
00226 {
00227 int inrow;
00228 JDIMENSION outcol;
00229 JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size;
00230 register JSAMPROW inptr, outptr;
00231 register int bias;
00232
00233
00234
00235
00236
00237 expand_right_edge(input_data, cinfo->max_v_samp_factor,
00238 cinfo->image_width, output_cols * 2);
00239
00240 for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) {
00241 outptr = output_data[inrow];
00242 inptr = input_data[inrow];
00243 bias = 0;
00244 for (outcol = 0; outcol < output_cols; outcol++) {
00245 *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1])
00246 + bias) >> 1);
00247 bias ^= 1;
00248 inptr += 2;
00249 }
00250 }
00251 }
00252
00253
00254
00255
00256
00257
00258
00259
00260 METHODDEF(void)
00261 h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
00262 JSAMPARRAY input_data, JSAMPARRAY output_data)
00263 {
00264 int inrow, outrow;
00265 JDIMENSION outcol;
00266 JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size;
00267 register JSAMPROW inptr0, inptr1, outptr;
00268 register int bias;
00269
00270
00271
00272
00273
00274 expand_right_edge(input_data, cinfo->max_v_samp_factor,
00275 cinfo->image_width, output_cols * 2);
00276
00277 inrow = outrow = 0;
00278 while (inrow < cinfo->max_v_samp_factor) {
00279 outptr = output_data[outrow];
00280 inptr0 = input_data[inrow];
00281 inptr1 = input_data[inrow+1];
00282 bias = 1;
00283 for (outcol = 0; outcol < output_cols; outcol++) {
00284 *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
00285 GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1])
00286 + bias) >> 2);
00287 bias ^= 3;
00288 inptr0 += 2; inptr1 += 2;
00289 }
00290 inrow += 2;
00291 outrow++;
00292 }
00293 }
00294
00295
00296 #ifdef INPUT_SMOOTHING_SUPPORTED
00297
00298
00299
00300
00301
00302
00303
00304 METHODDEF(void)
00305 h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
00306 JSAMPARRAY input_data, JSAMPARRAY output_data)
00307 {
00308 int inrow, outrow;
00309 JDIMENSION colctr;
00310 JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size;
00311 register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr;
00312 INT32 membersum, neighsum, memberscale, neighscale;
00313
00314
00315
00316
00317
00318 expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
00319 cinfo->image_width, output_cols * 2);
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 memberscale = 16384 - cinfo->smoothing_factor * 80;
00335 neighscale = cinfo->smoothing_factor * 16;
00336
00337 inrow = outrow = 0;
00338 while (inrow < cinfo->max_v_samp_factor) {
00339 outptr = output_data[outrow];
00340 inptr0 = input_data[inrow];
00341 inptr1 = input_data[inrow+1];
00342 above_ptr = input_data[inrow-1];
00343 below_ptr = input_data[inrow+2];
00344
00345
00346 membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
00347 GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
00348 neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
00349 GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
00350 GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) +
00351 GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]);
00352 neighsum += neighsum;
00353 neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) +
00354 GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]);
00355 membersum = membersum * memberscale + neighsum * neighscale;
00356 *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
00357 inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
00358
00359 for (colctr = output_cols - 2; colctr > 0; colctr--) {
00360
00361 membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
00362 GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
00363
00364 neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
00365 GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
00366 GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) +
00367 GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]);
00368
00369 neighsum += neighsum;
00370
00371 neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) +
00372 GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]);
00373
00374 membersum = membersum * memberscale + neighsum * neighscale;
00375
00376 *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
00377 inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
00378 }
00379
00380
00381 membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
00382 GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
00383 neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
00384 GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
00385 GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) +
00386 GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]);
00387 neighsum += neighsum;
00388 neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) +
00389 GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]);
00390 membersum = membersum * memberscale + neighsum * neighscale;
00391 *outptr = (JSAMPLE) ((membersum + 32768) >> 16);
00392
00393 inrow += 2;
00394 outrow++;
00395 }
00396 }
00397
00398
00399
00400
00401
00402
00403
00404
00405 METHODDEF(void)
00406 fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
00407 JSAMPARRAY input_data, JSAMPARRAY output_data)
00408 {
00409 int inrow;
00410 JDIMENSION colctr;
00411 JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size;
00412 register JSAMPROW inptr, above_ptr, below_ptr, outptr;
00413 INT32 membersum, neighsum, memberscale, neighscale;
00414 int colsum, lastcolsum, nextcolsum;
00415
00416
00417
00418
00419
00420 expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
00421 cinfo->image_width, output_cols);
00422
00423
00424
00425
00426
00427
00428
00429 memberscale = 65536L - cinfo->smoothing_factor * 512L;
00430 neighscale = cinfo->smoothing_factor * 64;
00431
00432 for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) {
00433 outptr = output_data[inrow];
00434 inptr = input_data[inrow];
00435 above_ptr = input_data[inrow-1];
00436 below_ptr = input_data[inrow+1];
00437
00438
00439 colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) +
00440 GETJSAMPLE(*inptr);
00441 membersum = GETJSAMPLE(*inptr++);
00442 nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
00443 GETJSAMPLE(*inptr);
00444 neighsum = colsum + (colsum - membersum) + nextcolsum;
00445 membersum = membersum * memberscale + neighsum * neighscale;
00446 *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
00447 lastcolsum = colsum; colsum = nextcolsum;
00448
00449 for (colctr = output_cols - 2; colctr > 0; colctr--) {
00450 membersum = GETJSAMPLE(*inptr++);
00451 above_ptr++; below_ptr++;
00452 nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
00453 GETJSAMPLE(*inptr);
00454 neighsum = lastcolsum + (colsum - membersum) + nextcolsum;
00455 membersum = membersum * memberscale + neighsum * neighscale;
00456 *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
00457 lastcolsum = colsum; colsum = nextcolsum;
00458 }
00459
00460
00461 membersum = GETJSAMPLE(*inptr);
00462 neighsum = lastcolsum + (colsum - membersum) + colsum;
00463 membersum = membersum * memberscale + neighsum * neighscale;
00464 *outptr = (JSAMPLE) ((membersum + 32768) >> 16);
00465
00466 }
00467 }
00468
00469 #endif
00470
00471
00472
00473
00474
00475
00476
00477 GLOBAL(void)
00478 jinit_downsampler (j_compress_ptr cinfo)
00479 {
00480 my_downsample_ptr downsample;
00481 int ci;
00482 jpeg_component_info * compptr;
00483 boolean smoothok = TRUE;
00484 int h_in_group, v_in_group, h_out_group, v_out_group;
00485
00486 downsample = (my_downsample_ptr)
00487 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00488 SIZEOF(my_downsampler));
00489 cinfo->downsample = (struct jpeg_downsampler *) downsample;
00490 downsample->pub.start_pass = start_pass_downsample;
00491 downsample->pub.downsample = sep_downsample;
00492 downsample->pub.need_context_rows = FALSE;
00493
00494 if (cinfo->CCIR601_sampling)
00495 ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
00496
00497
00498 for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
00499 ci++, compptr++) {
00500
00501
00502
00503 h_out_group = (compptr->h_samp_factor * compptr->DCT_h_scaled_size) /
00504 cinfo->min_DCT_h_scaled_size;
00505 v_out_group = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) /
00506 cinfo->min_DCT_v_scaled_size;
00507 h_in_group = cinfo->max_h_samp_factor;
00508 v_in_group = cinfo->max_v_samp_factor;
00509 downsample->rowgroup_height[ci] = v_out_group;
00510 if (h_in_group == h_out_group && v_in_group == v_out_group) {
00511 #ifdef INPUT_SMOOTHING_SUPPORTED
00512 if (cinfo->smoothing_factor) {
00513 downsample->methods[ci] = fullsize_smooth_downsample;
00514 downsample->pub.need_context_rows = TRUE;
00515 } else
00516 #endif
00517 downsample->methods[ci] = fullsize_downsample;
00518 } else if (h_in_group == h_out_group * 2 &&
00519 v_in_group == v_out_group) {
00520 smoothok = FALSE;
00521 downsample->methods[ci] = h2v1_downsample;
00522 } else if (h_in_group == h_out_group * 2 &&
00523 v_in_group == v_out_group * 2) {
00524 #ifdef INPUT_SMOOTHING_SUPPORTED
00525 if (cinfo->smoothing_factor) {
00526 downsample->methods[ci] = h2v2_smooth_downsample;
00527 downsample->pub.need_context_rows = TRUE;
00528 } else
00529 #endif
00530 downsample->methods[ci] = h2v2_downsample;
00531 } else if ((h_in_group % h_out_group) == 0 &&
00532 (v_in_group % v_out_group) == 0) {
00533 smoothok = FALSE;
00534 downsample->methods[ci] = int_downsample;
00535 downsample->h_expand[ci] = (UINT8) (h_in_group / h_out_group);
00536 downsample->v_expand[ci] = (UINT8) (v_in_group / v_out_group);
00537 } else
00538 ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
00539 }
00540
00541 #ifdef INPUT_SMOOTHING_SUPPORTED
00542 if (cinfo->smoothing_factor && !smoothok)
00543 TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL);
00544 #endif
00545 }