1 /* 2 * jdcolor.c 3 * 4 * Copyright (C) 1991-1997, 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 output colorspace conversion routines. 9 */ 10 11 #define JPEG_INTERNALS 12 #include "jinclude.h" 13 #include "jpeglib.h" 14 15 16 /* Private subobject */ 17 18 typedef struct { 19 struct jpeg_color_deconverter pub; /* public fields */ 20 21 /* Private state for YCC->RGB conversion */ 22 int * Cr_r_tab; /* => table for Cr to R conversion */ 23 int * Cb_b_tab; /* => table for Cb to B conversion */ 24 INT32 * Cr_g_tab; /* => table for Cr to G conversion */ 25 INT32 * Cb_g_tab; /* => table for Cb to G conversion */ 26 } my_color_deconverter; 27 28 typedef my_color_deconverter * my_cconvert_ptr; 29 30 31 #ifdef ANDROID_RGB 32 33 /* Declarations for ordered dithering. 34 * 35 * We use 4x4 ordered dither array packed into 32 bits. This array is 36 * sufficent for dithering RGB_888 to RGB_565. 37 */ 38 39 #define DITHER_MASK 0x3 40 #define DITHER_ROTATE(x) (((x)<<24) | (((x)>>8)&0x00FFFFFF)) 41 static const INT32 dither_matrix[4] = { 42 0x0008020A, 43 0x0C040E06, 44 0x030B0109, 45 0x0F070D05 46 }; 47 48 #endif 49 50 51 /**************** YCbCr -> RGB conversion: most common case **************/ 52 53 /* 54 * YCbCr is defined per CCIR 601-1, except that Cb and Cr are 55 * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. 56 * The conversion equations to be implemented are therefore 57 * R = Y + 1.40200 * Cr 58 * G = Y - 0.34414 * Cb - 0.71414 * Cr 59 * B = Y + 1.77200 * Cb 60 * where Cb and Cr represent the incoming values less CENTERJSAMPLE. 61 * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) 62 * 63 * To avoid floating-point arithmetic, we represent the fractional constants 64 * as integers scaled up by 2^16 (about 4 digits precision); we have to divide 65 * the products by 2^16, with appropriate rounding, to get the correct answer. 66 * Notice that Y, being an integral input, does not contribute any fraction 67 * so it need not participate in the rounding. 68 * 69 * For even more speed, we avoid doing any multiplications in the inner loop 70 * by precalculating the constants times Cb and Cr for all possible values. 71 * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); 72 * for 12-bit samples it is still acceptable. It's not very reasonable for 73 * 16-bit samples, but if you want lossless storage you shouldn't be changing 74 * colorspace anyway. 75 * The Cr=>R and Cb=>B values can be rounded to integers in advance; the 76 * values for the G calculation are left scaled up, since we must add them 77 * together before rounding. 78 */ 79 80 #define SCALEBITS 16 /* speediest right-shift on some machines */ 81 #define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) 82 #define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5)) 83 84 85 /* 86 * Initialize tables for YCC->RGB colorspace conversion. 87 */ 88 89 LOCAL(void) 90 build_ycc_rgb_table (j_decompress_ptr cinfo) 91 { 92 my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; 93 int i; 94 INT32 x; 95 SHIFT_TEMPS 96 97 cconvert->Cr_r_tab = (int *) 98 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 99 (MAXJSAMPLE+1) * SIZEOF(int)); 100 cconvert->Cb_b_tab = (int *) 101 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 102 (MAXJSAMPLE+1) * SIZEOF(int)); 103 cconvert->Cr_g_tab = (INT32 *) 104 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 105 (MAXJSAMPLE+1) * SIZEOF(INT32)); 106 cconvert->Cb_g_tab = (INT32 *) 107 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 108 (MAXJSAMPLE+1) * SIZEOF(INT32)); 109 110 for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { 111 /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ 112 /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ 113 /* Cr=>R value is nearest int to 1.40200 * x */ 114 cconvert->Cr_r_tab[i] = (int) 115 RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); 116 /* Cb=>B value is nearest int to 1.77200 * x */ 117 cconvert->Cb_b_tab[i] = (int) 118 RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); 119 /* Cr=>G value is scaled-up -0.71414 * x */ 120 cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x; 121 /* Cb=>G value is scaled-up -0.34414 * x */ 122 /* We also add in ONE_HALF so that need not do it in inner loop */ 123 cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; 124 } 125 } 126 127 /* 128 * Convert some rows of samples to the output colorspace. 129 * 130 * Note that we change from noninterleaved, one-plane-per-component format 131 * to interleaved-pixel format. The output buffer is therefore three times 132 * as wide as the input buffer. 133 * A starting row offset is provided only for the input buffer. The caller 134 * can easily adjust the passed output_buf value to accommodate any row 135 * offset required on that side. 136 */ 137 138 METHODDEF(void) 139 ycc_rgb_convert (j_decompress_ptr cinfo, 140 JSAMPIMAGE input_buf, JDIMENSION input_row, 141 JSAMPARRAY output_buf, int num_rows) 142 { 143 my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; 144 register int y, cb, cr; 145 register JSAMPROW outptr; 146 register JSAMPROW inptr0, inptr1, inptr2; 147 register JDIMENSION col; 148 JDIMENSION num_cols = cinfo->output_width; 149 /* copy these pointers into registers if possible */ 150 register JSAMPLE * range_limit = cinfo->sample_range_limit; 151 register int * Crrtab = cconvert->Cr_r_tab; 152 register int * Cbbtab = cconvert->Cb_b_tab; 153 register INT32 * Crgtab = cconvert->Cr_g_tab; 154 register INT32 * Cbgtab = cconvert->Cb_g_tab; 155 SHIFT_TEMPS 156 157 while (--num_rows >= 0) { 158 inptr0 = input_buf[0][input_row]; 159 inptr1 = input_buf[1][input_row]; 160 inptr2 = input_buf[2][input_row]; 161 input_row++; 162 outptr = *output_buf++; 163 for (col = 0; col < num_cols; col++) { 164 y = GETJSAMPLE(inptr0[col]); 165 cb = GETJSAMPLE(inptr1[col]); 166 cr = GETJSAMPLE(inptr2[col]); 167 /* Range-limiting is essential due to noise introduced by DCT losses. */ 168 outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; 169 outptr[RGB_GREEN] = range_limit[y + 170 ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], 171 SCALEBITS))]; 172 outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; 173 outptr += RGB_PIXELSIZE; 174 } 175 } 176 } 177 178 #ifdef ANDROID_RGB 179 METHODDEF(void) 180 ycc_rgba_8888_convert (j_decompress_ptr cinfo, 181 JSAMPIMAGE input_buf, JDIMENSION input_row, 182 JSAMPARRAY output_buf, int num_rows) 183 { 184 my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; 185 register int y, cb, cr; 186 register JSAMPROW outptr; 187 register JSAMPROW inptr0, inptr1, inptr2; 188 register JDIMENSION col; 189 JDIMENSION num_cols = cinfo->output_width; 190 /* copy these pointers into registers if possible */ 191 register JSAMPLE * range_limit = cinfo->sample_range_limit; 192 register int * Crrtab = cconvert->Cr_r_tab; 193 register int * Cbbtab = cconvert->Cb_b_tab; 194 register INT32 * Crgtab = cconvert->Cr_g_tab; 195 register INT32 * Cbgtab = cconvert->Cb_g_tab; 196 SHIFT_TEMPS 197 198 while (--num_rows >= 0) { 199 inptr0 = input_buf[0][input_row]; 200 inptr1 = input_buf[1][input_row]; 201 inptr2 = input_buf[2][input_row]; 202 input_row++; 203 outptr = *output_buf++; 204 for (col = 0; col < num_cols; col++) { 205 y = GETJSAMPLE(inptr0[col]); 206 cb = GETJSAMPLE(inptr1[col]); 207 cr = GETJSAMPLE(inptr2[col]); 208 /* Range-limiting is essential due to noise introduced by DCT losses. */ 209 outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; 210 outptr[RGB_GREEN] = range_limit[y + 211 ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], 212 SCALEBITS))]; 213 outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; 214 outptr[RGB_ALPHA] = 0xFF; 215 outptr += 4; 216 } 217 } 218 } 219 220 METHODDEF(void) 221 ycc_rgb_565_convert (j_decompress_ptr cinfo, 222 JSAMPIMAGE input_buf, JDIMENSION input_row, 223 JSAMPARRAY output_buf, int num_rows) 224 { 225 my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; 226 register int y, cb, cr; 227 register JSAMPROW outptr; 228 register JSAMPROW inptr0, inptr1, inptr2; 229 register JDIMENSION col; 230 JDIMENSION num_cols = cinfo->output_width; 231 /* copy these pointers into registers if possible */ 232 register JSAMPLE * range_limit = cinfo->sample_range_limit; 233 register int * Crrtab = cconvert->Cr_r_tab; 234 register int * Cbbtab = cconvert->Cb_b_tab; 235 register INT32 * Crgtab = cconvert->Cr_g_tab; 236 register INT32 * Cbgtab = cconvert->Cb_g_tab; 237 SHIFT_TEMPS 238 239 while (--num_rows >= 0) { 240 INT32 rgb; 241 unsigned int r, g, b; 242 inptr0 = input_buf[0][input_row]; 243 inptr1 = input_buf[1][input_row]; 244 inptr2 = input_buf[2][input_row]; 245 input_row++; 246 outptr = *output_buf++; 247 248 if (PACK_NEED_ALIGNMENT(outptr)) { 249 y = GETJSAMPLE(*inptr0++); 250 cb = GETJSAMPLE(*inptr1++); 251 cr = GETJSAMPLE(*inptr2++); 252 r = range_limit[y + Crrtab[cr]]; 253 g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb]+Crgtab[cr], SCALEBITS))]; 254 b = range_limit[y + Cbbtab[cb]]; 255 rgb = PACK_SHORT_565(r,g,b); 256 *(INT16*)outptr = rgb; 257 outptr += 2; 258 num_cols--; 259 } 260 for (col = 0; col < (num_cols>>1); col++) { 261 y = GETJSAMPLE(*inptr0++); 262 cb = GETJSAMPLE(*inptr1++); 263 cr = GETJSAMPLE(*inptr2++); 264 r = range_limit[y + Crrtab[cr]]; 265 g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb]+Crgtab[cr], SCALEBITS))]; 266 b = range_limit[y + Cbbtab[cb]]; 267 rgb = PACK_SHORT_565(r,g,b); 268 269 y = GETJSAMPLE(*inptr0++); 270 cb = GETJSAMPLE(*inptr1++); 271 cr = GETJSAMPLE(*inptr2++); 272 r = range_limit[y + Crrtab[cr]]; 273 g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb]+Crgtab[cr], SCALEBITS))]; 274 b = range_limit[y + Cbbtab[cb]]; 275 rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r,g,b)); 276 WRITE_TWO_ALIGNED_PIXELS(outptr, rgb); 277 outptr += 4; 278 } 279 if (num_cols&1) { 280 y = GETJSAMPLE(*inptr0); 281 cb = GETJSAMPLE(*inptr1); 282 cr = GETJSAMPLE(*inptr2); 283 r = range_limit[y + Crrtab[cr]]; 284 g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb]+Crgtab[cr], SCALEBITS))]; 285 b = range_limit[y + Cbbtab[cb]]; 286 rgb = PACK_SHORT_565(r,g,b); 287 *(INT16*)outptr = rgb; 288 } 289 } 290 } 291 292 METHODDEF(void) 293 ycc_rgb_565D_convert (j_decompress_ptr cinfo, 294 JSAMPIMAGE input_buf, JDIMENSION input_row, 295 JSAMPARRAY output_buf, int num_rows) 296 { 297 my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; 298 register int y, cb, cr; 299 register JSAMPROW outptr; 300 register JSAMPROW inptr0, inptr1, inptr2; 301 register JDIMENSION col; 302 JDIMENSION num_cols = cinfo->output_width; 303 /* copy these pointers into registers if possible */ 304 register JSAMPLE * range_limit = cinfo->sample_range_limit; 305 register int * Crrtab = cconvert->Cr_r_tab; 306 register int * Cbbtab = cconvert->Cb_b_tab; 307 register INT32 * Crgtab = cconvert->Cr_g_tab; 308 register INT32 * Cbgtab = cconvert->Cb_g_tab; 309 INT32 d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK]; 310 SHIFT_TEMPS 311 312 while (--num_rows >= 0) { 313 INT32 rgb; 314 unsigned int r, g, b; 315 inptr0 = input_buf[0][input_row]; 316 inptr1 = input_buf[1][input_row]; 317 inptr2 = input_buf[2][input_row]; 318 input_row++; 319 outptr = *output_buf++; 320 if (PACK_NEED_ALIGNMENT(outptr)) { 321 y = GETJSAMPLE(*inptr0++); 322 cb = GETJSAMPLE(*inptr1++); 323 cr = GETJSAMPLE(*inptr2++); 324 r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)]; 325 g = range_limit[DITHER_565_G(y + ((int)RIGHT_SHIFT(Cbgtab[cb]+Crgtab[cr], SCALEBITS)), d0)]; 326 b = range_limit[DITHER_565_B(y + Cbbtab[cb], d0)]; 327 rgb = PACK_SHORT_565(r,g,b); 328 *(INT16*)outptr = rgb; 329 outptr += 2; 330 num_cols--; 331 } 332 for (col = 0; col < (num_cols>>1); col++) { 333 y = GETJSAMPLE(*inptr0++); 334 cb = GETJSAMPLE(*inptr1++); 335 cr = GETJSAMPLE(*inptr2++); 336 r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)]; 337 g = range_limit[DITHER_565_G(y + ((int)RIGHT_SHIFT(Cbgtab[cb]+Crgtab[cr], SCALEBITS)), d0)]; 338 b = range_limit[DITHER_565_B(y + Cbbtab[cb], d0)]; 339 d0 = DITHER_ROTATE(d0); 340 rgb = PACK_SHORT_565(r,g,b); 341 y = GETJSAMPLE(*inptr0++); 342 cb = GETJSAMPLE(*inptr1++); 343 cr = GETJSAMPLE(*inptr2++); 344 r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)]; 345 g = range_limit[DITHER_565_G(y + ((int)RIGHT_SHIFT(Cbgtab[cb]+Crgtab[cr], SCALEBITS)), d0)]; 346 b = range_limit[DITHER_565_B(y + Cbbtab[cb], d0)]; 347 d0 = DITHER_ROTATE(d0); 348 rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r,g,b)); 349 WRITE_TWO_ALIGNED_PIXELS(outptr, rgb); 350 outptr += 4; 351 } 352 if (num_cols&1) { 353 y = GETJSAMPLE(*inptr0); 354 cb = GETJSAMPLE(*inptr1); 355 cr = GETJSAMPLE(*inptr2); 356 r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)]; 357 g = range_limit[DITHER_565_G(y + ((int)RIGHT_SHIFT(Cbgtab[cb]+Crgtab[cr], SCALEBITS)), d0)]; 358 b = range_limit[DITHER_565_B(y + Cbbtab[cb], d0)]; 359 rgb = PACK_SHORT_565(r,g,b); 360 *(INT16*)outptr = rgb; 361 } 362 } 363 } 364 365 #endif 366 367 /**************** Cases other than YCbCr -> RGB(A) **************/ 368 369 #ifdef ANDROID_RGB 370 METHODDEF(void) 371 rgb_rgba_8888_convert (j_decompress_ptr cinfo, 372 JSAMPIMAGE input_buf, JDIMENSION input_row, 373 JSAMPARRAY output_buf, int num_rows) 374 { 375 register JSAMPROW outptr; 376 register JSAMPROW inptr0, inptr1, inptr2; 377 register JDIMENSION col; 378 JDIMENSION num_cols = cinfo->output_width; 379 SHIFT_TEMPS 380 381 while (--num_rows >= 0) { 382 inptr0 = input_buf[0][input_row]; 383 inptr1 = input_buf[1][input_row]; 384 inptr2 = input_buf[2][input_row]; 385 input_row++; 386 outptr = *output_buf++; 387 for (col = 0; col < num_cols; col++) { 388 *outptr++ = *inptr0++; 389 *outptr++ = *inptr1++; 390 *outptr++ = *inptr2++; 391 *outptr++ = 0xFF; 392 } 393 } 394 } 395 396 METHODDEF(void) 397 rgb_rgb_565_convert (j_decompress_ptr cinfo, 398 JSAMPIMAGE input_buf, JDIMENSION input_row, 399 JSAMPARRAY output_buf, int num_rows) 400 { 401 register JSAMPROW outptr; 402 register JSAMPROW inptr0, inptr1, inptr2; 403 register JDIMENSION col; 404 JDIMENSION num_cols = cinfo->output_width; 405 SHIFT_TEMPS 406 407 while (--num_rows >= 0) { 408 INT32 rgb; 409 unsigned int r, g, b; 410 inptr0 = input_buf[0][input_row]; 411 inptr1 = input_buf[1][input_row]; 412 inptr2 = input_buf[2][input_row]; 413 input_row++; 414 outptr = *output_buf++; 415 if (PACK_NEED_ALIGNMENT(outptr)) { 416 r = GETJSAMPLE(*inptr0++); 417 g = GETJSAMPLE(*inptr1++); 418 b = GETJSAMPLE(*inptr2++); 419 rgb = PACK_SHORT_565(r,g,b); 420 *(INT16*)outptr = rgb; 421 outptr += 2; 422 num_cols--; 423 } 424 for (col = 0; col < (num_cols>>1); col++) { 425 r = GETJSAMPLE(*inptr0++); 426 g = GETJSAMPLE(*inptr1++); 427 b = GETJSAMPLE(*inptr2++); 428 rgb = PACK_SHORT_565(r,g,b); 429 r = GETJSAMPLE(*inptr0++); 430 g = GETJSAMPLE(*inptr1++); 431 b = GETJSAMPLE(*inptr2++); 432 rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r,g,b)); 433 WRITE_TWO_ALIGNED_PIXELS(outptr, rgb); 434 outptr += 4; 435 } 436 if (num_cols&1) { 437 r = GETJSAMPLE(*inptr0); 438 g = GETJSAMPLE(*inptr1); 439 b = GETJSAMPLE(*inptr2); 440 rgb = PACK_SHORT_565(r,g,b); 441 *(INT16*)outptr = rgb; 442 } 443 } 444 } 445 446 447 METHODDEF(void) 448 rgb_rgb_565D_convert (j_decompress_ptr cinfo, 449 JSAMPIMAGE input_buf, JDIMENSION input_row, 450 JSAMPARRAY output_buf, int num_rows) 451 { 452 register JSAMPROW outptr; 453 register JSAMPROW inptr0, inptr1, inptr2; 454 register JDIMENSION col; 455 register JSAMPLE * range_limit = cinfo->sample_range_limit; 456 JDIMENSION num_cols = cinfo->output_width; 457 INT32 d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK]; 458 SHIFT_TEMPS 459 460 while (--num_rows >= 0) { 461 INT32 rgb; 462 unsigned int r, g, b; 463 inptr0 = input_buf[0][input_row]; 464 inptr1 = input_buf[1][input_row]; 465 inptr2 = input_buf[2][input_row]; 466 input_row++; 467 outptr = *output_buf++; 468 if (PACK_NEED_ALIGNMENT(outptr)) { 469 r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0++), d0)]; 470 g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1++), d0)]; 471 b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2++), d0)]; 472 rgb = PACK_SHORT_565(r,g,b); 473 *(INT16*)outptr = rgb; 474 outptr += 2; 475 num_cols--; 476 } 477 for (col = 0; col < (num_cols>>1); col++) { 478 r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0++), d0)]; 479 g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1++), d0)]; 480 b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2++), d0)]; 481 d0 = DITHER_ROTATE(d0); 482 rgb = PACK_SHORT_565(r,g,b); 483 r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0++), d0)]; 484 g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1++), d0)]; 485 b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2++), d0)]; 486 d0 = DITHER_ROTATE(d0); 487 rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r,g,b)); 488 WRITE_TWO_ALIGNED_PIXELS(outptr, rgb); 489 outptr += 4; 490 } 491 if (num_cols&1) { 492 r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0), d0)]; 493 g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1), d0)]; 494 b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2), d0)]; 495 rgb = PACK_SHORT_565(r,g,b); 496 *(INT16*)outptr = rgb; 497 } 498 } 499 } 500 501 #endif 502 503 /* 504 * Color conversion for no colorspace change: just copy the data, 505 * converting from separate-planes to interleaved representation. 506 */ 507 508 METHODDEF(void) 509 null_convert (j_decompress_ptr cinfo, 510 JSAMPIMAGE input_buf, JDIMENSION input_row, 511 JSAMPARRAY output_buf, int num_rows) 512 { 513 register JSAMPROW inptr, outptr; 514 register JDIMENSION count; 515 register int num_components = cinfo->num_components; 516 JDIMENSION num_cols = cinfo->output_width; 517 int ci; 518 519 while (--num_rows >= 0) { 520 for (ci = 0; ci < num_components; ci++) { 521 inptr = input_buf[ci][input_row]; 522 outptr = output_buf[0] + ci; 523 for (count = num_cols; count > 0; count--) { 524 *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */ 525 outptr += num_components; 526 } 527 } 528 input_row++; 529 output_buf++; 530 } 531 } 532 533 534 /* 535 * Color conversion for grayscale: just copy the data. 536 * This also works for YCbCr -> grayscale conversion, in which 537 * we just copy the Y (luminance) component and ignore chrominance. 538 */ 539 540 METHODDEF(void) 541 grayscale_convert (j_decompress_ptr cinfo, 542 JSAMPIMAGE input_buf, JDIMENSION input_row, 543 JSAMPARRAY output_buf, int num_rows) 544 { 545 jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0, 546 num_rows, cinfo->output_width); 547 } 548 549 550 /* 551 * Convert grayscale to RGB: just duplicate the graylevel three times. 552 * This is provided to support applications that don't want to cope 553 * with grayscale as a separate case. 554 */ 555 556 METHODDEF(void) 557 gray_rgb_convert (j_decompress_ptr cinfo, 558 JSAMPIMAGE input_buf, JDIMENSION input_row, 559 JSAMPARRAY output_buf, int num_rows) 560 { 561 register JSAMPROW inptr, outptr; 562 register JDIMENSION col; 563 JDIMENSION num_cols = cinfo->output_width; 564 565 while (--num_rows >= 0) { 566 inptr = input_buf[0][input_row++]; 567 outptr = *output_buf++; 568 for (col = 0; col < num_cols; col++) { 569 /* We can dispense with GETJSAMPLE() here */ 570 outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col]; 571 outptr += RGB_PIXELSIZE; 572 } 573 } 574 } 575 576 #ifdef ANDROID_RGB 577 METHODDEF(void) 578 gray_rgba_8888_convert (j_decompress_ptr cinfo, 579 JSAMPIMAGE input_buf, JDIMENSION input_row, 580 JSAMPARRAY output_buf, int num_rows) 581 { 582 register JSAMPROW inptr, outptr; 583 register JDIMENSION col; 584 JDIMENSION num_cols = cinfo->output_width; 585 586 while (--num_rows >= 0) { 587 inptr = input_buf[0][input_row++]; 588 outptr = *output_buf++; 589 for (col = 0; col < num_cols; col++) { 590 /* We can dispense with GETJSAMPLE() here */ 591 outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col]; 592 outptr[RGB_ALPHA] = 0xff; 593 outptr += 4; 594 } 595 } 596 } 597 598 METHODDEF(void) 599 gray_rgb_565_convert (j_decompress_ptr cinfo, 600 JSAMPIMAGE input_buf, JDIMENSION input_row, 601 JSAMPARRAY output_buf, int num_rows) 602 { 603 register JSAMPROW inptr, outptr; 604 register JDIMENSION col; 605 JDIMENSION num_cols = cinfo->output_width; 606 607 while (--num_rows >= 0) { 608 INT32 rgb; 609 unsigned int g; 610 inptr = input_buf[0][input_row++]; 611 outptr = *output_buf++; 612 if (PACK_NEED_ALIGNMENT(outptr)) { 613 g = *inptr++; 614 rgb = PACK_SHORT_565(g, g, g); 615 *(INT16*)outptr = rgb; 616 outptr += 2; 617 num_cols--; 618 } 619 for (col = 0; col < (num_cols>>1); col++) { 620 g = *inptr++; 621 rgb = PACK_SHORT_565(g, g, g); 622 g = *inptr++; 623 rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(g, g, g)); 624 WRITE_TWO_ALIGNED_PIXELS(outptr, rgb); 625 outptr += 4; 626 } 627 if (num_cols&1) { 628 g = *inptr; 629 rgb = PACK_SHORT_565(g, g, g); 630 *(INT16*)outptr = rgb; 631 } 632 } 633 } 634 635 METHODDEF(void) 636 gray_rgb_565D_convert (j_decompress_ptr cinfo, 637 JSAMPIMAGE input_buf, JDIMENSION input_row, 638 JSAMPARRAY output_buf, int num_rows) 639 { 640 register JSAMPROW inptr, outptr; 641 register JDIMENSION col; 642 register JSAMPLE * range_limit = cinfo->sample_range_limit; 643 JDIMENSION num_cols = cinfo->output_width; 644 INT32 d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK]; 645 646 while (--num_rows >= 0) { 647 INT32 rgb; 648 unsigned int g; 649 inptr = input_buf[0][input_row++]; 650 outptr = *output_buf++; 651 if (PACK_NEED_ALIGNMENT(outptr)) { 652 g = *inptr++; 653 g = range_limit[DITHER_565_R(g, d0)]; 654 rgb = PACK_SHORT_565(g, g, g); 655 *(INT16*)outptr = rgb; 656 outptr += 2; 657 num_cols--; 658 } 659 for (col = 0; col < (num_cols>>1); col++) { 660 g = *inptr++; 661 g = range_limit[DITHER_565_R(g, d0)]; 662 rgb = PACK_SHORT_565(g, g, g); 663 d0 = DITHER_ROTATE(d0); 664 g = *inptr++; 665 g = range_limit[DITHER_565_R(g, d0)]; 666 rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(g, g, g)); 667 d0 = DITHER_ROTATE(d0); 668 WRITE_TWO_ALIGNED_PIXELS(outptr, rgb); 669 outptr += 4; 670 } 671 if (num_cols&1) { 672 g = *inptr; 673 g = range_limit[DITHER_565_R(g, d0)]; 674 rgb = PACK_SHORT_565(g, g, g); 675 *(INT16*)outptr = rgb; 676 } 677 } 678 } 679 #endif 680 681 /* 682 * Adobe-style YCCK->CMYK conversion. 683 * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same 684 * conversion as above, while passing K (black) unchanged. 685 * We assume build_ycc_rgb_table has been called. 686 */ 687 688 METHODDEF(void) 689 ycck_cmyk_convert (j_decompress_ptr cinfo, 690 JSAMPIMAGE input_buf, JDIMENSION input_row, 691 JSAMPARRAY output_buf, int num_rows) 692 { 693 my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; 694 register int y, cb, cr; 695 register JSAMPROW outptr; 696 register JSAMPROW inptr0, inptr1, inptr2, inptr3; 697 register JDIMENSION col; 698 JDIMENSION num_cols = cinfo->output_width; 699 /* copy these pointers into registers if possible */ 700 register JSAMPLE * range_limit = cinfo->sample_range_limit; 701 register int * Crrtab = cconvert->Cr_r_tab; 702 register int * Cbbtab = cconvert->Cb_b_tab; 703 register INT32 * Crgtab = cconvert->Cr_g_tab; 704 register INT32 * Cbgtab = cconvert->Cb_g_tab; 705 SHIFT_TEMPS 706 707 while (--num_rows >= 0) { 708 inptr0 = input_buf[0][input_row]; 709 inptr1 = input_buf[1][input_row]; 710 inptr2 = input_buf[2][input_row]; 711 inptr3 = input_buf[3][input_row]; 712 input_row++; 713 outptr = *output_buf++; 714 for (col = 0; col < num_cols; col++) { 715 y = GETJSAMPLE(inptr0[col]); 716 cb = GETJSAMPLE(inptr1[col]); 717 cr = GETJSAMPLE(inptr2[col]); 718 /* Range-limiting is essential due to noise introduced by DCT losses. */ 719 outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ 720 outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ 721 ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], 722 SCALEBITS)))]; 723 outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ 724 /* K passes through unchanged */ 725 outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */ 726 outptr += 4; 727 } 728 } 729 } 730 731 732 /* 733 * Empty method for start_pass. 734 */ 735 736 METHODDEF(void) 737 start_pass_dcolor (j_decompress_ptr cinfo) 738 { 739 /* no work needed */ 740 } 741 742 743 /* 744 * Module initialization routine for output colorspace conversion. 745 */ 746 747 GLOBAL(void) 748 jinit_color_deconverter (j_decompress_ptr cinfo) 749 { 750 my_cconvert_ptr cconvert; 751 int ci; 752 753 cconvert = (my_cconvert_ptr) 754 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 755 SIZEOF(my_color_deconverter)); 756 cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert; 757 cconvert->pub.start_pass = start_pass_dcolor; 758 759 /* Make sure num_components agrees with jpeg_color_space */ 760 switch (cinfo->jpeg_color_space) { 761 case JCS_GRAYSCALE: 762 if (cinfo->num_components != 1) 763 ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); 764 break; 765 766 case JCS_RGB: 767 case JCS_YCbCr: 768 if (cinfo->num_components != 3) 769 ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); 770 break; 771 772 case JCS_CMYK: 773 case JCS_YCCK: 774 if (cinfo->num_components != 4) 775 ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); 776 break; 777 778 default: /* JCS_UNKNOWN can be anything */ 779 if (cinfo->num_components < 1) 780 ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); 781 break; 782 } 783 784 /* Set out_color_components and conversion method based on requested space. 785 * Also clear the component_needed flags for any unused components, 786 * so that earlier pipeline stages can avoid useless computation. 787 */ 788 789 switch (cinfo->out_color_space) { 790 case JCS_GRAYSCALE: 791 cinfo->out_color_components = 1; 792 if (cinfo->jpeg_color_space == JCS_GRAYSCALE || 793 cinfo->jpeg_color_space == JCS_YCbCr) { 794 cconvert->pub.color_convert = grayscale_convert; 795 /* For color->grayscale conversion, only the Y (0) component is needed */ 796 for (ci = 1; ci < cinfo->num_components; ci++) 797 cinfo->comp_info[ci].component_needed = FALSE; 798 } else 799 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 800 break; 801 802 case JCS_RGB: 803 cinfo->out_color_components = RGB_PIXELSIZE; 804 if (cinfo->jpeg_color_space == JCS_YCbCr) { 805 cconvert->pub.color_convert = ycc_rgb_convert; 806 build_ycc_rgb_table(cinfo); 807 } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { 808 cconvert->pub.color_convert = gray_rgb_convert; 809 } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) { 810 cconvert->pub.color_convert = null_convert; 811 } else 812 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 813 break; 814 815 #ifdef ANDROID_RGB 816 case JCS_RGBA_8888: 817 cinfo->out_color_components = 4; 818 if (cinfo->jpeg_color_space == JCS_YCbCr) { 819 cconvert->pub.color_convert = ycc_rgba_8888_convert; 820 build_ycc_rgb_table(cinfo); 821 } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { 822 cconvert->pub.color_convert = gray_rgba_8888_convert; 823 } else if (cinfo->jpeg_color_space == JCS_RGB) { 824 cconvert->pub.color_convert = rgb_rgba_8888_convert; 825 } else 826 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 827 break; 828 829 case JCS_RGB_565: 830 cinfo->out_color_components = RGB_PIXELSIZE; 831 if (cinfo->dither_mode == JDITHER_NONE) { 832 if (cinfo->jpeg_color_space == JCS_YCbCr) { 833 cconvert->pub.color_convert = ycc_rgb_565_convert; 834 build_ycc_rgb_table(cinfo); 835 } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { 836 cconvert->pub.color_convert = gray_rgb_565_convert; 837 } else if (cinfo->jpeg_color_space == JCS_RGB) { 838 cconvert->pub.color_convert = rgb_rgb_565_convert; 839 } else 840 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 841 } else { 842 /* only ordered dither is supported */ 843 if (cinfo->jpeg_color_space == JCS_YCbCr) { 844 cconvert->pub.color_convert = ycc_rgb_565D_convert; 845 build_ycc_rgb_table(cinfo); 846 } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { 847 cconvert->pub.color_convert = gray_rgb_565D_convert; 848 } else if (cinfo->jpeg_color_space == JCS_RGB) { 849 cconvert->pub.color_convert = rgb_rgb_565D_convert; 850 } else 851 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 852 } 853 break; 854 #endif 855 856 case JCS_CMYK: 857 cinfo->out_color_components = 4; 858 if (cinfo->jpeg_color_space == JCS_YCCK) { 859 cconvert->pub.color_convert = ycck_cmyk_convert; 860 build_ycc_rgb_table(cinfo); 861 } else if (cinfo->jpeg_color_space == JCS_CMYK) { 862 cconvert->pub.color_convert = null_convert; 863 } else 864 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 865 break; 866 867 default: 868 /* Permit null conversion to same output space */ 869 if (cinfo->out_color_space == cinfo->jpeg_color_space) { 870 cinfo->out_color_components = cinfo->num_components; 871 cconvert->pub.color_convert = null_convert; 872 } else /* unsupported non-null conversion */ 873 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 874 break; 875 } 876 877 if (cinfo->quantize_colors) 878 cinfo->output_components = 1; /* single colormapped output component */ 879 else 880 cinfo->output_components = cinfo->out_color_components; 881 } 882