1 /* 2 * jdmerge.c 3 * 4 * Copyright (C) 1994-1996, Thomas G. Lane. 5 * This file is part of the Independent JPEG Group's software. 6 * For conditions of distribution and use, see the accompanying README file. 7 * 8 * This file contains code for merged upsampling/color conversion. 9 * 10 * This file combines functions from jdsample.c and jdcolor.c; 11 * read those files first to understand what's going on. 12 * 13 * When the chroma components are to be upsampled by simple replication 14 * (ie, box filtering), we can save some work in color conversion by 15 * calculating all the output pixels corresponding to a pair of chroma 16 * samples at one time. In the conversion equations 17 * R = Y + K1 * Cr 18 * G = Y + K2 * Cb + K3 * Cr 19 * B = Y + K4 * Cb 20 * only the Y term varies among the group of pixels corresponding to a pair 21 * of chroma samples, so the rest of the terms can be calculated just once. 22 * At typical sampling ratios, this eliminates half or three-quarters of the 23 * multiplications needed for color conversion. 24 * 25 * This file currently provides implementations for the following cases: 26 * YCbCr => RGB color conversion only. 27 * Sampling ratios of 2h1v or 2h2v. 28 * No scaling needed at upsample time. 29 * Corner-aligned (non-CCIR601) sampling alignment. 30 * Other special cases could be added, but in most applications these are 31 * the only common cases. (For uncommon cases we fall back on the more 32 * general code in jdsample.c and jdcolor.c.) 33 */ 34 35 #define JPEG_INTERNALS 36 #include "jinclude.h" 37 #include "jpeglib.h" 38 39 #ifdef UPSAMPLE_MERGING_SUPPORTED 40 41 #ifdef ANDROID_RGB 42 43 /* Declarations for ordered dithering. 44 * 45 * We use 4x4 ordered dither array packed into 32 bits. This array is 46 * sufficent for dithering RGB_888 to RGB_565. 47 */ 48 49 #define DITHER_MASK 0x3 50 #define DITHER_ROTATE(x) (((x)<<24) | (((x)>>8)&0x00FFFFFF)) 51 static const INT32 dither_matrix[4] = { 52 0x0008020A, 53 0x0C040E06, 54 0x030B0109, 55 0x0F070D05 56 }; 57 58 #endif 59 60 /* Private subobject */ 61 62 typedef struct { 63 struct jpeg_upsampler pub; /* public fields */ 64 65 /* Pointer to routine to do actual upsampling/conversion of one row group */ 66 JMETHOD(void, upmethod, (j_decompress_ptr cinfo, 67 JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, 68 JSAMPARRAY output_buf)); 69 70 /* Private state for YCC->RGB conversion */ 71 int * Cr_r_tab; /* => table for Cr to R conversion */ 72 int * Cb_b_tab; /* => table for Cb to B conversion */ 73 INT32 * Cr_g_tab; /* => table for Cr to G conversion */ 74 INT32 * Cb_g_tab; /* => table for Cb to G conversion */ 75 76 /* For 2:1 vertical sampling, we produce two output rows at a time. 77 * We need a "spare" row buffer to hold the second output row if the 78 * application provides just a one-row buffer; we also use the spare 79 * to discard the dummy last row if the image height is odd. 80 */ 81 JSAMPROW spare_row; 82 boolean spare_full; /* T if spare buffer is occupied */ 83 84 JDIMENSION out_row_width; /* samples per output row */ 85 JDIMENSION rows_to_go; /* counts rows remaining in image */ 86 } my_upsampler; 87 88 typedef my_upsampler * my_upsample_ptr; 89 90 #define SCALEBITS 16 /* speediest right-shift on some machines */ 91 #define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) 92 #define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5)) 93 94 95 /* 96 * Initialize tables for YCC->RGB colorspace conversion. 97 * This is taken directly from jdcolor.c; see that file for more info. 98 */ 99 100 LOCAL(void) 101 build_ycc_rgb_table (j_decompress_ptr cinfo) 102 { 103 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; 104 int i; 105 INT32 x; 106 SHIFT_TEMPS 107 108 upsample->Cr_r_tab = (int *) 109 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 110 (MAXJSAMPLE+1) * SIZEOF(int)); 111 upsample->Cb_b_tab = (int *) 112 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 113 (MAXJSAMPLE+1) * SIZEOF(int)); 114 upsample->Cr_g_tab = (INT32 *) 115 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 116 (MAXJSAMPLE+1) * SIZEOF(INT32)); 117 upsample->Cb_g_tab = (INT32 *) 118 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 119 (MAXJSAMPLE+1) * SIZEOF(INT32)); 120 121 for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { 122 /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ 123 /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ 124 /* Cr=>R value is nearest int to 1.40200 * x */ 125 upsample->Cr_r_tab[i] = (int) 126 RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); 127 /* Cb=>B value is nearest int to 1.77200 * x */ 128 upsample->Cb_b_tab[i] = (int) 129 RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); 130 /* Cr=>G value is scaled-up -0.71414 * x */ 131 upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x; 132 /* Cb=>G value is scaled-up -0.34414 * x */ 133 /* We also add in ONE_HALF so that need not do it in inner loop */ 134 upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; 135 } 136 } 137 138 139 /* 140 * Initialize for an upsampling pass. 141 */ 142 143 METHODDEF(void) 144 start_pass_merged_upsample (j_decompress_ptr cinfo) 145 { 146 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; 147 148 /* Mark the spare buffer empty */ 149 upsample->spare_full = FALSE; 150 /* Initialize total-height counter for detecting bottom of image */ 151 upsample->rows_to_go = cinfo->output_height; 152 } 153 154 155 /* 156 * Control routine to do upsampling (and color conversion). 157 * 158 * The control routine just handles the row buffering considerations. 159 */ 160 161 METHODDEF(void) 162 merged_2v_upsample (j_decompress_ptr cinfo, 163 JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, 164 JDIMENSION in_row_groups_avail, 165 JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, 166 JDIMENSION out_rows_avail) 167 /* 2:1 vertical sampling case: may need a spare row. */ 168 { 169 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; 170 JSAMPROW work_ptrs[2]; 171 JDIMENSION num_rows; /* number of rows returned to caller */ 172 173 if (upsample->spare_full) { 174 /* If we have a spare row saved from a previous cycle, just return it. */ 175 JDIMENSION size = upsample->out_row_width; 176 #ifdef ANDROID_RGB 177 if (cinfo->out_color_space == JCS_RGB_565) 178 size = cinfo->output_width*2; 179 #endif 180 jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0, 181 1, size); 182 183 num_rows = 1; 184 upsample->spare_full = FALSE; 185 } else { 186 /* Figure number of rows to return to caller. */ 187 num_rows = 2; 188 /* Not more than the distance to the end of the image. */ 189 if (num_rows > upsample->rows_to_go) 190 num_rows = upsample->rows_to_go; 191 /* And not more than what the client can accept: */ 192 out_rows_avail -= *out_row_ctr; 193 if (num_rows > out_rows_avail) 194 num_rows = out_rows_avail; 195 /* Create output pointer array for upsampler. */ 196 work_ptrs[0] = output_buf[*out_row_ctr]; 197 if (num_rows > 1) { 198 work_ptrs[1] = output_buf[*out_row_ctr + 1]; 199 } else { 200 work_ptrs[1] = upsample->spare_row; 201 upsample->spare_full = TRUE; 202 } 203 /* Now do the upsampling. */ 204 (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs); 205 } 206 207 /* Adjust counts */ 208 *out_row_ctr += num_rows; 209 upsample->rows_to_go -= num_rows; 210 /* When the buffer is emptied, declare this input row group consumed */ 211 if (! upsample->spare_full) 212 (*in_row_group_ctr)++; 213 } 214 215 216 METHODDEF(void) 217 merged_1v_upsample (j_decompress_ptr cinfo, 218 JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, 219 JDIMENSION in_row_groups_avail, 220 JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, 221 JDIMENSION out_rows_avail) 222 /* 1:1 vertical sampling case: much easier, never need a spare row. */ 223 { 224 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; 225 226 /* Just do the upsampling. */ 227 (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, 228 output_buf + *out_row_ctr); 229 /* Adjust counts */ 230 (*out_row_ctr)++; 231 (*in_row_group_ctr)++; 232 } 233 234 235 /* 236 * These are the routines invoked by the control routines to do 237 * the actual upsampling/conversion. One row group is processed per call. 238 * 239 * Note: since we may be writing directly into application-supplied buffers, 240 * we have to be honest about the output width; we can't assume the buffer 241 * has been rounded up to an even width. 242 */ 243 244 245 /* 246 * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical. 247 */ 248 249 METHODDEF(void) 250 h2v1_merged_upsample (j_decompress_ptr cinfo, 251 JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, 252 JSAMPARRAY output_buf) 253 { 254 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; 255 register int y, cred, cgreen, cblue; 256 int cb, cr; 257 register JSAMPROW outptr; 258 JSAMPROW inptr0, inptr1, inptr2; 259 JDIMENSION col; 260 /* copy these pointers into registers if possible */ 261 register JSAMPLE * range_limit = cinfo->sample_range_limit; 262 int * Crrtab = upsample->Cr_r_tab; 263 int * Cbbtab = upsample->Cb_b_tab; 264 INT32 * Crgtab = upsample->Cr_g_tab; 265 INT32 * Cbgtab = upsample->Cb_g_tab; 266 SHIFT_TEMPS 267 268 inptr0 = input_buf[0][in_row_group_ctr]; 269 inptr1 = input_buf[1][in_row_group_ctr]; 270 inptr2 = input_buf[2][in_row_group_ctr]; 271 outptr = output_buf[0]; 272 /* Loop for each pair of output pixels */ 273 for (col = cinfo->output_width >> 1; col > 0; col--) { 274 /* Do the chroma part of the calculation */ 275 cb = GETJSAMPLE(*inptr1++); 276 cr = GETJSAMPLE(*inptr2++); 277 cred = Crrtab[cr]; 278 cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); 279 cblue = Cbbtab[cb]; 280 /* Fetch 2 Y values and emit 2 pixels */ 281 y = GETJSAMPLE(*inptr0++); 282 outptr[RGB_RED] = range_limit[y + cred]; 283 outptr[RGB_GREEN] = range_limit[y + cgreen]; 284 outptr[RGB_BLUE] = range_limit[y + cblue]; 285 outptr += RGB_PIXELSIZE; 286 y = GETJSAMPLE(*inptr0++); 287 outptr[RGB_RED] = range_limit[y + cred]; 288 outptr[RGB_GREEN] = range_limit[y + cgreen]; 289 outptr[RGB_BLUE] = range_limit[y + cblue]; 290 outptr += RGB_PIXELSIZE; 291 } 292 /* If image width is odd, do the last output column separately */ 293 if (cinfo->output_width & 1) { 294 cb = GETJSAMPLE(*inptr1); 295 cr = GETJSAMPLE(*inptr2); 296 cred = Crrtab[cr]; 297 cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); 298 cblue = Cbbtab[cb]; 299 y = GETJSAMPLE(*inptr0); 300 outptr[RGB_RED] = range_limit[y + cred]; 301 outptr[RGB_GREEN] = range_limit[y + cgreen]; 302 outptr[RGB_BLUE] = range_limit[y + cblue]; 303 } 304 } 305 306 307 #ifdef ANDROID_RGB 308 METHODDEF(void) 309 h2v1_merged_upsample_565 (j_decompress_ptr cinfo, 310 JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, 311 JSAMPARRAY output_buf) 312 { 313 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; 314 register int y, cred, cgreen, cblue; 315 int cb, cr; 316 register JSAMPROW outptr; 317 JSAMPROW inptr0, inptr1, inptr2; 318 JDIMENSION col; 319 /* copy these pointers into registers if possible */ 320 register JSAMPLE * range_limit = cinfo->sample_range_limit; 321 int * Crrtab = upsample->Cr_r_tab; 322 int * Cbbtab = upsample->Cb_b_tab; 323 INT32 * Crgtab = upsample->Cr_g_tab; 324 INT32 * Cbgtab = upsample->Cb_g_tab; 325 unsigned int r, g, b; 326 INT32 rgb; 327 SHIFT_TEMPS 328 329 inptr0 = input_buf[0][in_row_group_ctr]; 330 inptr1 = input_buf[1][in_row_group_ctr]; 331 inptr2 = input_buf[2][in_row_group_ctr]; 332 outptr = output_buf[0]; 333 /* Loop for each pair of output pixels */ 334 for (col = cinfo->output_width >> 1; col > 0; col--) { 335 /* Do the chroma part of the calculation */ 336 cb = GETJSAMPLE(*inptr1++); 337 cr = GETJSAMPLE(*inptr2++); 338 cred = Crrtab[cr]; 339 cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); 340 cblue = Cbbtab[cb]; 341 /* Fetch 2 Y values and emit 2 pixels */ 342 y = GETJSAMPLE(*inptr0++); 343 r = range_limit[y + cred]; 344 g = range_limit[y + cgreen]; 345 b = range_limit[y + cblue]; 346 rgb = PACK_SHORT_565(r,g,b); 347 y = GETJSAMPLE(*inptr0++); 348 r = range_limit[y + cred]; 349 g = range_limit[y + cgreen]; 350 b = range_limit[y + cblue]; 351 rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r,g,b)); 352 WRITE_TWO_PIXELS(outptr, rgb); 353 outptr += 4; 354 } 355 /* If image width is odd, do the last output column separately */ 356 if (cinfo->output_width & 1) { 357 cb = GETJSAMPLE(*inptr1); 358 cr = GETJSAMPLE(*inptr2); 359 cred = Crrtab[cr]; 360 cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); 361 cblue = Cbbtab[cb]; 362 y = GETJSAMPLE(*inptr0); 363 r = range_limit[y + cred]; 364 g = range_limit[y + cgreen]; 365 b = range_limit[y + cblue]; 366 rgb = PACK_SHORT_565(r,g,b); 367 *(INT16*)outptr = rgb; 368 } 369 } 370 371 372 METHODDEF(void) 373 h2v1_merged_upsample_565D (j_decompress_ptr cinfo, 374 JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, 375 JSAMPARRAY output_buf) 376 { 377 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; 378 register int y, cred, cgreen, cblue; 379 int cb, cr; 380 register JSAMPROW outptr; 381 JSAMPROW inptr0, inptr1, inptr2; 382 JDIMENSION col; 383 /* copy these pointers into registers if possible */ 384 register JSAMPLE * range_limit = cinfo->sample_range_limit; 385 int * Crrtab = upsample->Cr_r_tab; 386 int * Cbbtab = upsample->Cb_b_tab; 387 INT32 * Crgtab = upsample->Cr_g_tab; 388 INT32 * Cbgtab = upsample->Cb_g_tab; 389 JDIMENSION col_index = 0; 390 INT32 d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK]; 391 unsigned int r, g, b; 392 INT32 rgb; 393 SHIFT_TEMPS 394 395 inptr0 = input_buf[0][in_row_group_ctr]; 396 inptr1 = input_buf[1][in_row_group_ctr]; 397 inptr2 = input_buf[2][in_row_group_ctr]; 398 outptr = output_buf[0]; 399 /* Loop for each pair of output pixels */ 400 for (col = cinfo->output_width >> 1; col > 0; col--) { 401 /* Do the chroma part of the calculation */ 402 cb = GETJSAMPLE(*inptr1++); 403 cr = GETJSAMPLE(*inptr2++); 404 cred = Crrtab[cr]; 405 cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); 406 cblue = Cbbtab[cb]; 407 /* Fetch 2 Y values and emit 2 pixels */ 408 y = GETJSAMPLE(*inptr0++); 409 r = range_limit[DITHER_565_R(y + cred, d0)]; 410 g = range_limit[DITHER_565_G(y + cgreen, d0)]; 411 b = range_limit[DITHER_565_B(y + cblue, d0)]; 412 d0 = DITHER_ROTATE(d0); 413 rgb = PACK_SHORT_565(r,g,b); 414 y = GETJSAMPLE(*inptr0++); 415 r = range_limit[DITHER_565_R(y + cred, d0)]; 416 g = range_limit[DITHER_565_G(y + cgreen, d0)]; 417 b = range_limit[DITHER_565_B(y + cblue, d0)]; 418 d0 = DITHER_ROTATE(d0); 419 rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r,g,b)); 420 WRITE_TWO_PIXELS(outptr, rgb); 421 outptr += 4; 422 } 423 /* If image width is odd, do the last output column separately */ 424 if (cinfo->output_width & 1) { 425 cb = GETJSAMPLE(*inptr1); 426 cr = GETJSAMPLE(*inptr2); 427 cred = Crrtab[cr]; 428 cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); 429 cblue = Cbbtab[cb]; 430 y = GETJSAMPLE(*inptr0); 431 r = range_limit[DITHER_565_R(y + cred, d0)]; 432 g = range_limit[DITHER_565_G(y + cgreen, d0)]; 433 b = range_limit[DITHER_565_B(y + cblue, d0)]; 434 rgb = PACK_SHORT_565(r,g,b); 435 *(INT16*)outptr = rgb; 436 } 437 } 438 439 440 #endif 441 442 /* 443 * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical. 444 */ 445 446 METHODDEF(void) 447 h2v2_merged_upsample (j_decompress_ptr cinfo, 448 JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, 449 JSAMPARRAY output_buf) 450 { 451 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; 452 register int y, cred, cgreen, cblue; 453 int cb, cr; 454 register JSAMPROW outptr0, outptr1; 455 JSAMPROW inptr00, inptr01, inptr1, inptr2; 456 JDIMENSION col; 457 /* copy these pointers into registers if possible */ 458 register JSAMPLE * range_limit = cinfo->sample_range_limit; 459 int * Crrtab = upsample->Cr_r_tab; 460 int * Cbbtab = upsample->Cb_b_tab; 461 INT32 * Crgtab = upsample->Cr_g_tab; 462 INT32 * Cbgtab = upsample->Cb_g_tab; 463 SHIFT_TEMPS 464 465 inptr00 = input_buf[0][in_row_group_ctr*2]; 466 inptr01 = input_buf[0][in_row_group_ctr*2 + 1]; 467 inptr1 = input_buf[1][in_row_group_ctr]; 468 inptr2 = input_buf[2][in_row_group_ctr]; 469 outptr0 = output_buf[0]; 470 outptr1 = output_buf[1]; 471 /* Loop for each group of output pixels */ 472 for (col = cinfo->output_width >> 1; col > 0; col--) { 473 /* Do the chroma part of the calculation */ 474 cb = GETJSAMPLE(*inptr1++); 475 cr = GETJSAMPLE(*inptr2++); 476 cred = Crrtab[cr]; 477 cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); 478 cblue = Cbbtab[cb]; 479 /* Fetch 4 Y values and emit 4 pixels */ 480 y = GETJSAMPLE(*inptr00++); 481 outptr0[RGB_RED] = range_limit[y + cred]; 482 outptr0[RGB_GREEN] = range_limit[y + cgreen]; 483 outptr0[RGB_BLUE] = range_limit[y + cblue]; 484 outptr0 += RGB_PIXELSIZE; 485 y = GETJSAMPLE(*inptr00++); 486 outptr0[RGB_RED] = range_limit[y + cred]; 487 outptr0[RGB_GREEN] = range_limit[y + cgreen]; 488 outptr0[RGB_BLUE] = range_limit[y + cblue]; 489 outptr0 += RGB_PIXELSIZE; 490 y = GETJSAMPLE(*inptr01++); 491 outptr1[RGB_RED] = range_limit[y + cred]; 492 outptr1[RGB_GREEN] = range_limit[y + cgreen]; 493 outptr1[RGB_BLUE] = range_limit[y + cblue]; 494 outptr1 += RGB_PIXELSIZE; 495 y = GETJSAMPLE(*inptr01++); 496 outptr1[RGB_RED] = range_limit[y + cred]; 497 outptr1[RGB_GREEN] = range_limit[y + cgreen]; 498 outptr1[RGB_BLUE] = range_limit[y + cblue]; 499 outptr1 += RGB_PIXELSIZE; 500 } 501 /* If image width is odd, do the last output column separately */ 502 if (cinfo->output_width & 1) { 503 cb = GETJSAMPLE(*inptr1); 504 cr = GETJSAMPLE(*inptr2); 505 cred = Crrtab[cr]; 506 cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); 507 cblue = Cbbtab[cb]; 508 y = GETJSAMPLE(*inptr00); 509 outptr0[RGB_RED] = range_limit[y + cred]; 510 outptr0[RGB_GREEN] = range_limit[y + cgreen]; 511 outptr0[RGB_BLUE] = range_limit[y + cblue]; 512 y = GETJSAMPLE(*inptr01); 513 outptr1[RGB_RED] = range_limit[y + cred]; 514 outptr1[RGB_GREEN] = range_limit[y + cgreen]; 515 outptr1[RGB_BLUE] = range_limit[y + cblue]; 516 } 517 } 518 519 520 #ifdef ANDROID_RGB 521 522 METHODDEF(void) 523 h2v2_merged_upsample_565 (j_decompress_ptr cinfo, 524 JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, 525 JSAMPARRAY output_buf) 526 { 527 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; 528 register int y, cred, cgreen, cblue; 529 int cb, cr; 530 register JSAMPROW outptr0, outptr1; 531 JSAMPROW inptr00, inptr01, inptr1, inptr2; 532 JDIMENSION col; 533 /* copy these pointers into registers if possible */ 534 register JSAMPLE * range_limit = cinfo->sample_range_limit; 535 int * Crrtab = upsample->Cr_r_tab; 536 int * Cbbtab = upsample->Cb_b_tab; 537 INT32 * Crgtab = upsample->Cr_g_tab; 538 INT32 * Cbgtab = upsample->Cb_g_tab; 539 unsigned int r, g, b; 540 INT32 rgb; 541 SHIFT_TEMPS 542 543 inptr00 = input_buf[0][in_row_group_ctr*2]; 544 inptr01 = input_buf[0][in_row_group_ctr*2 + 1]; 545 inptr1 = input_buf[1][in_row_group_ctr]; 546 inptr2 = input_buf[2][in_row_group_ctr]; 547 outptr0 = output_buf[0]; 548 outptr1 = output_buf[1]; 549 /* Loop for each group of output pixels */ 550 for (col = cinfo->output_width >> 1; col > 0; col--) { 551 /* Do the chroma part of the calculation */ 552 cb = GETJSAMPLE(*inptr1++); 553 cr = GETJSAMPLE(*inptr2++); 554 cred = Crrtab[cr]; 555 cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); 556 cblue = Cbbtab[cb]; 557 /* Fetch 4 Y values and emit 4 pixels */ 558 y = GETJSAMPLE(*inptr00++); 559 r = range_limit[y + cred]; 560 g = range_limit[y + cgreen]; 561 b = range_limit[y + cblue]; 562 rgb = PACK_SHORT_565(r,g,b); 563 y = GETJSAMPLE(*inptr00++); 564 r = range_limit[y + cred]; 565 g = range_limit[y + cgreen]; 566 b = range_limit[y + cblue]; 567 rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r,g,b)); 568 WRITE_TWO_PIXELS(outptr0, rgb); 569 outptr0 += 4; 570 y = GETJSAMPLE(*inptr01++); 571 r = range_limit[y + cred]; 572 g = range_limit[y + cgreen]; 573 b = range_limit[y + cblue]; 574 rgb = PACK_SHORT_565(r,g,b); 575 y = GETJSAMPLE(*inptr01++); 576 r = range_limit[y + cred]; 577 g = range_limit[y + cgreen]; 578 b = range_limit[y + cblue]; 579 rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r,g,b)); 580 WRITE_TWO_PIXELS(outptr1, rgb); 581 outptr1 += 4; 582 } 583 /* If image width is odd, do the last output column separately */ 584 if (cinfo->output_width & 1) { 585 cb = GETJSAMPLE(*inptr1); 586 cr = GETJSAMPLE(*inptr2); 587 cred = Crrtab[cr]; 588 cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); 589 cblue = Cbbtab[cb]; 590 y = GETJSAMPLE(*inptr00); 591 r = range_limit[y + cred]; 592 g = range_limit[y + cgreen]; 593 b = range_limit[y + cblue]; 594 rgb = PACK_SHORT_565(r,g,b); 595 *(INT16*)outptr0 = rgb; 596 y = GETJSAMPLE(*inptr01); 597 r = range_limit[y + cred]; 598 g = range_limit[y + cgreen]; 599 b = range_limit[y + cblue]; 600 rgb = PACK_SHORT_565(r,g,b); 601 *(INT16*)outptr1 = rgb; 602 } 603 } 604 605 606 607 METHODDEF(void) 608 h2v2_merged_upsample_565D (j_decompress_ptr cinfo, 609 JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr, 610 JSAMPARRAY output_buf) 611 { 612 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; 613 register int y, cred, cgreen, cblue; 614 int cb, cr; 615 register JSAMPROW outptr0, outptr1; 616 JSAMPROW inptr00, inptr01, inptr1, inptr2; 617 JDIMENSION col; 618 /* copy these pointers into registers if possible */ 619 register JSAMPLE * range_limit = cinfo->sample_range_limit; 620 int * Crrtab = upsample->Cr_r_tab; 621 int * Cbbtab = upsample->Cb_b_tab; 622 INT32 * Crgtab = upsample->Cr_g_tab; 623 INT32 * Cbgtab = upsample->Cb_g_tab; 624 JDIMENSION col_index = 0; 625 INT32 d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK]; 626 INT32 d1 = dither_matrix[(cinfo->output_scanline+1) & DITHER_MASK]; 627 unsigned int r, g, b; 628 INT32 rgb; 629 SHIFT_TEMPS 630 631 inptr00 = input_buf[0][in_row_group_ctr*2]; 632 inptr01 = input_buf[0][in_row_group_ctr*2 + 1]; 633 inptr1 = input_buf[1][in_row_group_ctr]; 634 inptr2 = input_buf[2][in_row_group_ctr]; 635 outptr0 = output_buf[0]; 636 outptr1 = output_buf[1]; 637 /* Loop for each group of output pixels */ 638 for (col = cinfo->output_width >> 1; col > 0; col--) { 639 640 /* Do the chroma part of the calculation */ 641 cb = GETJSAMPLE(*inptr1++); 642 cr = GETJSAMPLE(*inptr2++); 643 cred = Crrtab[cr]; 644 cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); 645 cblue = Cbbtab[cb]; 646 /* Fetch 4 Y values and emit 4 pixels */ 647 y = GETJSAMPLE(*inptr00++); 648 r = range_limit[DITHER_565_R(y + cred, d0)]; 649 g = range_limit[DITHER_565_G(y + cgreen, d0)]; 650 b = range_limit[DITHER_565_B(y + cblue, d0)]; 651 d0 = DITHER_ROTATE(d0); 652 rgb = PACK_SHORT_565(r,g,b); 653 y = GETJSAMPLE(*inptr00++); 654 r = range_limit[DITHER_565_R(y + cred, d1)]; 655 g = range_limit[DITHER_565_G(y + cgreen, d1)]; 656 b = range_limit[DITHER_565_B(y + cblue, d1)]; 657 d1 = DITHER_ROTATE(d1); 658 rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r,g,b)); 659 WRITE_TWO_PIXELS(outptr0, rgb); 660 outptr0 += 4; 661 y = GETJSAMPLE(*inptr01++); 662 r = range_limit[DITHER_565_R(y + cred, d0)]; 663 g = range_limit[DITHER_565_G(y + cgreen, d0)]; 664 b = range_limit[DITHER_565_B(y + cblue, d0)]; 665 d0 = DITHER_ROTATE(d0); 666 rgb = PACK_SHORT_565(r,g,b); 667 y = GETJSAMPLE(*inptr01++); 668 r = range_limit[DITHER_565_R(y + cred, d1)]; 669 g = range_limit[DITHER_565_G(y + cgreen, d1)]; 670 b = range_limit[DITHER_565_B(y + cblue, d1)]; 671 d1 = DITHER_ROTATE(d1); 672 rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r,g,b)); 673 WRITE_TWO_PIXELS(outptr1, rgb); 674 outptr1 += 4; 675 } 676 /* If image width is odd, do the last output column separately */ 677 if (cinfo->output_width & 1) { 678 cb = GETJSAMPLE(*inptr1); 679 cr = GETJSAMPLE(*inptr2); 680 cred = Crrtab[cr]; 681 cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS); 682 cblue = Cbbtab[cb]; 683 y = GETJSAMPLE(*inptr00); 684 r = range_limit[DITHER_565_R(y + cred, d0)]; 685 g = range_limit[DITHER_565_G(y + cgreen, d0)]; 686 b = range_limit[DITHER_565_B(y + cblue, d0)]; 687 rgb = PACK_SHORT_565(r,g,b); 688 *(INT16*)outptr0 = rgb; 689 y = GETJSAMPLE(*inptr01); 690 r = range_limit[DITHER_565_R(y + cred, d1)]; 691 g = range_limit[DITHER_565_G(y + cgreen, d1)]; 692 b = range_limit[DITHER_565_B(y + cblue, d1)]; 693 rgb = PACK_SHORT_565(r,g,b); 694 *(INT16*)outptr1 = rgb; 695 } 696 } 697 698 #endif 699 700 /* 701 * Module initialization routine for merged upsampling/color conversion. 702 * 703 * NB: this is called under the conditions determined by use_merged_upsample() 704 * in jdmaster.c. That routine MUST correspond to the actual capabilities 705 * of this module; no safety checks are made here. 706 */ 707 708 GLOBAL(void) 709 jinit_merged_upsampler (j_decompress_ptr cinfo) 710 { 711 my_upsample_ptr upsample; 712 713 upsample = (my_upsample_ptr) 714 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 715 SIZEOF(my_upsampler)); 716 cinfo->upsample = (struct jpeg_upsampler *) upsample; 717 upsample->pub.start_pass = start_pass_merged_upsample; 718 upsample->pub.need_context_rows = FALSE; 719 720 upsample->out_row_width = cinfo->output_width * cinfo->out_color_components; 721 722 if (cinfo->max_v_samp_factor == 2) { 723 upsample->pub.upsample = merged_2v_upsample; 724 upsample->upmethod = h2v2_merged_upsample; 725 #ifdef ANDROID_RGB 726 if (cinfo->out_color_space == JCS_RGB_565) { 727 if (cinfo->dither_mode == JDITHER_NONE) { 728 upsample->upmethod = h2v2_merged_upsample_565; 729 } else { 730 upsample->upmethod = h2v2_merged_upsample_565D; 731 } 732 } 733 #endif 734 /* Allocate a spare row buffer */ 735 upsample->spare_row = (JSAMPROW) 736 (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, 737 (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE))); 738 } else { 739 upsample->pub.upsample = merged_1v_upsample; 740 upsample->upmethod = h2v1_merged_upsample; 741 #ifdef ANDROID_RGB 742 if (cinfo->out_color_space == JCS_RGB_565) { 743 if (cinfo->dither_mode == JDITHER_NONE) { 744 upsample->upmethod = h2v1_merged_upsample_565; 745 } else { 746 upsample->upmethod = h2v1_merged_upsample_565D; 747 } 748 } 749 #endif 750 /* No spare row needed */ 751 upsample->spare_row = NULL; 752 } 753 754 build_ycc_rgb_table(cinfo); 755 } 756 757 #endif /* UPSAMPLE_MERGING_SUPPORTED */ 758