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