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, JSAMPIMAGE input_buf, 255 JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) 256 { 257 switch (cinfo->out_color_space) { 258 case JCS_EXT_RGB: 259 ycc_extrgb_convert_internal(cinfo, input_buf, input_row, output_buf, 260 num_rows); 261 break; 262 case JCS_EXT_RGBX: 263 case JCS_EXT_RGBA: 264 ycc_extrgbx_convert_internal(cinfo, input_buf, input_row, output_buf, 265 num_rows); 266 break; 267 case JCS_EXT_BGR: 268 ycc_extbgr_convert_internal(cinfo, input_buf, input_row, output_buf, 269 num_rows); 270 break; 271 case JCS_EXT_BGRX: 272 case JCS_EXT_BGRA: 273 ycc_extbgrx_convert_internal(cinfo, input_buf, input_row, output_buf, 274 num_rows); 275 break; 276 case JCS_EXT_XBGR: 277 case JCS_EXT_ABGR: 278 ycc_extxbgr_convert_internal(cinfo, input_buf, input_row, output_buf, 279 num_rows); 280 break; 281 case JCS_EXT_XRGB: 282 case JCS_EXT_ARGB: 283 ycc_extxrgb_convert_internal(cinfo, input_buf, input_row, output_buf, 284 num_rows); 285 break; 286 default: 287 ycc_rgb_convert_internal(cinfo, input_buf, input_row, output_buf, 288 num_rows); 289 break; 290 } 291 } 292 293 294 /**************** Cases other than YCbCr -> RGB **************/ 295 296 297 /* 298 * Initialize for RGB->grayscale colorspace conversion. 299 */ 300 301 LOCAL(void) 302 build_rgb_y_table(j_decompress_ptr cinfo) 303 { 304 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; 305 JLONG *rgb_y_tab; 306 JLONG i; 307 308 /* Allocate and fill in the conversion tables. */ 309 cconvert->rgb_y_tab = rgb_y_tab = (JLONG *) 310 (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, 311 (TABLE_SIZE * sizeof(JLONG))); 312 313 for (i = 0; i <= MAXJSAMPLE; i++) { 314 rgb_y_tab[i + R_Y_OFF] = FIX(0.29900) * i; 315 rgb_y_tab[i + G_Y_OFF] = FIX(0.58700) * i; 316 rgb_y_tab[i + B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; 317 } 318 } 319 320 321 /* 322 * Convert RGB to grayscale. 323 */ 324 325 METHODDEF(void) 326 rgb_gray_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, 327 JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) 328 { 329 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; 330 register int r, g, b; 331 register JLONG *ctab = cconvert->rgb_y_tab; 332 register JSAMPROW outptr; 333 register JSAMPROW inptr0, inptr1, inptr2; 334 register JDIMENSION col; 335 JDIMENSION num_cols = cinfo->output_width; 336 337 while (--num_rows >= 0) { 338 inptr0 = input_buf[0][input_row]; 339 inptr1 = input_buf[1][input_row]; 340 inptr2 = input_buf[2][input_row]; 341 input_row++; 342 outptr = *output_buf++; 343 for (col = 0; col < num_cols; col++) { 344 r = GETJSAMPLE(inptr0[col]); 345 g = GETJSAMPLE(inptr1[col]); 346 b = GETJSAMPLE(inptr2[col]); 347 /* Y */ 348 outptr[col] = (JSAMPLE)((ctab[r + R_Y_OFF] + ctab[g + G_Y_OFF] + 349 ctab[b + B_Y_OFF]) >> SCALEBITS); 350 } 351 } 352 } 353 354 355 /* 356 * Color conversion for no colorspace change: just copy the data, 357 * converting from separate-planes to interleaved representation. 358 */ 359 360 METHODDEF(void) 361 null_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, 362 JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) 363 { 364 register JSAMPROW inptr, inptr0, inptr1, inptr2, inptr3, outptr; 365 register JDIMENSION col; 366 register int num_components = cinfo->num_components; 367 JDIMENSION num_cols = cinfo->output_width; 368 int ci; 369 370 if (num_components == 3) { 371 while (--num_rows >= 0) { 372 inptr0 = input_buf[0][input_row]; 373 inptr1 = input_buf[1][input_row]; 374 inptr2 = input_buf[2][input_row]; 375 input_row++; 376 outptr = *output_buf++; 377 for (col = 0; col < num_cols; col++) { 378 *outptr++ = inptr0[col]; 379 *outptr++ = inptr1[col]; 380 *outptr++ = inptr2[col]; 381 } 382 } 383 } else if (num_components == 4) { 384 while (--num_rows >= 0) { 385 inptr0 = input_buf[0][input_row]; 386 inptr1 = input_buf[1][input_row]; 387 inptr2 = input_buf[2][input_row]; 388 inptr3 = input_buf[3][input_row]; 389 input_row++; 390 outptr = *output_buf++; 391 for (col = 0; col < num_cols; col++) { 392 *outptr++ = inptr0[col]; 393 *outptr++ = inptr1[col]; 394 *outptr++ = inptr2[col]; 395 *outptr++ = inptr3[col]; 396 } 397 } 398 } else { 399 while (--num_rows >= 0) { 400 for (ci = 0; ci < num_components; ci++) { 401 inptr = input_buf[ci][input_row]; 402 outptr = *output_buf; 403 for (col = 0; col < num_cols; col++) { 404 outptr[ci] = inptr[col]; 405 outptr += num_components; 406 } 407 } 408 output_buf++; 409 input_row++; 410 } 411 } 412 } 413 414 415 /* 416 * Color conversion for grayscale: just copy the data. 417 * This also works for YCbCr -> grayscale conversion, in which 418 * we just copy the Y (luminance) component and ignore chrominance. 419 */ 420 421 METHODDEF(void) 422 grayscale_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, 423 JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) 424 { 425 jcopy_sample_rows(input_buf[0], (int)input_row, output_buf, 0, num_rows, 426 cinfo->output_width); 427 } 428 429 430 /* 431 * Convert grayscale to RGB 432 */ 433 434 METHODDEF(void) 435 gray_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, 436 JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) 437 { 438 switch (cinfo->out_color_space) { 439 case JCS_EXT_RGB: 440 gray_extrgb_convert_internal(cinfo, input_buf, input_row, output_buf, 441 num_rows); 442 break; 443 case JCS_EXT_RGBX: 444 case JCS_EXT_RGBA: 445 gray_extrgbx_convert_internal(cinfo, input_buf, input_row, output_buf, 446 num_rows); 447 break; 448 case JCS_EXT_BGR: 449 gray_extbgr_convert_internal(cinfo, input_buf, input_row, output_buf, 450 num_rows); 451 break; 452 case JCS_EXT_BGRX: 453 case JCS_EXT_BGRA: 454 gray_extbgrx_convert_internal(cinfo, input_buf, input_row, output_buf, 455 num_rows); 456 break; 457 case JCS_EXT_XBGR: 458 case JCS_EXT_ABGR: 459 gray_extxbgr_convert_internal(cinfo, input_buf, input_row, output_buf, 460 num_rows); 461 break; 462 case JCS_EXT_XRGB: 463 case JCS_EXT_ARGB: 464 gray_extxrgb_convert_internal(cinfo, input_buf, input_row, output_buf, 465 num_rows); 466 break; 467 default: 468 gray_rgb_convert_internal(cinfo, input_buf, input_row, output_buf, 469 num_rows); 470 break; 471 } 472 } 473 474 475 /* 476 * Convert plain RGB to extended RGB 477 */ 478 479 METHODDEF(void) 480 rgb_rgb_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, 481 JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) 482 { 483 switch (cinfo->out_color_space) { 484 case JCS_EXT_RGB: 485 rgb_extrgb_convert_internal(cinfo, input_buf, input_row, output_buf, 486 num_rows); 487 break; 488 case JCS_EXT_RGBX: 489 case JCS_EXT_RGBA: 490 rgb_extrgbx_convert_internal(cinfo, input_buf, input_row, output_buf, 491 num_rows); 492 break; 493 case JCS_EXT_BGR: 494 rgb_extbgr_convert_internal(cinfo, input_buf, input_row, output_buf, 495 num_rows); 496 break; 497 case JCS_EXT_BGRX: 498 case JCS_EXT_BGRA: 499 rgb_extbgrx_convert_internal(cinfo, input_buf, input_row, output_buf, 500 num_rows); 501 break; 502 case JCS_EXT_XBGR: 503 case JCS_EXT_ABGR: 504 rgb_extxbgr_convert_internal(cinfo, input_buf, input_row, output_buf, 505 num_rows); 506 break; 507 case JCS_EXT_XRGB: 508 case JCS_EXT_ARGB: 509 rgb_extxrgb_convert_internal(cinfo, input_buf, input_row, output_buf, 510 num_rows); 511 break; 512 default: 513 rgb_rgb_convert_internal(cinfo, input_buf, input_row, output_buf, 514 num_rows); 515 break; 516 } 517 } 518 519 520 /* 521 * Adobe-style YCCK->CMYK conversion. 522 * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same 523 * conversion as above, while passing K (black) unchanged. 524 * We assume build_ycc_rgb_table has been called. 525 */ 526 527 METHODDEF(void) 528 ycck_cmyk_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, 529 JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) 530 { 531 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert; 532 register int y, cb, cr; 533 register JSAMPROW outptr; 534 register JSAMPROW inptr0, inptr1, inptr2, inptr3; 535 register JDIMENSION col; 536 JDIMENSION num_cols = cinfo->output_width; 537 /* copy these pointers into registers if possible */ 538 register JSAMPLE *range_limit = cinfo->sample_range_limit; 539 register int *Crrtab = cconvert->Cr_r_tab; 540 register int *Cbbtab = cconvert->Cb_b_tab; 541 register JLONG *Crgtab = cconvert->Cr_g_tab; 542 register JLONG *Cbgtab = cconvert->Cb_g_tab; 543 SHIFT_TEMPS 544 545 while (--num_rows >= 0) { 546 inptr0 = input_buf[0][input_row]; 547 inptr1 = input_buf[1][input_row]; 548 inptr2 = input_buf[2][input_row]; 549 inptr3 = input_buf[3][input_row]; 550 input_row++; 551 outptr = *output_buf++; 552 for (col = 0; col < num_cols; col++) { 553 y = GETJSAMPLE(inptr0[col]); 554 cb = GETJSAMPLE(inptr1[col]); 555 cr = GETJSAMPLE(inptr2[col]); 556 /* Range-limiting is essential due to noise introduced by DCT losses. */ 557 outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ 558 outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ 559 ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], 560 SCALEBITS)))]; 561 outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ 562 /* K passes through unchanged */ 563 outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */ 564 outptr += 4; 565 } 566 } 567 } 568 569 570 /* 571 * RGB565 conversion 572 */ 573 574 #define PACK_SHORT_565_LE(r, g, b) ((((r) << 8) & 0xF800) | \ 575 (((g) << 3) & 0x7E0) | ((b) >> 3)) 576 #define PACK_SHORT_565_BE(r, g, b) (((r) & 0xF8) | ((g) >> 5) | \ 577 (((g) << 11) & 0xE000) | \ 578 (((b) << 5) & 0x1F00)) 579 580 #define PACK_TWO_PIXELS_LE(l, r) ((r << 16) | l) 581 #define PACK_TWO_PIXELS_BE(l, r) ((l << 16) | r) 582 583 #define PACK_NEED_ALIGNMENT(ptr) (((size_t)(ptr)) & 3) 584 585 #define WRITE_TWO_ALIGNED_PIXELS(addr, pixels) ((*(int *)(addr)) = pixels) 586 587 #define DITHER_565_R(r, dither) ((r) + ((dither) & 0xFF)) 588 #define DITHER_565_G(g, dither) ((g) + (((dither) & 0xFF) >> 1)) 589 #define DITHER_565_B(b, dither) ((b) + ((dither) & 0xFF)) 590 591 592 /* Declarations for ordered dithering 593 * 594 * We use a 4x4 ordered dither array packed into 32 bits. This array is 595 * sufficient for dithering RGB888 to RGB565. 596 */ 597 598 #define DITHER_MASK 0x3 599 #define DITHER_ROTATE(x) ((((x) & 0xFF) << 24) | (((x) >> 8) & 0x00FFFFFF)) 600 static const JLONG dither_matrix[4] = { 601 0x0008020A, 602 0x0C040E06, 603 0x030B0109, 604 0x0F070D05 605 }; 606 607 608 static INLINE boolean is_big_endian(void) 609 { 610 int test_value = 1; 611 if (*(char *)&test_value != 1) 612 return TRUE; 613 return FALSE; 614 } 615 616 617 /* Include inline routines for RGB565 conversion */ 618 619 #define PACK_SHORT_565 PACK_SHORT_565_LE 620 #define PACK_TWO_PIXELS PACK_TWO_PIXELS_LE 621 #define ycc_rgb565_convert_internal ycc_rgb565_convert_le 622 #define ycc_rgb565D_convert_internal ycc_rgb565D_convert_le 623 #define rgb_rgb565_convert_internal rgb_rgb565_convert_le 624 #define rgb_rgb565D_convert_internal rgb_rgb565D_convert_le 625 #define gray_rgb565_convert_internal gray_rgb565_convert_le 626 #define gray_rgb565D_convert_internal gray_rgb565D_convert_le 627 #include "jdcol565.c" 628 #undef PACK_SHORT_565 629 #undef PACK_TWO_PIXELS 630 #undef ycc_rgb565_convert_internal 631 #undef ycc_rgb565D_convert_internal 632 #undef rgb_rgb565_convert_internal 633 #undef rgb_rgb565D_convert_internal 634 #undef gray_rgb565_convert_internal 635 #undef gray_rgb565D_convert_internal 636 637 #define PACK_SHORT_565 PACK_SHORT_565_BE 638 #define PACK_TWO_PIXELS PACK_TWO_PIXELS_BE 639 #define ycc_rgb565_convert_internal ycc_rgb565_convert_be 640 #define ycc_rgb565D_convert_internal ycc_rgb565D_convert_be 641 #define rgb_rgb565_convert_internal rgb_rgb565_convert_be 642 #define rgb_rgb565D_convert_internal rgb_rgb565D_convert_be 643 #define gray_rgb565_convert_internal gray_rgb565_convert_be 644 #define gray_rgb565D_convert_internal gray_rgb565D_convert_be 645 #include "jdcol565.c" 646 #undef PACK_SHORT_565 647 #undef PACK_TWO_PIXELS 648 #undef ycc_rgb565_convert_internal 649 #undef ycc_rgb565D_convert_internal 650 #undef rgb_rgb565_convert_internal 651 #undef rgb_rgb565D_convert_internal 652 #undef gray_rgb565_convert_internal 653 #undef gray_rgb565D_convert_internal 654 655 656 METHODDEF(void) 657 ycc_rgb565_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, 658 JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) 659 { 660 if (is_big_endian()) 661 ycc_rgb565_convert_be(cinfo, input_buf, input_row, output_buf, num_rows); 662 else 663 ycc_rgb565_convert_le(cinfo, input_buf, input_row, output_buf, num_rows); 664 } 665 666 667 METHODDEF(void) 668 ycc_rgb565D_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, 669 JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) 670 { 671 if (is_big_endian()) 672 ycc_rgb565D_convert_be(cinfo, input_buf, input_row, output_buf, num_rows); 673 else 674 ycc_rgb565D_convert_le(cinfo, input_buf, input_row, output_buf, num_rows); 675 } 676 677 678 METHODDEF(void) 679 rgb_rgb565_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, 680 JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) 681 { 682 if (is_big_endian()) 683 rgb_rgb565_convert_be(cinfo, input_buf, input_row, output_buf, num_rows); 684 else 685 rgb_rgb565_convert_le(cinfo, input_buf, input_row, output_buf, num_rows); 686 } 687 688 689 METHODDEF(void) 690 rgb_rgb565D_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, 691 JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) 692 { 693 if (is_big_endian()) 694 rgb_rgb565D_convert_be(cinfo, input_buf, input_row, output_buf, num_rows); 695 else 696 rgb_rgb565D_convert_le(cinfo, input_buf, input_row, output_buf, num_rows); 697 } 698 699 700 METHODDEF(void) 701 gray_rgb565_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, 702 JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) 703 { 704 if (is_big_endian()) 705 gray_rgb565_convert_be(cinfo, input_buf, input_row, output_buf, num_rows); 706 else 707 gray_rgb565_convert_le(cinfo, input_buf, input_row, output_buf, num_rows); 708 } 709 710 711 METHODDEF(void) 712 gray_rgb565D_convert(j_decompress_ptr cinfo, JSAMPIMAGE input_buf, 713 JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) 714 { 715 if (is_big_endian()) 716 gray_rgb565D_convert_be(cinfo, input_buf, input_row, output_buf, num_rows); 717 else 718 gray_rgb565D_convert_le(cinfo, input_buf, input_row, output_buf, num_rows); 719 } 720 721 722 /* 723 * Empty method for start_pass. 724 */ 725 726 METHODDEF(void) 727 start_pass_dcolor(j_decompress_ptr cinfo) 728 { 729 /* no work needed */ 730 } 731 732 733 /* 734 * Module initialization routine for output colorspace conversion. 735 */ 736 737 GLOBAL(void) 738 jinit_color_deconverter(j_decompress_ptr cinfo) 739 { 740 my_cconvert_ptr cconvert; 741 int ci; 742 743 cconvert = (my_cconvert_ptr) 744 (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, 745 sizeof(my_color_deconverter)); 746 cinfo->cconvert = (struct jpeg_color_deconverter *)cconvert; 747 cconvert->pub.start_pass = start_pass_dcolor; 748 749 /* Make sure num_components agrees with jpeg_color_space */ 750 switch (cinfo->jpeg_color_space) { 751 case JCS_GRAYSCALE: 752 if (cinfo->num_components != 1) 753 ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); 754 break; 755 756 case JCS_RGB: 757 case JCS_YCbCr: 758 if (cinfo->num_components != 3) 759 ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); 760 break; 761 762 case JCS_CMYK: 763 case JCS_YCCK: 764 if (cinfo->num_components != 4) 765 ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); 766 break; 767 768 default: /* JCS_UNKNOWN can be anything */ 769 if (cinfo->num_components < 1) 770 ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); 771 break; 772 } 773 774 /* Set out_color_components and conversion method based on requested space. 775 * Also clear the component_needed flags for any unused components, 776 * so that earlier pipeline stages can avoid useless computation. 777 */ 778 779 switch (cinfo->out_color_space) { 780 case JCS_GRAYSCALE: 781 cinfo->out_color_components = 1; 782 if (cinfo->jpeg_color_space == JCS_GRAYSCALE || 783 cinfo->jpeg_color_space == JCS_YCbCr) { 784 cconvert->pub.color_convert = grayscale_convert; 785 /* For color->grayscale conversion, only the Y (0) component is needed */ 786 for (ci = 1; ci < cinfo->num_components; ci++) 787 cinfo->comp_info[ci].component_needed = FALSE; 788 } else if (cinfo->jpeg_color_space == JCS_RGB) { 789 cconvert->pub.color_convert = rgb_gray_convert; 790 build_rgb_y_table(cinfo); 791 } else 792 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 793 break; 794 795 case JCS_RGB: 796 case JCS_EXT_RGB: 797 case JCS_EXT_RGBX: 798 case JCS_EXT_BGR: 799 case JCS_EXT_BGRX: 800 case JCS_EXT_XBGR: 801 case JCS_EXT_XRGB: 802 case JCS_EXT_RGBA: 803 case JCS_EXT_BGRA: 804 case JCS_EXT_ABGR: 805 case JCS_EXT_ARGB: 806 cinfo->out_color_components = rgb_pixelsize[cinfo->out_color_space]; 807 if (cinfo->jpeg_color_space == JCS_YCbCr) { 808 if (jsimd_can_ycc_rgb()) 809 cconvert->pub.color_convert = jsimd_ycc_rgb_convert; 810 else { 811 cconvert->pub.color_convert = ycc_rgb_convert; 812 build_ycc_rgb_table(cinfo); 813 } 814 } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { 815 cconvert->pub.color_convert = gray_rgb_convert; 816 } else if (cinfo->jpeg_color_space == JCS_RGB) { 817 if (rgb_red[cinfo->out_color_space] == 0 && 818 rgb_green[cinfo->out_color_space] == 1 && 819 rgb_blue[cinfo->out_color_space] == 2 && 820 rgb_pixelsize[cinfo->out_color_space] == 3) 821 cconvert->pub.color_convert = null_convert; 822 else 823 cconvert->pub.color_convert = rgb_rgb_convert; 824 } else 825 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 826 break; 827 828 case JCS_RGB565: 829 cinfo->out_color_components = 3; 830 if (cinfo->dither_mode == JDITHER_NONE) { 831 if (cinfo->jpeg_color_space == JCS_YCbCr) { 832 if (jsimd_can_ycc_rgb565()) 833 cconvert->pub.color_convert = jsimd_ycc_rgb565_convert; 834 else { 835 cconvert->pub.color_convert = ycc_rgb565_convert; 836 build_ycc_rgb_table(cinfo); 837 } 838 } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { 839 cconvert->pub.color_convert = gray_rgb565_convert; 840 } else if (cinfo->jpeg_color_space == JCS_RGB) { 841 cconvert->pub.color_convert = rgb_rgb565_convert; 842 } else 843 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 844 } else { 845 /* only ordered dithering is supported */ 846 if (cinfo->jpeg_color_space == JCS_YCbCr) { 847 cconvert->pub.color_convert = ycc_rgb565D_convert; 848 build_ycc_rgb_table(cinfo); 849 } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { 850 cconvert->pub.color_convert = gray_rgb565D_convert; 851 } else if (cinfo->jpeg_color_space == JCS_RGB) { 852 cconvert->pub.color_convert = rgb_rgb565D_convert; 853 } else 854 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 855 } 856 break; 857 858 case JCS_CMYK: 859 cinfo->out_color_components = 4; 860 if (cinfo->jpeg_color_space == JCS_YCCK) { 861 cconvert->pub.color_convert = ycck_cmyk_convert; 862 build_ycc_rgb_table(cinfo); 863 } else if (cinfo->jpeg_color_space == JCS_CMYK) { 864 cconvert->pub.color_convert = null_convert; 865 } else 866 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 867 break; 868 869 default: 870 /* Permit null conversion to same output space */ 871 if (cinfo->out_color_space == cinfo->jpeg_color_space) { 872 cinfo->out_color_components = cinfo->num_components; 873 cconvert->pub.color_convert = null_convert; 874 } else /* unsupported non-null conversion */ 875 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 876 break; 877 } 878 879 if (cinfo->quantize_colors) 880 cinfo->output_components = 1; /* single colormapped output component */ 881 else 882 cinfo->output_components = cinfo->out_color_components; 883 } 884