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