1793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 2793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * jdcolor.c 3793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * 4793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Copyright (C) 1991-1997, Thomas G. Lane. 5793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Modified 2011-2012 by Guido Vollbeding. 6793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * This file is part of the Independent JPEG Group's software. 7793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * For conditions of distribution and use, see the accompanying README file. 8793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * 9793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * This file contains output colorspace conversion routines. 10793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 11793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 12793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define JPEG_INTERNALS 13793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "jinclude.h" 14793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "jpeglib.h" 15793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 16793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 17793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* Private subobject */ 18793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 19793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslertypedef struct { 20793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler struct jpeg_color_deconverter pub; /* public fields */ 21793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 22793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Private state for YCC->RGB conversion */ 23793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int * Cr_r_tab; /* => table for Cr to R conversion */ 24793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int * Cb_b_tab; /* => table for Cb to B conversion */ 25793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler INT32 * Cr_g_tab; /* => table for Cr to G conversion */ 26793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler INT32 * Cb_g_tab; /* => table for Cb to G conversion */ 27793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 28793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Private state for RGB->Y conversion */ 29793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler INT32 * rgb_y_tab; /* => table for RGB to Y conversion */ 30793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} my_color_deconverter; 31793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 32793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslertypedef my_color_deconverter * my_cconvert_ptr; 33793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 34793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 35793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/**************** YCbCr -> RGB conversion: most common case **************/ 36793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/**************** RGB -> Y conversion: less common case **************/ 37793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 38793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 39793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * YCbCr is defined per CCIR 601-1, except that Cb and Cr are 40793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. 41793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * The conversion equations to be implemented are therefore 42793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * 43793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * R = Y + 1.40200 * Cr 44793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * G = Y - 0.34414 * Cb - 0.71414 * Cr 45793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * B = Y + 1.77200 * Cb 46793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * 47793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B 48793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * 49793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * where Cb and Cr represent the incoming values less CENTERJSAMPLE. 50793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) 51793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * 52793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * To avoid floating-point arithmetic, we represent the fractional constants 53793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * as integers scaled up by 2^16 (about 4 digits precision); we have to divide 54793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * the products by 2^16, with appropriate rounding, to get the correct answer. 55793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Notice that Y, being an integral input, does not contribute any fraction 56793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * so it need not participate in the rounding. 57793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * 58793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * For even more speed, we avoid doing any multiplications in the inner loop 59793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * by precalculating the constants times Cb and Cr for all possible values. 60793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); 61793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * for 12-bit samples it is still acceptable. It's not very reasonable for 62793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * 16-bit samples, but if you want lossless storage you shouldn't be changing 63793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * colorspace anyway. 64793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * The Cr=>R and Cb=>B values can be rounded to integers in advance; the 65793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * values for the G calculation are left scaled up, since we must add them 66793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * together before rounding. 67793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 68793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 69793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define SCALEBITS 16 /* speediest right-shift on some machines */ 70793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) 71793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5)) 72793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 73793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* We allocate one big table for RGB->Y conversion and divide it up into 74793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * three parts, instead of doing three alloc_small requests. This lets us 75793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * use a single table base address, which can be held in a register in the 76793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * inner loops on many machines (more than can hold all three addresses, 77793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * anyway). 78793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 79793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 80793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define R_Y_OFF 0 /* offset to R => Y section */ 81793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */ 82793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */ 83793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define TABLE_SIZE (3*(MAXJSAMPLE+1)) 84793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 85793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 86793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 87793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Initialize tables for YCC->RGB colorspace conversion. 88793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 89793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 90793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerLOCAL(void) 91793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerbuild_ycc_rgb_table (j_decompress_ptr cinfo) 92793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 93793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; 94793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int i; 95793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler INT32 x; 96793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler SHIFT_TEMPS 97793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 98793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cconvert->Cr_r_tab = (int *) 99793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 100793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (MAXJSAMPLE+1) * SIZEOF(int)); 101793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cconvert->Cb_b_tab = (int *) 102793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 103793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (MAXJSAMPLE+1) * SIZEOF(int)); 104793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cconvert->Cr_g_tab = (INT32 *) 105793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 106793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (MAXJSAMPLE+1) * SIZEOF(INT32)); 107793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cconvert->Cb_g_tab = (INT32 *) 108793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 109793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (MAXJSAMPLE+1) * SIZEOF(INT32)); 110793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 111793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { 112793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ 113793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ 114793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Cr=>R value is nearest int to 1.40200 * x */ 115793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cconvert->Cr_r_tab[i] = (int) 116793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); 117793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Cb=>B value is nearest int to 1.77200 * x */ 118793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cconvert->Cb_b_tab[i] = (int) 119793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); 120793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Cr=>G value is scaled-up -0.71414 * x */ 121793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x; 122793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Cb=>G value is scaled-up -0.34414 * x */ 123793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* We also add in ONE_HALF so that need not do it in inner loop */ 124793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; 125793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 126793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 127793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 128793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 129793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 130793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Convert some rows of samples to the output colorspace. 131793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * 132793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Note that we change from noninterleaved, one-plane-per-component format 133793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * to interleaved-pixel format. The output buffer is therefore three times 134793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * as wide as the input buffer. 135793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * A starting row offset is provided only for the input buffer. The caller 136793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * can easily adjust the passed output_buf value to accommodate any row 137793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * offset required on that side. 138793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 139793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 140793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerMETHODDEF(void) 141793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerycc_rgb_convert (j_decompress_ptr cinfo, 142793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPIMAGE input_buf, JDIMENSION input_row, 143793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPARRAY output_buf, int num_rows) 144793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 145793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; 146793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register int y, cb, cr; 147793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JSAMPROW outptr; 148793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JSAMPROW inptr0, inptr1, inptr2; 149793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JDIMENSION col; 150793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JDIMENSION num_cols = cinfo->output_width; 151793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* copy these pointers into registers if possible */ 152793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JSAMPLE * range_limit = cinfo->sample_range_limit; 153793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register int * Crrtab = cconvert->Cr_r_tab; 154793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register int * Cbbtab = cconvert->Cb_b_tab; 155793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register INT32 * Crgtab = cconvert->Cr_g_tab; 156793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register INT32 * Cbgtab = cconvert->Cb_g_tab; 157793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler SHIFT_TEMPS 158793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 159793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler while (--num_rows >= 0) { 160793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr0 = input_buf[0][input_row]; 161793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr1 = input_buf[1][input_row]; 162793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr2 = input_buf[2][input_row]; 163793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler input_row++; 164793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr = *output_buf++; 165793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for (col = 0; col < num_cols; col++) { 166793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler y = GETJSAMPLE(inptr0[col]); 167793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cb = GETJSAMPLE(inptr1[col]); 168793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cr = GETJSAMPLE(inptr2[col]); 169793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Range-limiting is essential due to noise introduced by DCT losses. */ 170793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; 171793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr[RGB_GREEN] = range_limit[y + 172793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], 173793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler SCALEBITS))]; 174793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; 175793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr += RGB_PIXELSIZE; 176793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 177793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 178793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 179793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 180793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 181793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/**************** Cases other than YCbCr -> RGB **************/ 182793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 183793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 184793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 185793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Initialize for RGB->grayscale colorspace conversion. 186793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 187793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 188793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerLOCAL(void) 189793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerbuild_rgb_y_table (j_decompress_ptr cinfo) 190793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 191793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; 192793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler INT32 * rgb_y_tab; 193793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler INT32 i; 194793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 195793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Allocate and fill in the conversion tables. */ 196793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cconvert->rgb_y_tab = rgb_y_tab = (INT32 *) 197793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 198793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (TABLE_SIZE * SIZEOF(INT32))); 199793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 200793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for (i = 0; i <= MAXJSAMPLE; i++) { 201793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler rgb_y_tab[i+R_Y_OFF] = FIX(0.29900) * i; 202793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler rgb_y_tab[i+G_Y_OFF] = FIX(0.58700) * i; 203793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler rgb_y_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; 204793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 205793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 206793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 207793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 208793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 209793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Convert RGB to grayscale. 210793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 211793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 212793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerMETHODDEF(void) 213793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerrgb_gray_convert (j_decompress_ptr cinfo, 214793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPIMAGE input_buf, JDIMENSION input_row, 215793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPARRAY output_buf, int num_rows) 216793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 217793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; 218793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register INT32 * ctab = cconvert->rgb_y_tab; 219793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register int r, g, b; 220793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JSAMPROW outptr; 221793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JSAMPROW inptr0, inptr1, inptr2; 222793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JDIMENSION col; 223793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JDIMENSION num_cols = cinfo->output_width; 224793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 225793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler while (--num_rows >= 0) { 226793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr0 = input_buf[0][input_row]; 227793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr1 = input_buf[1][input_row]; 228793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr2 = input_buf[2][input_row]; 229793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler input_row++; 230793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr = *output_buf++; 231793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for (col = 0; col < num_cols; col++) { 232793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler r = GETJSAMPLE(inptr0[col]); 233793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler g = GETJSAMPLE(inptr1[col]); 234793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler b = GETJSAMPLE(inptr2[col]); 235793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Y */ 236793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr[col] = (JSAMPLE) 237793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) 238793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler >> SCALEBITS); 239793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 240793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 241793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 242793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 243793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 244793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 245793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * [R-G,G,B-G] to [R,G,B] conversion with modulo calculation 246793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * (inverse color transform). 247793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 248793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 249793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerMETHODDEF(void) 250793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerrgb1_rgb_convert (j_decompress_ptr cinfo, 251793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPIMAGE input_buf, JDIMENSION input_row, 252793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPARRAY output_buf, int num_rows) 253793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 254793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register int r, g, b; 255793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JSAMPROW outptr; 256793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JSAMPROW inptr0, inptr1, inptr2; 257793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JDIMENSION col; 258793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JDIMENSION num_cols = cinfo->output_width; 259793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 260793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler while (--num_rows >= 0) { 261793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr0 = input_buf[0][input_row]; 262793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr1 = input_buf[1][input_row]; 263793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr2 = input_buf[2][input_row]; 264793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler input_row++; 265793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr = *output_buf++; 266793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for (col = 0; col < num_cols; col++) { 267793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler r = GETJSAMPLE(inptr0[col]); 268793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler g = GETJSAMPLE(inptr1[col]); 269793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler b = GETJSAMPLE(inptr2[col]); 270793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Assume that MAXJSAMPLE+1 is a power of 2, so that the MOD 271793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * (modulo) operator is equivalent to the bitmask operator AND. 272793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 273793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr[RGB_RED] = (JSAMPLE) ((r + g - CENTERJSAMPLE) & MAXJSAMPLE); 274793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr[RGB_GREEN] = (JSAMPLE) g; 275793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr[RGB_BLUE] = (JSAMPLE) ((b + g - CENTERJSAMPLE) & MAXJSAMPLE); 276793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr += RGB_PIXELSIZE; 277793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 278793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 279793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 280793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 281793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 282793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 283793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * [R-G,G,B-G] to grayscale conversion with modulo calculation 284793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * (inverse color transform). 285793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 286793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 287793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerMETHODDEF(void) 288793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerrgb1_gray_convert (j_decompress_ptr cinfo, 289793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPIMAGE input_buf, JDIMENSION input_row, 290793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPARRAY output_buf, int num_rows) 291793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 292793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; 293793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register INT32 * ctab = cconvert->rgb_y_tab; 294793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register int r, g, b; 295793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JSAMPROW outptr; 296793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JSAMPROW inptr0, inptr1, inptr2; 297793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JDIMENSION col; 298793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JDIMENSION num_cols = cinfo->output_width; 299793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 300793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler while (--num_rows >= 0) { 301793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr0 = input_buf[0][input_row]; 302793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr1 = input_buf[1][input_row]; 303793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr2 = input_buf[2][input_row]; 304793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler input_row++; 305793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr = *output_buf++; 306793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for (col = 0; col < num_cols; col++) { 307793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler r = GETJSAMPLE(inptr0[col]); 308793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler g = GETJSAMPLE(inptr1[col]); 309793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler b = GETJSAMPLE(inptr2[col]); 310793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Assume that MAXJSAMPLE+1 is a power of 2, so that the MOD 311793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * (modulo) operator is equivalent to the bitmask operator AND. 312793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 313793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler r = (r + g - CENTERJSAMPLE) & MAXJSAMPLE; 314793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler b = (b + g - CENTERJSAMPLE) & MAXJSAMPLE; 315793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Y */ 316793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr[col] = (JSAMPLE) 317793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) 318793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler >> SCALEBITS); 319793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 320793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 321793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 322793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 323793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 324793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 325793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * No colorspace change, but conversion from separate-planes 326793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * to interleaved representation. 327793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 328793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 329793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerMETHODDEF(void) 330793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerrgb_convert (j_decompress_ptr cinfo, 331793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPIMAGE input_buf, JDIMENSION input_row, 332793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPARRAY output_buf, int num_rows) 333793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 334793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JSAMPROW outptr; 335793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JSAMPROW inptr0, inptr1, inptr2; 336793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JDIMENSION col; 337793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JDIMENSION num_cols = cinfo->output_width; 338793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 339793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler while (--num_rows >= 0) { 340793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr0 = input_buf[0][input_row]; 341793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr1 = input_buf[1][input_row]; 342793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr2 = input_buf[2][input_row]; 343793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler input_row++; 344793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr = *output_buf++; 345793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for (col = 0; col < num_cols; col++) { 346793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* We can dispense with GETJSAMPLE() here */ 347793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr[RGB_RED] = inptr0[col]; 348793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr[RGB_GREEN] = inptr1[col]; 349793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr[RGB_BLUE] = inptr2[col]; 350793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr += RGB_PIXELSIZE; 351793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 352793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 353793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 354793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 355793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 356793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 357793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Color conversion for no colorspace change: just copy the data, 358793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * converting from separate-planes to interleaved representation. 359793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 360793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 361793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerMETHODDEF(void) 362793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslernull_convert (j_decompress_ptr cinfo, 363793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPIMAGE input_buf, JDIMENSION input_row, 364793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPARRAY output_buf, int num_rows) 365793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 366793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int ci; 367793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register int nc = cinfo->num_components; 368793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JSAMPROW outptr; 369793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JSAMPROW inptr; 370793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JDIMENSION col; 371793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JDIMENSION num_cols = cinfo->output_width; 372793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 373793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler while (--num_rows >= 0) { 374793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for (ci = 0; ci < nc; ci++) { 375793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr = input_buf[ci][input_row]; 376793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr = output_buf[0] + ci; 377793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for (col = 0; col < num_cols; col++) { 378793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */ 379793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr += nc; 380793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 381793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 382793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler input_row++; 383793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler output_buf++; 384793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 385793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 386793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 387793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 388793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 389793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Color conversion for grayscale: just copy the data. 390793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * This also works for YCbCr -> grayscale conversion, in which 391793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * we just copy the Y (luminance) component and ignore chrominance. 392793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 393793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 394793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerMETHODDEF(void) 395793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslergrayscale_convert (j_decompress_ptr cinfo, 396793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPIMAGE input_buf, JDIMENSION input_row, 397793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPARRAY output_buf, int num_rows) 398793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 399793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0, 400793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler num_rows, cinfo->output_width); 401793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 402793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 403793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 404793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 405793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Convert grayscale to RGB: just duplicate the graylevel three times. 406793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * This is provided to support applications that don't want to cope 407793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * with grayscale as a separate case. 408793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 409793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 410793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerMETHODDEF(void) 411793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslergray_rgb_convert (j_decompress_ptr cinfo, 412793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPIMAGE input_buf, JDIMENSION input_row, 413793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPARRAY output_buf, int num_rows) 414793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 415793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JSAMPROW outptr; 416793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JSAMPROW inptr; 417793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JDIMENSION col; 418793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JDIMENSION num_cols = cinfo->output_width; 419793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 420793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler while (--num_rows >= 0) { 421793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr = input_buf[0][input_row++]; 422793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr = *output_buf++; 423793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for (col = 0; col < num_cols; col++) { 424793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* We can dispense with GETJSAMPLE() here */ 425793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col]; 426793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr += RGB_PIXELSIZE; 427793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 428793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 429793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 430793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 431793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 432793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 433793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Adobe-style YCCK->CMYK conversion. 434793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same 435793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * conversion as above, while passing K (black) unchanged. 436793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * We assume build_ycc_rgb_table has been called. 437793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 438793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 439793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerMETHODDEF(void) 440793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerycck_cmyk_convert (j_decompress_ptr cinfo, 441793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPIMAGE input_buf, JDIMENSION input_row, 442793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JSAMPARRAY output_buf, int num_rows) 443793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 444793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; 445793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register int y, cb, cr; 446793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JSAMPROW outptr; 447793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JSAMPROW inptr0, inptr1, inptr2, inptr3; 448793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JDIMENSION col; 449793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler JDIMENSION num_cols = cinfo->output_width; 450793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* copy these pointers into registers if possible */ 451793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register JSAMPLE * range_limit = cinfo->sample_range_limit; 452793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register int * Crrtab = cconvert->Cr_r_tab; 453793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register int * Cbbtab = cconvert->Cb_b_tab; 454793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register INT32 * Crgtab = cconvert->Cr_g_tab; 455793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler register INT32 * Cbgtab = cconvert->Cb_g_tab; 456793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler SHIFT_TEMPS 457793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 458793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler while (--num_rows >= 0) { 459793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr0 = input_buf[0][input_row]; 460793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr1 = input_buf[1][input_row]; 461793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr2 = input_buf[2][input_row]; 462793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler inptr3 = input_buf[3][input_row]; 463793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler input_row++; 464793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr = *output_buf++; 465793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for (col = 0; col < num_cols; col++) { 466793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler y = GETJSAMPLE(inptr0[col]); 467793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cb = GETJSAMPLE(inptr1[col]); 468793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cr = GETJSAMPLE(inptr2[col]); 469793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Range-limiting is essential due to noise introduced by DCT losses. */ 470793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ 471793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ 472793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], 473793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler SCALEBITS)))]; 474793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ 475793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* K passes through unchanged */ 476793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */ 477793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler outptr += 4; 478793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 479793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 480793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 481793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 482793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 483793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 484793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Empty method for start_pass. 485793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 486793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 487793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerMETHODDEF(void) 488793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstart_pass_dcolor (j_decompress_ptr cinfo) 489793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 490793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* no work needed */ 491793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 492793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 493793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 494793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* 495793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Module initialization routine for output colorspace conversion. 496793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 497793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 498793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerGLOBAL(void) 499793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerjinit_color_deconverter (j_decompress_ptr cinfo) 500793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 501793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler my_cconvert_ptr cconvert; 502793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler int ci; 503793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 504793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cconvert = (my_cconvert_ptr) 505793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 506793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler SIZEOF(my_color_deconverter)); 507793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cinfo->cconvert = &cconvert->pub; 508793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cconvert->pub.start_pass = start_pass_dcolor; 509793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 510793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Make sure num_components agrees with jpeg_color_space */ 511793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler switch (cinfo->jpeg_color_space) { 512793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler case JCS_GRAYSCALE: 513793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (cinfo->num_components != 1) 514793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); 515793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 516793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 517793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler case JCS_RGB: 518793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler case JCS_YCbCr: 519793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (cinfo->num_components != 3) 520793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); 521793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 522793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 523793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler case JCS_CMYK: 524793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler case JCS_YCCK: 525793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (cinfo->num_components != 4) 526793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); 527793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 528793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 529793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler default: /* JCS_UNKNOWN can be anything */ 530793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (cinfo->num_components < 1) 531793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); 532793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 533793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 534793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 535793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Support color transform only for RGB colorspace */ 536793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (cinfo->color_transform && cinfo->jpeg_color_space != JCS_RGB) 537793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 538793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 539793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Set out_color_components and conversion method based on requested space. 540793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Also clear the component_needed flags for any unused components, 541793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * so that earlier pipeline stages can avoid useless computation. 542793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */ 543793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 544793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler switch (cinfo->out_color_space) { 545793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler case JCS_GRAYSCALE: 546793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cinfo->out_color_components = 1; 547793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (cinfo->jpeg_color_space == JCS_GRAYSCALE || 548793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cinfo->jpeg_color_space == JCS_YCbCr) { 549793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cconvert->pub.color_convert = grayscale_convert; 550793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* For color->grayscale conversion, only the Y (0) component is needed */ 551793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler for (ci = 1; ci < cinfo->num_components; ci++) 552793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cinfo->comp_info[ci].component_needed = FALSE; 553793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } else if (cinfo->jpeg_color_space == JCS_RGB) { 554793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler switch (cinfo->color_transform) { 555793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler case JCT_NONE: 556793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cconvert->pub.color_convert = rgb_gray_convert; 557793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 558793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler case JCT_SUBTRACT_GREEN: 559793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cconvert->pub.color_convert = rgb1_gray_convert; 560793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 561793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler default: 562793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 563793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 564793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 565793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler build_rgb_y_table(cinfo); 566793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } else 567793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 568793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 569793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 570793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler case JCS_RGB: 571793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cinfo->out_color_components = RGB_PIXELSIZE; 572793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (cinfo->jpeg_color_space == JCS_YCbCr) { 573793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cconvert->pub.color_convert = ycc_rgb_convert; 574793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler build_ycc_rgb_table(cinfo); 575793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { 576793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cconvert->pub.color_convert = gray_rgb_convert; 577793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } else if (cinfo->jpeg_color_space == JCS_RGB) { 578793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler switch (cinfo->color_transform) { 579793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler case JCT_NONE: 580793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cconvert->pub.color_convert = rgb_convert; 581793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 582793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler case JCT_SUBTRACT_GREEN: 583793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cconvert->pub.color_convert = rgb1_rgb_convert; 584793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 585793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler default: 586793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 587793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 588793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 589793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } else 590793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 591793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 592793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 593793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler case JCS_CMYK: 594793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cinfo->out_color_components = 4; 595793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (cinfo->jpeg_color_space == JCS_YCCK) { 596793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cconvert->pub.color_convert = ycck_cmyk_convert; 597793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler build_ycc_rgb_table(cinfo); 598793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } else if (cinfo->jpeg_color_space == JCS_CMYK) { 599793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cconvert->pub.color_convert = null_convert; 600793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } else 601793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 602793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 603793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 604793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler default: 605793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler /* Permit null conversion to same output space */ 606793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (cinfo->out_color_space == cinfo->jpeg_color_space) { 607793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cinfo->out_color_components = cinfo->num_components; 608793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cconvert->pub.color_convert = null_convert; 609793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } else /* unsupported non-null conversion */ 610793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); 611793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler break; 612793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler } 613793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 614793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler if (cinfo->quantize_colors) 615793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cinfo->output_components = 1; /* single colormapped output component */ 616793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler else 617793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler cinfo->output_components = cinfo->out_color_components; 618793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} 619