1e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#if !defined(_FX_JPEG_TURBO_) 2e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 3e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * jdcolor.c 4e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 5e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Copyright (C) 1991-1997, Thomas G. Lane. 6e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * This file is part of the Independent JPEG Group's software. 7e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * For conditions of distribution and use, see the accompanying README file. 8e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 9e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * This file contains output colorspace conversion routines. 10e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 11e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 12e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#define JPEG_INTERNALS 13e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include "jinclude.h" 14e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include "jpeglib.h" 15e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 16e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 17e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* Private subobject */ 18e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 19e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovtypedef struct { 20e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov struct jpeg_color_deconverter pub; /* public fields */ 21e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 22e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Private state for YCC->RGB conversion */ 23e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int * Cr_r_tab; /* => table for Cr to R conversion */ 24e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int * Cb_b_tab; /* => table for Cb to B conversion */ 25e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov INT32 * Cr_g_tab; /* => table for Cr to G conversion */ 26e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov INT32 * Cb_g_tab; /* => table for Cb to G conversion */ 27e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} my_color_deconverter; 28e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 29e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovtypedef my_color_deconverter * my_cconvert_ptr; 30e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 31e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 32e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/**************** YCbCr -> RGB conversion: most common case **************/ 33e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 34e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 35e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * YCbCr is defined per CCIR 601-1, except that Cb and Cr are 36e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. 37e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * The conversion equations to be implemented are therefore 38e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * R = Y + 1.40200 * Cr 39e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * G = Y - 0.34414 * Cb - 0.71414 * Cr 40e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * B = Y + 1.77200 * Cb 41e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * where Cb and Cr represent the incoming values less CENTERJSAMPLE. 42e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) 43e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 44e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * To avoid floating-point arithmetic, we represent the fractional constants 45e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * as integers scaled up by 2^16 (about 4 digits precision); we have to divide 46e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * the products by 2^16, with appropriate rounding, to get the correct answer. 47e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Notice that Y, being an integral input, does not contribute any fraction 48e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * so it need not participate in the rounding. 49e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 50e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * For even more speed, we avoid doing any multiplications in the inner loop 51e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * by precalculating the constants times Cb and Cr for all possible values. 52e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); 53e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * for 12-bit samples it is still acceptable. It's not very reasonable for 54e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 16-bit samples, but if you want lossless storage you shouldn't be changing 55e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * colorspace anyway. 56e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * The Cr=>R and Cb=>B values can be rounded to integers in advance; the 57e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * values for the G calculation are left scaled up, since we must add them 58e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * together before rounding. 59e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 60e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 61e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#define SCALEBITS 16 /* speediest right-shift on some machines */ 62e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) 63e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5)) 64e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 65e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 66e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 67e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Initialize tables for YCC->RGB colorspace conversion. 68e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 69e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 70e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovLOCAL(void) 71e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovbuild_ycc_rgb_table (j_decompress_ptr cinfo) 72e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 73e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; 74e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int i; 75e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov INT32 x; 76e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov SHIFT_TEMPS 77e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 78e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cconvert->Cr_r_tab = (int *) 79e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 80e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (MAXJSAMPLE+1) * SIZEOF(int)); 81e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cconvert->Cb_b_tab = (int *) 82e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 83e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (MAXJSAMPLE+1) * SIZEOF(int)); 84e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cconvert->Cr_g_tab = (INT32 *) 85e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 86e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (MAXJSAMPLE+1) * SIZEOF(INT32)); 87e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cconvert->Cb_g_tab = (INT32 *) 88e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 89e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (MAXJSAMPLE+1) * SIZEOF(INT32)); 90e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 91e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { 92e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ 93e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ 94e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Cr=>R value is nearest int to 1.40200 * x */ 95e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cconvert->Cr_r_tab[i] = (int) 96e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); 97e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Cb=>B value is nearest int to 1.77200 * x */ 98e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cconvert->Cb_b_tab[i] = (int) 99e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); 100e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Cr=>G value is scaled-up -0.71414 * x */ 101e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x; 102e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Cb=>G value is scaled-up -0.34414 * x */ 103e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* We also add in ONE_HALF so that need not do it in inner loop */ 104e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; 105e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 106e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 107e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 108e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 109e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 110e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Convert some rows of samples to the output colorspace. 111e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * 112e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Note that we change from noninterleaved, one-plane-per-component format 113e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * to interleaved-pixel format. The output buffer is therefore three times 114e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * as wide as the input buffer. 115e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * A starting row offset is provided only for the input buffer. The caller 116e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * can easily adjust the passed output_buf value to accommodate any row 117e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * offset required on that side. 118e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 119e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 120e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovMETHODDEF(void) 121e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovycc_rgb_convert (j_decompress_ptr cinfo, 122e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPIMAGE input_buf, JDIMENSION input_row, 123e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPARRAY output_buf, int num_rows) 124e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 125e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; 126e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register int y, cb, cr; 127e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register JSAMPROW outptr; 128e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register JSAMPROW inptr0, inptr1, inptr2; 129e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register JDIMENSION col; 130e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JDIMENSION num_cols = cinfo->output_width; 131e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* copy these pointers into registers if possible */ 132e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register JSAMPLE * range_limit = cinfo->sample_range_limit; 133e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register int * Crrtab = cconvert->Cr_r_tab; 134e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register int * Cbbtab = cconvert->Cb_b_tab; 135e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register INT32 * Crgtab = cconvert->Cr_g_tab; 136e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register INT32 * Cbgtab = cconvert->Cb_g_tab; 137e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov SHIFT_TEMPS 138e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 139e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov while (--num_rows >= 0) { 140e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov inptr0 = input_buf[0][input_row]; 141e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov inptr1 = input_buf[1][input_row]; 142e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov inptr2 = input_buf[2][input_row]; 143e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov input_row++; 144e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov outptr = *output_buf++; 145e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (col = 0; col < num_cols; col++) { 146e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov y = GETJSAMPLE(inptr0[col]); 147e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cb = GETJSAMPLE(inptr1[col]); 148e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cr = GETJSAMPLE(inptr2[col]); 149e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Range-limiting is essential due to noise introduced by DCT losses. */ 150e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; 151e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov outptr[RGB_GREEN] = range_limit[y + 152e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], 153e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov SCALEBITS))]; 154e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; 155e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov outptr += RGB_PIXELSIZE; 156e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 157e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 158e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 159e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 160e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 161e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/**************** Cases other than YCbCr -> RGB **************/ 162e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 163e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 164e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 165e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Color conversion for no colorspace change: just copy the data, 166e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * converting from separate-planes to interleaved representation. 167e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 168e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 169e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovMETHODDEF(void) 170e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovnull_convert (j_decompress_ptr cinfo, 171e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPIMAGE input_buf, JDIMENSION input_row, 172e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPARRAY output_buf, int num_rows) 173e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 174e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register JSAMPROW inptr, outptr; 175e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register JDIMENSION count; 176e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register int num_components = cinfo->num_components; 177e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JDIMENSION num_cols = cinfo->output_width; 178e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int ci; 179e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 180e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov while (--num_rows >= 0) { 181e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (ci = 0; ci < num_components; ci++) { 182e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov inptr = input_buf[ci][input_row]; 183e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov outptr = output_buf[0] + ci; 184e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (count = num_cols; count > 0; count--) { 185e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */ 186e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov outptr += num_components; 187e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 188e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 189e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov input_row++; 190e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov output_buf++; 191e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 192e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 193e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 194e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 195e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 196e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Color conversion for grayscale: just copy the data. 197e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * This also works for YCbCr -> grayscale conversion, in which 198e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * we just copy the Y (luminance) component and ignore chrominance. 199e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 200e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 201e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovMETHODDEF(void) 202e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovgrayscale_convert (j_decompress_ptr cinfo, 203e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPIMAGE input_buf, JDIMENSION input_row, 204e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPARRAY output_buf, int num_rows) 205e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 206e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0, 207e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov num_rows, cinfo->output_width); 208e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 209e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 210e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 211e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 212e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Convert grayscale to RGB: just duplicate the graylevel three times. 213e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * This is provided to support applications that don't want to cope 214e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * with grayscale as a separate case. 215e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 216e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 217e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovMETHODDEF(void) 218e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovgray_rgb_convert (j_decompress_ptr cinfo, 219e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPIMAGE input_buf, JDIMENSION input_row, 220e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPARRAY output_buf, int num_rows) 221e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 222e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register JSAMPROW inptr, outptr; 223e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register JDIMENSION col; 224e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JDIMENSION num_cols = cinfo->output_width; 225e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 226e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov while (--num_rows >= 0) { 227e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov inptr = input_buf[0][input_row++]; 228e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov outptr = *output_buf++; 229e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (col = 0; col < num_cols; col++) { 230e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* We can dispense with GETJSAMPLE() here */ 231e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col]; 232e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov outptr += RGB_PIXELSIZE; 233e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 234e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 235e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 236e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 237e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 238e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 239e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Adobe-style YCCK->CMYK conversion. 240e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same 241e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * conversion as above, while passing K (black) unchanged. 242e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * We assume build_ycc_rgb_table has been called. 243e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 244e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 245e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovMETHODDEF(void) 246e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovycck_cmyk_convert (j_decompress_ptr cinfo, 247e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPIMAGE input_buf, JDIMENSION input_row, 248e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JSAMPARRAY output_buf, int num_rows) 249e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 250e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; 251e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register int y, cb, cr; 252e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register JSAMPROW outptr; 253e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register JSAMPROW inptr0, inptr1, inptr2, inptr3; 254e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register JDIMENSION col; 255e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov JDIMENSION num_cols = cinfo->output_width; 256e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* copy these pointers into registers if possible */ 257e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register JSAMPLE * range_limit = cinfo->sample_range_limit; 258e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register int * Crrtab = cconvert->Cr_r_tab; 259e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register int * Cbbtab = cconvert->Cb_b_tab; 260e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register INT32 * Crgtab = cconvert->Cr_g_tab; 261e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov register INT32 * Cbgtab = cconvert->Cb_g_tab; 262e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov SHIFT_TEMPS 263e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 264e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov while (--num_rows >= 0) { 265e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov inptr0 = input_buf[0][input_row]; 266e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov inptr1 = input_buf[1][input_row]; 267e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov inptr2 = input_buf[2][input_row]; 268e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov inptr3 = input_buf[3][input_row]; 269e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov input_row++; 270e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov outptr = *output_buf++; 271e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (col = 0; col < num_cols; col++) { 272e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov y = GETJSAMPLE(inptr0[col]); 273e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cb = GETJSAMPLE(inptr1[col]); 274e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cr = GETJSAMPLE(inptr2[col]); 275e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Range-limiting is essential due to noise introduced by DCT losses. */ 276e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ 277e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ 278e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], 279e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov SCALEBITS)))]; 280e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ 281e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* K passes through unchanged */ 282e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */ 283e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov outptr += 4; 284e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 285e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 286e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 287e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 288e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 289e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 290e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Empty method for start_pass. 291e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 292e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 293e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovMETHODDEF(void) 294e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstart_pass_dcolor (j_decompress_ptr cinfo) 295e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 296e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* no work needed */ 297e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 298e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 299e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 300e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov/* 301e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Module initialization routine for output colorspace conversion. 302e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 303e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 304e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovGLOBAL(void) 305e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovjinit_color_deconverter (j_decompress_ptr cinfo) 306e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 307e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov my_cconvert_ptr cconvert; 308e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int ci; 309e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 310e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cconvert = (my_cconvert_ptr) 311e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 312e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov SIZEOF(my_color_deconverter)); 313e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert; 314e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cconvert->pub.start_pass = start_pass_dcolor; 315e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 316e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Make sure num_components agrees with jpeg_color_space */ 317e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov switch (cinfo->jpeg_color_space) { 318e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov case JCS_GRAYSCALE: 319e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (cinfo->num_components != 1) 320e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); 321e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov break; 322e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 323e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov case JCS_RGB: 324e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov case JCS_YCbCr: 325e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (cinfo->num_components != 3) 326e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); 327e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov break; 328e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 329e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov case JCS_CMYK: 330e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov case JCS_YCCK: 331e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (cinfo->num_components != 4) 332e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); 333e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov break; 334e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 335e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov default: /* JCS_UNKNOWN can be anything */ 336e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (cinfo->num_components < 1) 337e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); 338e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov break; 339e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 340e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 341e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Set out_color_components and conversion method based on requested space. 342e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * Also clear the component_needed flags for any unused components, 343e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov * so that earlier pipeline stages can avoid useless computation. 344e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov */ 345e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 346e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov switch (cinfo->out_color_space) { 347e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov case JCS_GRAYSCALE: 348e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cinfo->out_color_components = 1; 349e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (cinfo->jpeg_color_space == JCS_GRAYSCALE || 350e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cinfo->jpeg_color_space == JCS_YCbCr) { 351e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cconvert->pub.color_convert = grayscale_convert; 352e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* For color->grayscale conversion, only the Y (0) component is needed */ 353e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (ci = 1; ci < cinfo->num_components; ci++) 354e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cinfo->comp_info[ci].component_needed = FALSE; 355e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else 356e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 357e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov break; 358e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 359e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov case JCS_RGB: 360e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cinfo->out_color_components = RGB_PIXELSIZE; 361e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (cinfo->jpeg_color_space == JCS_YCbCr) { 362e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cconvert->pub.color_convert = ycc_rgb_convert; 363e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov build_ycc_rgb_table(cinfo); 364e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { 365e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cconvert->pub.color_convert = gray_rgb_convert; 366e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) { 367e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cconvert->pub.color_convert = null_convert; 368e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else 369e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 370e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov break; 371e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 372e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov case JCS_CMYK: 373e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cinfo->out_color_components = 4; 374e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (cinfo->jpeg_color_space == JCS_YCCK) { 375e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cconvert->pub.color_convert = ycck_cmyk_convert; 376e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov build_ycc_rgb_table(cinfo); 377e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else if (cinfo->jpeg_color_space == JCS_CMYK) { 378e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cconvert->pub.color_convert = null_convert; 379e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else 380e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 381e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov break; 382e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 383e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov default: 384e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov /* Permit null conversion to same output space */ 385e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (cinfo->out_color_space == cinfo->jpeg_color_space) { 386e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cinfo->out_color_components = cinfo->num_components; 387e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cconvert->pub.color_convert = null_convert; 388e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else /* unsupported non-null conversion */ 389e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 390e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov break; 391e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 392e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 393e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (cinfo->quantize_colors) 394e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cinfo->output_components = 1; /* single colormapped output component */ 395e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov else 396e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cinfo->output_components = cinfo->out_color_components; 397e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 398e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 399e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#endif //_FX_JPEG_TURBO_ 400