1#if !defined(_FX_JPEG_TURBO_) 2/* 3 * jccolor.c 4 * 5 * Copyright (C) 1991-1996, Thomas G. Lane. 6 * This file is part of the Independent JPEG Group's software. 7 * For conditions of distribution and use, see the accompanying README file. 8 * 9 * This file contains input colorspace conversion routines. 10 */ 11 12#define JPEG_INTERNALS 13#include "jinclude.h" 14#include "jpeglib.h" 15 16 17/* Private subobject */ 18 19typedef struct { 20 struct jpeg_color_converter pub; /* public fields */ 21 22 /* Private state for RGB->YCC conversion */ 23 INT32 * rgb_ycc_tab; /* => table for RGB to YCbCr conversion */ 24} my_color_converter; 25 26typedef my_color_converter * my_cconvert_ptr; 27 28 29/**************** RGB -> YCbCr conversion: most common case **************/ 30 31/* 32 * YCbCr is defined per CCIR 601-1, except that Cb and Cr are 33 * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. 34 * The conversion equations to be implemented are therefore 35 * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B 36 * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE 37 * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE 38 * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) 39 * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2, 40 * rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and 41 * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0) 42 * were not represented exactly. Now we sacrifice exact representation of 43 * maximum red and maximum blue in order to get exact grayscales. 44 * 45 * To avoid floating-point arithmetic, we represent the fractional constants 46 * as integers scaled up by 2^16 (about 4 digits precision); we have to divide 47 * the products by 2^16, with appropriate rounding, to get the correct answer. 48 * 49 * For even more speed, we avoid doing any multiplications in the inner loop 50 * by precalculating the constants times R,G,B for all possible values. 51 * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); 52 * for 12-bit samples it is still acceptable. It's not very reasonable for 53 * 16-bit samples, but if you want lossless storage you shouldn't be changing 54 * colorspace anyway. 55 * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included 56 * in the tables to save adding them separately in the inner loop. 57 */ 58 59#define SCALEBITS 16 /* speediest right-shift on some machines */ 60#define CBCR_OFFSET ((INT32) CENTERJSAMPLE << SCALEBITS) 61#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) 62#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5)) 63 64/* We allocate one big table and divide it up into eight parts, instead of 65 * doing eight alloc_small requests. This lets us use a single table base 66 * address, which can be held in a register in the inner loops on many 67 * machines (more than can hold all eight addresses, anyway). 68 */ 69 70#define R_Y_OFF 0 /* offset to R => Y section */ 71#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */ 72#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */ 73#define R_CB_OFF (3*(MAXJSAMPLE+1)) 74#define G_CB_OFF (4*(MAXJSAMPLE+1)) 75#define B_CB_OFF (5*(MAXJSAMPLE+1)) 76#define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */ 77#define G_CR_OFF (6*(MAXJSAMPLE+1)) 78#define B_CR_OFF (7*(MAXJSAMPLE+1)) 79#define TABLE_SIZE (8*(MAXJSAMPLE+1)) 80 81 82/* 83 * Initialize for RGB->YCC colorspace conversion. 84 */ 85 86METHODDEF(void) 87rgb_ycc_start (j_compress_ptr cinfo) 88{ 89 my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; 90 INT32 * rgb_ycc_tab; 91 INT32 i; 92 93 /* Allocate and fill in the conversion tables. */ 94 cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *) 95 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 96 (TABLE_SIZE * SIZEOF(INT32))); 97 98 for (i = 0; i <= MAXJSAMPLE; i++) { 99 rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i; 100 rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i; 101 rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; 102 rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i; 103 rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i; 104 /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr. 105 * This ensures that the maximum output will round to MAXJSAMPLE 106 * not MAXJSAMPLE+1, and thus that we don't have to range-limit. 107 */ 108 rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; 109/* B=>Cb and R=>Cr tables are the same 110 rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1; 111*/ 112 rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i; 113 rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i; 114 } 115} 116 117 118/* 119 * Convert some rows of samples to the JPEG colorspace. 120 * 121 * Note that we change from the application's interleaved-pixel format 122 * to our internal noninterleaved, one-plane-per-component format. 123 * The input buffer is therefore three times as wide as the output buffer. 124 * 125 * A starting row offset is provided only for the output buffer. The caller 126 * can easily adjust the passed input_buf value to accommodate any row 127 * offset required on that side. 128 */ 129 130METHODDEF(void) 131rgb_ycc_convert (j_compress_ptr cinfo, 132 JSAMPARRAY input_buf, JSAMPIMAGE output_buf, 133 JDIMENSION output_row, int num_rows) 134{ 135 my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; 136 register int r, g, b; 137 register INT32 * ctab = cconvert->rgb_ycc_tab; 138 register JSAMPROW inptr; 139 register JSAMPROW outptr0, outptr1, outptr2; 140 register JDIMENSION col; 141 JDIMENSION num_cols = cinfo->image_width; 142 143 while (--num_rows >= 0) { 144 inptr = *input_buf++; 145 outptr0 = output_buf[0][output_row]; 146 outptr1 = output_buf[1][output_row]; 147 outptr2 = output_buf[2][output_row]; 148 output_row++; 149 for (col = 0; col < num_cols; col++) { 150 r = GETJSAMPLE(inptr[RGB_RED]); 151 g = GETJSAMPLE(inptr[RGB_GREEN]); 152 b = GETJSAMPLE(inptr[RGB_BLUE]); 153 inptr += RGB_PIXELSIZE; 154 /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations 155 * must be too; we do not need an explicit range-limiting operation. 156 * Hence the value being shifted is never negative, and we don't 157 * need the general RIGHT_SHIFT macro. 158 */ 159 /* Y */ 160 outptr0[col] = (JSAMPLE) 161 ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) 162 >> SCALEBITS); 163 /* Cb */ 164 outptr1[col] = (JSAMPLE) 165 ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) 166 >> SCALEBITS); 167 /* Cr */ 168 outptr2[col] = (JSAMPLE) 169 ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) 170 >> SCALEBITS); 171 } 172 } 173} 174 175 176/**************** Cases other than RGB -> YCbCr **************/ 177 178 179/* 180 * Convert some rows of samples to the JPEG colorspace. 181 * This version handles RGB->grayscale conversion, which is the same 182 * as the RGB->Y portion of RGB->YCbCr. 183 * We assume rgb_ycc_start has been called (we only use the Y tables). 184 */ 185 186METHODDEF(void) 187rgb_gray_convert (j_compress_ptr cinfo, 188 JSAMPARRAY input_buf, JSAMPIMAGE output_buf, 189 JDIMENSION output_row, int num_rows) 190{ 191 my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; 192 register int r, g, b; 193 register INT32 * ctab = cconvert->rgb_ycc_tab; 194 register JSAMPROW inptr; 195 register JSAMPROW outptr; 196 register JDIMENSION col; 197 JDIMENSION num_cols = cinfo->image_width; 198 199 while (--num_rows >= 0) { 200 inptr = *input_buf++; 201 outptr = output_buf[0][output_row]; 202 output_row++; 203 for (col = 0; col < num_cols; col++) { 204 r = GETJSAMPLE(inptr[RGB_RED]); 205 g = GETJSAMPLE(inptr[RGB_GREEN]); 206 b = GETJSAMPLE(inptr[RGB_BLUE]); 207 inptr += RGB_PIXELSIZE; 208 /* Y */ 209 outptr[col] = (JSAMPLE) 210 ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) 211 >> SCALEBITS); 212 } 213 } 214} 215 216 217/* 218 * Convert some rows of samples to the JPEG colorspace. 219 * This version handles Adobe-style CMYK->YCCK conversion, 220 * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same 221 * conversion as above, while passing K (black) unchanged. 222 * We assume rgb_ycc_start has been called. 223 */ 224 225METHODDEF(void) 226cmyk_ycck_convert (j_compress_ptr cinfo, 227 JSAMPARRAY input_buf, JSAMPIMAGE output_buf, 228 JDIMENSION output_row, int num_rows) 229{ 230 my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; 231 register int r, g, b; 232 register INT32 * ctab = cconvert->rgb_ycc_tab; 233 register JSAMPROW inptr; 234 register JSAMPROW outptr0, outptr1, outptr2, outptr3; 235 register JDIMENSION col; 236 JDIMENSION num_cols = cinfo->image_width; 237 238 while (--num_rows >= 0) { 239 inptr = *input_buf++; 240 outptr0 = output_buf[0][output_row]; 241 outptr1 = output_buf[1][output_row]; 242 outptr2 = output_buf[2][output_row]; 243 outptr3 = output_buf[3][output_row]; 244 output_row++; 245 for (col = 0; col < num_cols; col++) { 246 r = MAXJSAMPLE - GETJSAMPLE(inptr[0]); 247 g = MAXJSAMPLE - GETJSAMPLE(inptr[1]); 248 b = MAXJSAMPLE - GETJSAMPLE(inptr[2]); 249 /* K passes through as-is */ 250 outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */ 251 inptr += 4; 252 /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations 253 * must be too; we do not need an explicit range-limiting operation. 254 * Hence the value being shifted is never negative, and we don't 255 * need the general RIGHT_SHIFT macro. 256 */ 257 /* Y */ 258 outptr0[col] = (JSAMPLE) 259 ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) 260 >> SCALEBITS); 261 /* Cb */ 262 outptr1[col] = (JSAMPLE) 263 ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) 264 >> SCALEBITS); 265 /* Cr */ 266 outptr2[col] = (JSAMPLE) 267 ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) 268 >> SCALEBITS); 269 } 270 } 271} 272 273 274/* 275 * Convert some rows of samples to the JPEG colorspace. 276 * This version handles grayscale output with no conversion. 277 * The source can be either plain grayscale or YCbCr (since Y == gray). 278 */ 279 280METHODDEF(void) 281grayscale_convert (j_compress_ptr cinfo, 282 JSAMPARRAY input_buf, JSAMPIMAGE output_buf, 283 JDIMENSION output_row, int num_rows) 284{ 285 register JSAMPROW inptr; 286 register JSAMPROW outptr; 287 register JDIMENSION col; 288 JDIMENSION num_cols = cinfo->image_width; 289 int instride = cinfo->input_components; 290 291 while (--num_rows >= 0) { 292 inptr = *input_buf++; 293 outptr = output_buf[0][output_row]; 294 output_row++; 295 for (col = 0; col < num_cols; col++) { 296 outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */ 297 inptr += instride; 298 } 299 } 300} 301 302 303/* 304 * Convert some rows of samples to the JPEG colorspace. 305 * This version handles multi-component colorspaces without conversion. 306 * We assume input_components == num_components. 307 */ 308 309METHODDEF(void) 310null_convert (j_compress_ptr cinfo, 311 JSAMPARRAY input_buf, JSAMPIMAGE output_buf, 312 JDIMENSION output_row, int num_rows) 313{ 314 register JSAMPROW inptr; 315 register JSAMPROW outptr; 316 register JDIMENSION col; 317 register int ci; 318 int nc = cinfo->num_components; 319 JDIMENSION num_cols = cinfo->image_width; 320 321 while (--num_rows >= 0) { 322 /* It seems fastest to make a separate pass for each component. */ 323 for (ci = 0; ci < nc; ci++) { 324 inptr = *input_buf; 325 outptr = output_buf[ci][output_row]; 326 for (col = 0; col < num_cols; col++) { 327 outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */ 328 inptr += nc; 329 } 330 } 331 input_buf++; 332 output_row++; 333 } 334} 335 336 337/* 338 * Empty method for start_pass. 339 */ 340 341METHODDEF(void) 342null_method (j_compress_ptr cinfo) 343{ 344 /* no work needed */ 345} 346 347 348/* 349 * Module initialization routine for input colorspace conversion. 350 */ 351 352GLOBAL(void) 353jinit_color_converter (j_compress_ptr cinfo) 354{ 355 my_cconvert_ptr cconvert; 356 357 cconvert = (my_cconvert_ptr) 358 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 359 SIZEOF(my_color_converter)); 360 cinfo->cconvert = (struct jpeg_color_converter *) cconvert; 361 /* set start_pass to null method until we find out differently */ 362 cconvert->pub.start_pass = null_method; 363 364 /* Make sure input_components agrees with in_color_space */ 365 switch (cinfo->in_color_space) { 366 case JCS_GRAYSCALE: 367 if (cinfo->input_components != 1) 368 ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); 369 break; 370 371 case JCS_RGB: 372#if RGB_PIXELSIZE != 3 373 if (cinfo->input_components != RGB_PIXELSIZE) 374 ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); 375 break; 376#endif /* else share code with YCbCr */ 377 378 case JCS_YCbCr: 379 if (cinfo->input_components != 3) 380 ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); 381 break; 382 383 case JCS_CMYK: 384 case JCS_YCCK: 385 if (cinfo->input_components != 4) 386 ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); 387 break; 388 389 default: /* JCS_UNKNOWN can be anything */ 390 if (cinfo->input_components < 1) 391 ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); 392 break; 393 } 394 395 /* Check num_components, set conversion method based on requested space */ 396 switch (cinfo->jpeg_color_space) { 397 case JCS_GRAYSCALE: 398 if (cinfo->num_components != 1) 399 ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); 400 if (cinfo->in_color_space == JCS_GRAYSCALE) 401 cconvert->pub.color_convert = grayscale_convert; 402 else if (cinfo->in_color_space == JCS_RGB) { 403 cconvert->pub.start_pass = rgb_ycc_start; 404 cconvert->pub.color_convert = rgb_gray_convert; 405 } else if (cinfo->in_color_space == JCS_YCbCr) 406 cconvert->pub.color_convert = grayscale_convert; 407 else 408 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 409 break; 410 411 case JCS_RGB: 412 if (cinfo->num_components != 3) 413 ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); 414 if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3) 415 cconvert->pub.color_convert = null_convert; 416 else 417 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 418 break; 419 420 case JCS_YCbCr: 421 if (cinfo->num_components != 3) 422 ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); 423 if (cinfo->in_color_space == JCS_RGB) { 424 cconvert->pub.start_pass = rgb_ycc_start; 425 cconvert->pub.color_convert = rgb_ycc_convert; 426 } else if (cinfo->in_color_space == JCS_YCbCr) 427 cconvert->pub.color_convert = null_convert; 428 else 429 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 430 break; 431 432 case JCS_CMYK: 433 if (cinfo->num_components != 4) 434 ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); 435 if (cinfo->in_color_space == JCS_CMYK) 436 cconvert->pub.color_convert = null_convert; 437 else 438 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 439 break; 440 441 case JCS_YCCK: 442 if (cinfo->num_components != 4) 443 ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); 444 if (cinfo->in_color_space == JCS_CMYK) { 445 cconvert->pub.start_pass = rgb_ycc_start; 446 cconvert->pub.color_convert = cmyk_ycck_convert; 447 } else if (cinfo->in_color_space == JCS_YCCK) 448 cconvert->pub.color_convert = null_convert; 449 else 450 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 451 break; 452 453 default: /* allow null conversion of JCS_UNKNOWN */ 454 if (cinfo->jpeg_color_space != cinfo->in_color_space || 455 cinfo->num_components != cinfo->input_components) 456 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 457 cconvert->pub.color_convert = null_convert; 458 break; 459 } 460} 461 462#endif //_FX_JPEG_TURBO_ 463