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