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@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 49typedef 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 75typedef 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 188LOCAL(void) 189build_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 231METHODDEF(void) 232start_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 249METHODDEF(void) 250merged_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 298METHODDEF(void) 299merged_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 331METHODDEF(void) 332h2v1_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 377METHODDEF(void) 378h2v2_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 427GLOBAL(void) 428jinit_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