1 /* 2 * jdmerge.c 3 * 4 * This file was part of the Independent JPEG Group's software: 5 * Copyright (C) 1994-1996, Thomas G. Lane. 6 * Copyright 2009 Pierre Ossman <ossman (at) cendio.se> for Cendio AB 7 * libjpeg-turbo Modifications: 8 * Copyright (C) 2009, 2011, D. R. Commander. 9 * For conditions of distribution and use, see the accompanying README file. 10 * 11 * This file contains code for merged upsampling/color conversion. 12 * 13 * This file combines functions from jdsample.c and jdcolor.c; 14 * read those files first to understand what's going on. 15 * 16 * When the chroma components are to be upsampled by simple replication 17 * (ie, box filtering), we can save some work in color conversion by 18 * calculating all the output pixels corresponding to a pair of chroma 19 * samples at one time. In the conversion equations 20 * R = Y + K1 * Cr 21 * G = Y + K2 * Cb + K3 * Cr 22 * B = Y + K4 * Cb 23 * only the Y term varies among the group of pixels corresponding to a pair 24 * of chroma samples, so the rest of the terms can be calculated just once. 25 * At typical sampling ratios, this eliminates half or three-quarters of the 26 * multiplications needed for color conversion. 27 * 28 * This file currently provides implementations for the following cases: 29 * YCbCr => RGB color conversion only. 30 * Sampling ratios of 2h1v or 2h2v. 31 * No scaling needed at upsample time. 32 * Corner-aligned (non-CCIR601) sampling alignment. 33 * Other special cases could be added, but in most applications these are 34 * the only common cases. (For uncommon cases we fall back on the more 35 * general code in jdsample.c and jdcolor.c.) 36 */ 37 38 #define JPEG_INTERNALS 39 #include "jinclude.h" 40 #include "jpeglib.h" 41 #include "jsimd.h" 42 #include "config.h" 43 44 #ifdef UPSAMPLE_MERGING_SUPPORTED 45 46 47 /* Private subobject */ 48 49 typedef struct { 50 struct jpeg_upsampler pub; /* public fields */ 51 52 /* Pointer to routine to do actual upsampling/conversion of one row group */ 53 JMETHOD(void, upmethod, (j_decompress_ptr cinfo, 54 JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, 55 JSAMPARRAY output_buf)); 56 57 /* Private state for YCC->RGB conversion */ 58 int * Cr_r_tab; /* => table for Cr to R conversion */ 59 int * Cb_b_tab; /* => table for Cb to B conversion */ 60 INT32 * Cr_g_tab; /* => table for Cr to G conversion */ 61 INT32 * Cb_g_tab; /* => table for Cb to G conversion */ 62 63 /* For 2:1 vertical sampling, we produce two output rows at a time. 64 * We need a "spare" row buffer to hold the second output row if the 65 * application provides just a one-row buffer; we also use the spare 66 * to discard the dummy last row if the image height is odd. 67 */ 68 JSAMPROW spare_row; 69 boolean spare_full; /* T if spare buffer is occupied */ 70 71 JDIMENSION out_row_width; /* samples per output row */ 72 JDIMENSION rows_to_go; /* counts rows remaining in image */ 73 } my_upsampler; 74 75 typedef my_upsampler * my_upsample_ptr; 76 77 #define SCALEBITS 16 /* speediest right-shift on some machines */ 78 #define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) 79 #define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5)) 80 81 82 /* Include inline routines for colorspace extensions */ 83 84 #include "jdmrgext.c" 85 #undef RGB_RED 86 #undef RGB_GREEN 87 #undef RGB_BLUE 88 #undef RGB_PIXELSIZE 89 90 #define RGB_RED EXT_RGB_RED 91 #define RGB_GREEN EXT_RGB_GREEN 92 #define RGB_BLUE EXT_RGB_BLUE 93 #define RGB_PIXELSIZE EXT_RGB_PIXELSIZE 94 #define h2v1_merged_upsample_internal extrgb_h2v1_merged_upsample_internal 95 #define h2v2_merged_upsample_internal extrgb_h2v2_merged_upsample_internal 96 #include "jdmrgext.c" 97 #undef RGB_RED 98 #undef RGB_GREEN 99 #undef RGB_BLUE 100 #undef RGB_PIXELSIZE 101 #undef h2v1_merged_upsample_internal 102 #undef h2v2_merged_upsample_internal 103 104 #define RGB_RED EXT_RGBX_RED 105 #define RGB_GREEN EXT_RGBX_GREEN 106 #define RGB_BLUE EXT_RGBX_BLUE 107 #define RGB_ALPHA 3 108 #define RGB_PIXELSIZE EXT_RGBX_PIXELSIZE 109 #define h2v1_merged_upsample_internal extrgbx_h2v1_merged_upsample_internal 110 #define h2v2_merged_upsample_internal extrgbx_h2v2_merged_upsample_internal 111 #include "jdmrgext.c" 112 #undef RGB_RED 113 #undef RGB_GREEN 114 #undef RGB_BLUE 115 #undef RGB_ALPHA 116 #undef RGB_PIXELSIZE 117 #undef h2v1_merged_upsample_internal 118 #undef h2v2_merged_upsample_internal 119 120 #define RGB_RED EXT_BGR_RED 121 #define RGB_GREEN EXT_BGR_GREEN 122 #define RGB_BLUE EXT_BGR_BLUE 123 #define RGB_PIXELSIZE EXT_BGR_PIXELSIZE 124 #define h2v1_merged_upsample_internal extbgr_h2v1_merged_upsample_internal 125 #define h2v2_merged_upsample_internal extbgr_h2v2_merged_upsample_internal 126 #include "jdmrgext.c" 127 #undef RGB_RED 128 #undef RGB_GREEN 129 #undef RGB_BLUE 130 #undef RGB_PIXELSIZE 131 #undef h2v1_merged_upsample_internal 132 #undef h2v2_merged_upsample_internal 133 134 #define RGB_RED EXT_BGRX_RED 135 #define RGB_GREEN EXT_BGRX_GREEN 136 #define RGB_BLUE EXT_BGRX_BLUE 137 #define RGB_ALPHA 3 138 #define RGB_PIXELSIZE EXT_BGRX_PIXELSIZE 139 #define h2v1_merged_upsample_internal extbgrx_h2v1_merged_upsample_internal 140 #define h2v2_merged_upsample_internal extbgrx_h2v2_merged_upsample_internal 141 #include "jdmrgext.c" 142 #undef RGB_RED 143 #undef RGB_GREEN 144 #undef RGB_BLUE 145 #undef RGB_ALPHA 146 #undef RGB_PIXELSIZE 147 #undef h2v1_merged_upsample_internal 148 #undef h2v2_merged_upsample_internal 149 150 #define RGB_RED EXT_XBGR_RED 151 #define RGB_GREEN EXT_XBGR_GREEN 152 #define RGB_BLUE EXT_XBGR_BLUE 153 #define RGB_ALPHA 0 154 #define RGB_PIXELSIZE EXT_XBGR_PIXELSIZE 155 #define h2v1_merged_upsample_internal extxbgr_h2v1_merged_upsample_internal 156 #define h2v2_merged_upsample_internal extxbgr_h2v2_merged_upsample_internal 157 #include "jdmrgext.c" 158 #undef RGB_RED 159 #undef RGB_GREEN 160 #undef RGB_BLUE 161 #undef RGB_ALPHA 162 #undef RGB_PIXELSIZE 163 #undef h2v1_merged_upsample_internal 164 #undef h2v2_merged_upsample_internal 165 166 #define RGB_RED EXT_XRGB_RED 167 #define RGB_GREEN EXT_XRGB_GREEN 168 #define RGB_BLUE EXT_XRGB_BLUE 169 #define RGB_ALPHA 0 170 #define RGB_PIXELSIZE EXT_XRGB_PIXELSIZE 171 #define h2v1_merged_upsample_internal extxrgb_h2v1_merged_upsample_internal 172 #define h2v2_merged_upsample_internal extxrgb_h2v2_merged_upsample_internal 173 #include "jdmrgext.c" 174 #undef RGB_RED 175 #undef RGB_GREEN 176 #undef RGB_BLUE 177 #undef RGB_ALPHA 178 #undef RGB_PIXELSIZE 179 #undef h2v1_merged_upsample_internal 180 #undef h2v2_merged_upsample_internal 181 182 183 /* 184 * Initialize tables for YCC->RGB colorspace conversion. 185 * This is taken directly from jdcolor.c; see that file for more info. 186 */ 187 188 LOCAL(void) 189 build_ycc_rgb_table (j_decompress_ptr cinfo) 190 { 191 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; 192 int i; 193 INT32 x; 194 SHIFT_TEMPS 195 196 upsample->Cr_r_tab = (int *) 197 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 198 (MAXJSAMPLE+1) * SIZEOF(int)); 199 upsample->Cb_b_tab = (int *) 200 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 201 (MAXJSAMPLE+1) * SIZEOF(int)); 202 upsample->Cr_g_tab = (INT32 *) 203 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 204 (MAXJSAMPLE+1) * SIZEOF(INT32)); 205 upsample->Cb_g_tab = (INT32 *) 206 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 207 (MAXJSAMPLE+1) * SIZEOF(INT32)); 208 209 for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { 210 /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ 211 /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ 212 /* Cr=>R value is nearest int to 1.40200 * x */ 213 upsample->Cr_r_tab[i] = (int) 214 RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); 215 /* Cb=>B value is nearest int to 1.77200 * x */ 216 upsample->Cb_b_tab[i] = (int) 217 RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); 218 /* Cr=>G value is scaled-up -0.71414 * x */ 219 upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x; 220 /* Cb=>G value is scaled-up -0.34414 * x */ 221 /* We also add in ONE_HALF so that need not do it in inner loop */ 222 upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; 223 } 224 } 225 226 227 /* 228 * Initialize for an upsampling pass. 229 */ 230 231 METHODDEF(void) 232 start_pass_merged_upsample (j_decompress_ptr cinfo) 233 { 234 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; 235 236 /* Mark the spare buffer empty */ 237 upsample->spare_full = FALSE; 238 /* Initialize total-height counter for detecting bottom of image */ 239 upsample->rows_to_go = cinfo->output_height; 240 } 241 242 243 /* 244 * Control routine to do upsampling (and color conversion). 245 * 246 * The control routine just handles the row buffering considerations. 247 */ 248 249 METHODDEF(void) 250 merged_2v_upsample (j_decompress_ptr cinfo, 251 JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, 252 JDIMENSION in_row_groups_avail, 253 JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, 254 JDIMENSION out_rows_avail) 255 /* 2:1 vertical sampling case: may need a spare row. */ 256 { 257 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; 258 JSAMPROW work_ptrs[2]; 259 JDIMENSION num_rows; /* number of rows returned to caller */ 260 261 if (upsample->spare_full) { 262 /* If we have a spare row saved from a previous cycle, just return it. */ 263 jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0, 264 1, upsample->out_row_width); 265 num_rows = 1; 266 upsample->spare_full = FALSE; 267 } else { 268 /* Figure number of rows to return to caller. */ 269 num_rows = 2; 270 /* Not more than the distance to the end of the image. */ 271 if (num_rows > upsample->rows_to_go) 272 num_rows = upsample->rows_to_go; 273 /* And not more than what the client can accept: */ 274 out_rows_avail -= *out_row_ctr; 275 if (num_rows > out_rows_avail) 276 num_rows = out_rows_avail; 277 /* Create output pointer array for upsampler. */ 278 work_ptrs[0] = output_buf[*out_row_ctr]; 279 if (num_rows > 1) { 280 work_ptrs[1] = output_buf[*out_row_ctr + 1]; 281 } else { 282 work_ptrs[1] = upsample->spare_row; 283 upsample->spare_full = TRUE; 284 } 285 /* Now do the upsampling. */ 286 (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs); 287 } 288 289 /* Adjust counts */ 290 *out_row_ctr += num_rows; 291 upsample->rows_to_go -= num_rows; 292 /* When the buffer is emptied, declare this input row group consumed */ 293 if (! upsample->spare_full) 294 (*in_row_group_ctr)++; 295 } 296 297 298 METHODDEF(void) 299 merged_1v_upsample (j_decompress_ptr cinfo, 300 JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, 301 JDIMENSION in_row_groups_avail, 302 JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, 303 JDIMENSION out_rows_avail) 304 /* 1:1 vertical sampling case: much easier, never need a spare row. */ 305 { 306 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; 307 308 /* Just do the upsampling. */ 309 (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, 310 output_buf + *out_row_ctr); 311 /* Adjust counts */ 312 (*out_row_ctr)++; 313 (*in_row_group_ctr)++; 314 } 315 316 317 /* 318 * These are the routines invoked by the control routines to do 319 * the actual upsampling/conversion. One row group is processed per call. 320 * 321 * Note: since we may be writing directly into application-supplied buffers, 322 * we have to be honest about the output width; we can't assume the buffer 323 * has been rounded up to an even width. 324 */ 325 326 327 /* 328 * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical. 329 */ 330 331 METHODDEF(void) 332 h2v1_merged_upsample (j_decompress_ptr cinfo, 333 JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, 334 JSAMPARRAY output_buf) 335 { 336 switch (cinfo->out_color_space) { 337 case JCS_EXT_RGB: 338 extrgb_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, 339 output_buf); 340 break; 341 case JCS_EXT_RGBX: 342 case JCS_EXT_RGBA: 343 extrgbx_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, 344 output_buf); 345 break; 346 case JCS_EXT_BGR: 347 extbgr_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, 348 output_buf); 349 break; 350 case JCS_EXT_BGRX: 351 case JCS_EXT_BGRA: 352 extbgrx_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, 353 output_buf); 354 break; 355 case JCS_EXT_XBGR: 356 case JCS_EXT_ABGR: 357 extxbgr_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, 358 output_buf); 359 break; 360 case JCS_EXT_XRGB: 361 case JCS_EXT_ARGB: 362 extxrgb_h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, 363 output_buf); 364 break; 365 default: 366 h2v1_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, 367 output_buf); 368 break; 369 } 370 } 371 372 373 /* 374 * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical. 375 */ 376 377 METHODDEF(void) 378 h2v2_merged_upsample (j_decompress_ptr cinfo, 379 JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, 380 JSAMPARRAY output_buf) 381 { 382 switch (cinfo->out_color_space) { 383 case JCS_EXT_RGB: 384 extrgb_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, 385 output_buf); 386 break; 387 case JCS_EXT_RGBX: 388 case JCS_EXT_RGBA: 389 extrgbx_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, 390 output_buf); 391 break; 392 case JCS_EXT_BGR: 393 extbgr_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, 394 output_buf); 395 break; 396 case JCS_EXT_BGRX: 397 case JCS_EXT_BGRA: 398 extbgrx_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, 399 output_buf); 400 break; 401 case JCS_EXT_XBGR: 402 case JCS_EXT_ABGR: 403 extxbgr_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, 404 output_buf); 405 break; 406 case JCS_EXT_XRGB: 407 case JCS_EXT_ARGB: 408 extxrgb_h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, 409 output_buf); 410 break; 411 default: 412 h2v2_merged_upsample_internal(cinfo, input_buf, in_row_group_ctr, 413 output_buf); 414 break; 415 } 416 } 417 418 419 /* 420 * Module initialization routine for merged upsampling/color conversion. 421 * 422 * NB: this is called under the conditions determined by use_merged_upsample() 423 * in jdmaster.c. That routine MUST correspond to the actual capabilities 424 * of this module; no safety checks are made here. 425 */ 426 427 GLOBAL(void) 428 jinit_merged_upsampler (j_decompress_ptr cinfo) 429 { 430 my_upsample_ptr upsample; 431 432 upsample = (my_upsample_ptr) 433 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 434 SIZEOF(my_upsampler)); 435 cinfo->upsample = (struct jpeg_upsampler *) upsample; 436 upsample->pub.start_pass = start_pass_merged_upsample; 437 upsample->pub.need_context_rows = FALSE; 438 439 upsample->out_row_width = cinfo->output_width * cinfo->out_color_components; 440 441 if (cinfo->max_v_samp_factor == 2) { 442 upsample->pub.upsample = merged_2v_upsample; 443 if (jsimd_can_h2v2_merged_upsample()) 444 upsample->upmethod = jsimd_h2v2_merged_upsample; 445 else 446 upsample->upmethod = h2v2_merged_upsample; 447 /* Allocate a spare row buffer */ 448 upsample->spare_row = (JSAMPROW) 449 (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, 450 (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE))); 451 } else { 452 upsample->pub.upsample = merged_1v_upsample; 453 if (jsimd_can_h2v1_merged_upsample()) 454 upsample->upmethod = jsimd_h2v1_merged_upsample; 455 else 456 upsample->upmethod = h2v1_merged_upsample; 457 /* No spare row needed */ 458 upsample->spare_row = NULL; 459 } 460 461 build_ycc_rgb_table(cinfo); 462 } 463 464 #endif /* UPSAMPLE_MERGING_SUPPORTED */ 465