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