jdsample.c (18583B)
1 /* 2 * jdsample.c 3 * 4 * This file was part of the Independent JPEG Group's software: 5 * Copyright (C) 1991-1996, Thomas G. Lane. 6 * libjpeg-turbo Modifications: 7 * Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB 8 * Copyright (C) 2010, 2015-2016, 2022, D. R. Commander. 9 * Copyright (C) 2014, MIPS Technologies, Inc., California. 10 * Copyright (C) 2015, Google, Inc. 11 * Copyright (C) 2019-2020, Arm Limited. 12 * For conditions of distribution and use, see the accompanying README.ijg 13 * file. 14 * 15 * This file contains upsampling routines. 16 * 17 * Upsampling input data is counted in "row groups". A row group 18 * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) 19 * sample rows of each component. Upsampling will normally produce 20 * max_v_samp_factor pixel rows from each row group (but this could vary 21 * if the upsampler is applying a scale factor of its own). 22 * 23 * An excellent reference for image resampling is 24 * Digital Image Warping, George Wolberg, 1990. 25 * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. 26 */ 27 28 #include "jinclude.h" 29 #include "jdsample.h" 30 #include "jsimd.h" 31 #include "jpegapicomp.h" 32 33 34 35 #if BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) 36 37 /* 38 * Initialize for an upsampling pass. 39 */ 40 41 METHODDEF(void) 42 start_pass_upsample(j_decompress_ptr cinfo) 43 { 44 my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample; 45 46 /* Mark the conversion buffer empty */ 47 upsample->next_row_out = cinfo->max_v_samp_factor; 48 /* Initialize total-height counter for detecting bottom of image */ 49 upsample->rows_to_go = cinfo->output_height; 50 } 51 52 53 /* 54 * Control routine to do upsampling (and color conversion). 55 * 56 * In this version we upsample each component independently. 57 * We upsample one row group into the conversion buffer, then apply 58 * color conversion a row at a time. 59 */ 60 61 METHODDEF(void) 62 sep_upsample(j_decompress_ptr cinfo, _JSAMPIMAGE input_buf, 63 JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, 64 _JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, 65 JDIMENSION out_rows_avail) 66 { 67 my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample; 68 int ci; 69 jpeg_component_info *compptr; 70 JDIMENSION num_rows; 71 72 /* Fill the conversion buffer, if it's empty */ 73 if (upsample->next_row_out >= cinfo->max_v_samp_factor) { 74 for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; 75 ci++, compptr++) { 76 /* Invoke per-component upsample method. Notice we pass a POINTER 77 * to color_buf[ci], so that fullsize_upsample can change it. 78 */ 79 (*upsample->methods[ci]) (cinfo, compptr, 80 input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]), 81 upsample->color_buf + ci); 82 } 83 upsample->next_row_out = 0; 84 } 85 86 /* Color-convert and emit rows */ 87 88 /* How many we have in the buffer: */ 89 num_rows = (JDIMENSION)(cinfo->max_v_samp_factor - upsample->next_row_out); 90 /* Not more than the distance to the end of the image. Need this test 91 * in case the image height is not a multiple of max_v_samp_factor: 92 */ 93 if (num_rows > upsample->rows_to_go) 94 num_rows = upsample->rows_to_go; 95 /* And not more than what the client can accept: */ 96 out_rows_avail -= *out_row_ctr; 97 if (num_rows > out_rows_avail) 98 num_rows = out_rows_avail; 99 100 (*cinfo->cconvert->_color_convert) (cinfo, upsample->color_buf, 101 (JDIMENSION)upsample->next_row_out, 102 output_buf + *out_row_ctr, 103 (int)num_rows); 104 105 /* Adjust counts */ 106 *out_row_ctr += num_rows; 107 upsample->rows_to_go -= num_rows; 108 upsample->next_row_out += num_rows; 109 /* When the buffer is emptied, declare this input row group consumed */ 110 if (upsample->next_row_out >= cinfo->max_v_samp_factor) 111 (*in_row_group_ctr)++; 112 } 113 114 115 /* 116 * These are the routines invoked by sep_upsample to upsample pixel values 117 * of a single component. One row group is processed per call. 118 */ 119 120 121 /* 122 * For full-size components, we just make color_buf[ci] point at the 123 * input buffer, and thus avoid copying any data. Note that this is 124 * safe only because sep_upsample doesn't declare the input row group 125 * "consumed" until we are done color converting and emitting it. 126 */ 127 128 METHODDEF(void) 129 fullsize_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, 130 _JSAMPARRAY input_data, _JSAMPARRAY *output_data_ptr) 131 { 132 *output_data_ptr = input_data; 133 } 134 135 136 /* 137 * This is a no-op version used for "uninteresting" components. 138 * These components will not be referenced by color conversion. 139 */ 140 141 METHODDEF(void) 142 noop_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, 143 _JSAMPARRAY input_data, _JSAMPARRAY *output_data_ptr) 144 { 145 *output_data_ptr = NULL; /* safety check */ 146 } 147 148 149 /* 150 * This version handles any integral sampling ratios. 151 * This is not used for typical JPEG files, so it need not be fast. 152 * Nor, for that matter, is it particularly accurate: the algorithm is 153 * simple replication of the input pixel onto the corresponding output 154 * pixels. The hi-falutin sampling literature refers to this as a 155 * "box filter". A box filter tends to introduce visible artifacts, 156 * so if you are actually going to use 3:1 or 4:1 sampling ratios 157 * you would be well advised to improve this code. 158 */ 159 160 METHODDEF(void) 161 int_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, 162 _JSAMPARRAY input_data, _JSAMPARRAY *output_data_ptr) 163 { 164 my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample; 165 _JSAMPARRAY output_data = *output_data_ptr; 166 register _JSAMPROW inptr, outptr; 167 register _JSAMPLE invalue; 168 register int h; 169 _JSAMPROW outend; 170 int h_expand, v_expand; 171 int inrow, outrow; 172 173 h_expand = upsample->h_expand[compptr->component_index]; 174 v_expand = upsample->v_expand[compptr->component_index]; 175 176 inrow = outrow = 0; 177 while (outrow < cinfo->max_v_samp_factor) { 178 /* Generate one output row with proper horizontal expansion */ 179 inptr = input_data[inrow]; 180 outptr = output_data[outrow]; 181 outend = outptr + cinfo->output_width; 182 while (outptr < outend) { 183 invalue = *inptr++; 184 for (h = h_expand; h > 0; h--) { 185 *outptr++ = invalue; 186 } 187 } 188 /* Generate any additional output rows by duplicating the first one */ 189 if (v_expand > 1) { 190 _jcopy_sample_rows(output_data, outrow, output_data, outrow + 1, 191 v_expand - 1, cinfo->output_width); 192 } 193 inrow++; 194 outrow += v_expand; 195 } 196 } 197 198 199 /* 200 * Fast processing for the common case of 2:1 horizontal and 1:1 vertical. 201 * It's still a box filter. 202 */ 203 204 METHODDEF(void) 205 h2v1_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, 206 _JSAMPARRAY input_data, _JSAMPARRAY *output_data_ptr) 207 { 208 _JSAMPARRAY output_data = *output_data_ptr; 209 register _JSAMPROW inptr, outptr; 210 register _JSAMPLE invalue; 211 _JSAMPROW outend; 212 int inrow; 213 214 for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { 215 inptr = input_data[inrow]; 216 outptr = output_data[inrow]; 217 outend = outptr + cinfo->output_width; 218 while (outptr < outend) { 219 invalue = *inptr++; 220 *outptr++ = invalue; 221 *outptr++ = invalue; 222 } 223 } 224 } 225 226 227 /* 228 * Fast processing for the common case of 2:1 horizontal and 2:1 vertical. 229 * It's still a box filter. 230 */ 231 232 METHODDEF(void) 233 h2v2_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, 234 _JSAMPARRAY input_data, _JSAMPARRAY *output_data_ptr) 235 { 236 _JSAMPARRAY output_data = *output_data_ptr; 237 register _JSAMPROW inptr, outptr; 238 register _JSAMPLE invalue; 239 _JSAMPROW outend; 240 int inrow, outrow; 241 242 inrow = outrow = 0; 243 while (outrow < cinfo->max_v_samp_factor) { 244 inptr = input_data[inrow]; 245 outptr = output_data[outrow]; 246 outend = outptr + cinfo->output_width; 247 while (outptr < outend) { 248 invalue = *inptr++; 249 *outptr++ = invalue; 250 *outptr++ = invalue; 251 } 252 _jcopy_sample_rows(output_data, outrow, output_data, outrow + 1, 1, 253 cinfo->output_width); 254 inrow++; 255 outrow += 2; 256 } 257 } 258 259 260 /* 261 * Fancy processing for the common case of 2:1 horizontal and 1:1 vertical. 262 * 263 * The upsampling algorithm is linear interpolation between pixel centers, 264 * also known as a "triangle filter". This is a good compromise between 265 * speed and visual quality. The centers of the output pixels are 1/4 and 3/4 266 * of the way between input pixel centers. 267 * 268 * A note about the "bias" calculations: when rounding fractional values to 269 * integer, we do not want to always round 0.5 up to the next integer. 270 * If we did that, we'd introduce a noticeable bias towards larger values. 271 * Instead, this code is arranged so that 0.5 will be rounded up or down at 272 * alternate pixel locations (a simple ordered dither pattern). 273 */ 274 275 METHODDEF(void) 276 h2v1_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, 277 _JSAMPARRAY input_data, _JSAMPARRAY *output_data_ptr) 278 { 279 _JSAMPARRAY output_data = *output_data_ptr; 280 register _JSAMPROW inptr, outptr; 281 register int invalue; 282 register JDIMENSION colctr; 283 int inrow; 284 285 for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { 286 inptr = input_data[inrow]; 287 outptr = output_data[inrow]; 288 /* Special case for first column */ 289 invalue = *inptr++; 290 *outptr++ = (_JSAMPLE)invalue; 291 *outptr++ = (_JSAMPLE)((invalue * 3 + inptr[0] + 2) >> 2); 292 293 for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { 294 /* General case: 3/4 * nearer pixel + 1/4 * further pixel */ 295 invalue = (*inptr++) * 3; 296 *outptr++ = (_JSAMPLE)((invalue + inptr[-2] + 1) >> 2); 297 *outptr++ = (_JSAMPLE)((invalue + inptr[0] + 2) >> 2); 298 } 299 300 /* Special case for last column */ 301 invalue = *inptr; 302 *outptr++ = (_JSAMPLE)((invalue * 3 + inptr[-1] + 1) >> 2); 303 *outptr++ = (_JSAMPLE)invalue; 304 } 305 } 306 307 308 /* 309 * Fancy processing for 1:1 horizontal and 2:1 vertical (4:4:0 subsampling). 310 * 311 * This is a less common case, but it can be encountered when losslessly 312 * rotating/transposing a JPEG file that uses 4:2:2 chroma subsampling. 313 */ 314 315 METHODDEF(void) 316 h1v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, 317 _JSAMPARRAY input_data, _JSAMPARRAY *output_data_ptr) 318 { 319 _JSAMPARRAY output_data = *output_data_ptr; 320 _JSAMPROW inptr0, inptr1, outptr; 321 #if BITS_IN_JSAMPLE == 8 322 int thiscolsum, bias; 323 #else 324 JLONG thiscolsum, bias; 325 #endif 326 JDIMENSION colctr; 327 int inrow, outrow, v; 328 329 inrow = outrow = 0; 330 while (outrow < cinfo->max_v_samp_factor) { 331 for (v = 0; v < 2; v++) { 332 /* inptr0 points to nearest input row, inptr1 points to next nearest */ 333 inptr0 = input_data[inrow]; 334 if (v == 0) { /* next nearest is row above */ 335 inptr1 = input_data[inrow - 1]; 336 bias = 1; 337 } else { /* next nearest is row below */ 338 inptr1 = input_data[inrow + 1]; 339 bias = 2; 340 } 341 outptr = output_data[outrow++]; 342 343 for (colctr = 0; colctr < compptr->downsampled_width; colctr++) { 344 thiscolsum = (*inptr0++) * 3 + (*inptr1++); 345 *outptr++ = (_JSAMPLE)((thiscolsum + bias) >> 2); 346 } 347 } 348 inrow++; 349 } 350 } 351 352 353 /* 354 * Fancy processing for the common case of 2:1 horizontal and 2:1 vertical. 355 * Again a triangle filter; see comments for h2v1 case, above. 356 * 357 * It is OK for us to reference the adjacent input rows because we demanded 358 * context from the main buffer controller (see initialization code). 359 */ 360 361 METHODDEF(void) 362 h2v2_fancy_upsample(j_decompress_ptr cinfo, jpeg_component_info *compptr, 363 _JSAMPARRAY input_data, _JSAMPARRAY *output_data_ptr) 364 { 365 _JSAMPARRAY output_data = *output_data_ptr; 366 register _JSAMPROW inptr0, inptr1, outptr; 367 #if BITS_IN_JSAMPLE == 8 368 register int thiscolsum, lastcolsum, nextcolsum; 369 #else 370 register JLONG thiscolsum, lastcolsum, nextcolsum; 371 #endif 372 register JDIMENSION colctr; 373 int inrow, outrow, v; 374 375 inrow = outrow = 0; 376 while (outrow < cinfo->max_v_samp_factor) { 377 for (v = 0; v < 2; v++) { 378 /* inptr0 points to nearest input row, inptr1 points to next nearest */ 379 inptr0 = input_data[inrow]; 380 if (v == 0) /* next nearest is row above */ 381 inptr1 = input_data[inrow - 1]; 382 else /* next nearest is row below */ 383 inptr1 = input_data[inrow + 1]; 384 outptr = output_data[outrow++]; 385 386 /* Special case for first column */ 387 thiscolsum = (*inptr0++) * 3 + (*inptr1++); 388 nextcolsum = (*inptr0++) * 3 + (*inptr1++); 389 *outptr++ = (_JSAMPLE)((thiscolsum * 4 + 8) >> 4); 390 *outptr++ = (_JSAMPLE)((thiscolsum * 3 + nextcolsum + 7) >> 4); 391 lastcolsum = thiscolsum; thiscolsum = nextcolsum; 392 393 for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { 394 /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */ 395 /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */ 396 nextcolsum = (*inptr0++) * 3 + (*inptr1++); 397 *outptr++ = (_JSAMPLE)((thiscolsum * 3 + lastcolsum + 8) >> 4); 398 *outptr++ = (_JSAMPLE)((thiscolsum * 3 + nextcolsum + 7) >> 4); 399 lastcolsum = thiscolsum; thiscolsum = nextcolsum; 400 } 401 402 /* Special case for last column */ 403 *outptr++ = (_JSAMPLE)((thiscolsum * 3 + lastcolsum + 8) >> 4); 404 *outptr++ = (_JSAMPLE)((thiscolsum * 4 + 7) >> 4); 405 } 406 inrow++; 407 } 408 } 409 410 411 /* 412 * Module initialization routine for upsampling. 413 */ 414 415 GLOBAL(void) 416 _jinit_upsampler(j_decompress_ptr cinfo) 417 { 418 my_upsample_ptr upsample; 419 int ci; 420 jpeg_component_info *compptr; 421 boolean need_buffer, do_fancy; 422 int h_in_group, v_in_group, h_out_group, v_out_group; 423 424 if (cinfo->data_precision != BITS_IN_JSAMPLE) 425 ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); 426 427 if (!cinfo->master->jinit_upsampler_no_alloc) { 428 upsample = (my_upsample_ptr) 429 (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, 430 sizeof(my_upsampler)); 431 cinfo->upsample = (struct jpeg_upsampler *)upsample; 432 upsample->pub.start_pass = start_pass_upsample; 433 upsample->pub._upsample = sep_upsample; 434 upsample->pub.need_context_rows = FALSE; /* until we find out differently */ 435 } else 436 upsample = (my_upsample_ptr)cinfo->upsample; 437 438 if (cinfo->CCIR601_sampling) /* this isn't supported */ 439 ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); 440 441 /* jdmainct.c doesn't support context rows when min_DCT_scaled_size = 1, 442 * so don't ask for it. 443 */ 444 do_fancy = cinfo->do_fancy_upsampling && cinfo->_min_DCT_scaled_size > 1; 445 446 /* Verify we can handle the sampling factors, select per-component methods, 447 * and create storage as needed. 448 */ 449 for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; 450 ci++, compptr++) { 451 /* Compute size of an "input group" after IDCT scaling. This many samples 452 * are to be converted to max_h_samp_factor * max_v_samp_factor pixels. 453 */ 454 h_in_group = (compptr->h_samp_factor * compptr->_DCT_scaled_size) / 455 cinfo->_min_DCT_scaled_size; 456 v_in_group = (compptr->v_samp_factor * compptr->_DCT_scaled_size) / 457 cinfo->_min_DCT_scaled_size; 458 h_out_group = cinfo->max_h_samp_factor; 459 v_out_group = cinfo->max_v_samp_factor; 460 upsample->rowgroup_height[ci] = v_in_group; /* save for use later */ 461 need_buffer = TRUE; 462 if (!compptr->component_needed) { 463 /* Don't bother to upsample an uninteresting component. */ 464 upsample->methods[ci] = noop_upsample; 465 need_buffer = FALSE; 466 } else if (h_in_group == h_out_group && v_in_group == v_out_group) { 467 /* Fullsize components can be processed without any work. */ 468 upsample->methods[ci] = fullsize_upsample; 469 need_buffer = FALSE; 470 } else if (h_in_group * 2 == h_out_group && v_in_group == v_out_group) { 471 /* Special cases for 2h1v upsampling */ 472 if (do_fancy && compptr->downsampled_width > 2) { 473 #ifdef WITH_SIMD 474 if (jsimd_can_h2v1_fancy_upsample()) 475 upsample->methods[ci] = jsimd_h2v1_fancy_upsample; 476 else 477 #endif 478 upsample->methods[ci] = h2v1_fancy_upsample; 479 } else { 480 #ifdef WITH_SIMD 481 if (jsimd_can_h2v1_upsample()) 482 upsample->methods[ci] = jsimd_h2v1_upsample; 483 else 484 #endif 485 upsample->methods[ci] = h2v1_upsample; 486 } 487 } else if (h_in_group == h_out_group && 488 v_in_group * 2 == v_out_group && do_fancy) { 489 /* Non-fancy upsampling is handled by the generic method */ 490 #if defined(WITH_SIMD) && (defined(__arm__) || defined(__aarch64__) || \ 491 defined(_M_ARM) || defined(_M_ARM64)) 492 if (jsimd_can_h1v2_fancy_upsample()) 493 upsample->methods[ci] = jsimd_h1v2_fancy_upsample; 494 else 495 #endif 496 upsample->methods[ci] = h1v2_fancy_upsample; 497 upsample->pub.need_context_rows = TRUE; 498 } else if (h_in_group * 2 == h_out_group && 499 v_in_group * 2 == v_out_group) { 500 /* Special cases for 2h2v upsampling */ 501 if (do_fancy && compptr->downsampled_width > 2) { 502 #ifdef WITH_SIMD 503 if (jsimd_can_h2v2_fancy_upsample()) 504 upsample->methods[ci] = jsimd_h2v2_fancy_upsample; 505 else 506 #endif 507 upsample->methods[ci] = h2v2_fancy_upsample; 508 upsample->pub.need_context_rows = TRUE; 509 } else { 510 #ifdef WITH_SIMD 511 if (jsimd_can_h2v2_upsample()) 512 upsample->methods[ci] = jsimd_h2v2_upsample; 513 else 514 #endif 515 upsample->methods[ci] = h2v2_upsample; 516 } 517 } else if ((h_out_group % h_in_group) == 0 && 518 (v_out_group % v_in_group) == 0) { 519 /* Generic integral-factors upsampling method */ 520 #if defined(WITH_SIMD) && defined(__mips__) 521 if (jsimd_can_int_upsample()) 522 upsample->methods[ci] = jsimd_int_upsample; 523 else 524 #endif 525 upsample->methods[ci] = int_upsample; 526 upsample->h_expand[ci] = (UINT8)(h_out_group / h_in_group); 527 upsample->v_expand[ci] = (UINT8)(v_out_group / v_in_group); 528 } else 529 ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); 530 if (need_buffer && !cinfo->master->jinit_upsampler_no_alloc) { 531 upsample->color_buf[ci] = (_JSAMPARRAY)(*cinfo->mem->alloc_sarray) 532 ((j_common_ptr)cinfo, JPOOL_IMAGE, 533 (JDIMENSION)jround_up((long)cinfo->output_width, 534 (long)cinfo->max_h_samp_factor), 535 (JDIMENSION)cinfo->max_v_samp_factor); 536 } 537 } 538 } 539 540 #endif /* BITS_IN_JSAMPLE != 16 || defined(D_LOSSLESS_SUPPORTED) */