ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

jdcolor.c
Go to the documentation of this file.
00001 /*
00002  * jdcolor.c
00003  *
00004  * Copyright (C) 1991-1997, Thomas G. Lane.
00005  * This file is part of the Independent JPEG Group's software.
00006  * For conditions of distribution and use, see the accompanying README file.
00007  *
00008  * This file contains output colorspace conversion routines.
00009  */
00010 
00011 #define JPEG_INTERNALS
00012 #include "jinclude.h"
00013 #include "jpeglib.h"
00014 
00015 
00016 /* Private subobject */
00017 
00018 typedef struct {
00019   struct jpeg_color_deconverter pub; /* public fields */
00020 
00021   /* Private state for YCC->RGB conversion */
00022   int * Cr_r_tab;       /* => table for Cr to R conversion */
00023   int * Cb_b_tab;       /* => table for Cb to B conversion */
00024   INT32 * Cr_g_tab;     /* => table for Cr to G conversion */
00025   INT32 * Cb_g_tab;     /* => table for Cb to G conversion */
00026 } my_color_deconverter;
00027 
00028 typedef my_color_deconverter * my_cconvert_ptr;
00029 
00030 
00031 /**************** YCbCr -> RGB conversion: most common case **************/
00032 
00033 /*
00034  * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
00035  * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
00036  * The conversion equations to be implemented are therefore
00037  *  R = Y                + 1.40200 * Cr
00038  *  G = Y - 0.34414 * Cb - 0.71414 * Cr
00039  *  B = Y + 1.77200 * Cb
00040  * where Cb and Cr represent the incoming values less CENTERJSAMPLE.
00041  * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
00042  *
00043  * To avoid floating-point arithmetic, we represent the fractional constants
00044  * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
00045  * the products by 2^16, with appropriate rounding, to get the correct answer.
00046  * Notice that Y, being an integral input, does not contribute any fraction
00047  * so it need not participate in the rounding.
00048  *
00049  * For even more speed, we avoid doing any multiplications in the inner loop
00050  * by precalculating the constants times Cb and Cr for all possible values.
00051  * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
00052  * for 12-bit samples it is still acceptable.  It's not very reasonable for
00053  * 16-bit samples, but if you want lossless storage you shouldn't be changing
00054  * colorspace anyway.
00055  * The Cr=>R and Cb=>B values can be rounded to integers in advance; the
00056  * values for the G calculation are left scaled up, since we must add them
00057  * together before rounding.
00058  */
00059 
00060 #define SCALEBITS   16  /* speediest right-shift on some machines */
00061 #define ONE_HALF    ((INT32) 1 << (SCALEBITS-1))
00062 #define FIX(x)      ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
00063 
00064 
00065 /*
00066  * Initialize tables for YCC->RGB colorspace conversion.
00067  */
00068 
00069 LOCAL(void)
00070 build_ycc_rgb_table (j_decompress_ptr cinfo)
00071 {
00072   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
00073   int i;
00074   INT32 x;
00075   SHIFT_TEMPS
00076 
00077   cconvert->Cr_r_tab = (int *)
00078     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00079                 (MAXJSAMPLE+1) * SIZEOF(int));
00080   cconvert->Cb_b_tab = (int *)
00081     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00082                 (MAXJSAMPLE+1) * SIZEOF(int));
00083   cconvert->Cr_g_tab = (INT32 *)
00084     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00085                 (MAXJSAMPLE+1) * SIZEOF(INT32));
00086   cconvert->Cb_g_tab = (INT32 *)
00087     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00088                 (MAXJSAMPLE+1) * SIZEOF(INT32));
00089 
00090   for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
00091     /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
00092     /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
00093     /* Cr=>R value is nearest int to 1.40200 * x */
00094     cconvert->Cr_r_tab[i] = (int)
00095             RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS);
00096     /* Cb=>B value is nearest int to 1.77200 * x */
00097     cconvert->Cb_b_tab[i] = (int)
00098             RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
00099     /* Cr=>G value is scaled-up -0.71414 * x */
00100     cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x;
00101     /* Cb=>G value is scaled-up -0.34414 * x */
00102     /* We also add in ONE_HALF so that need not do it in inner loop */
00103     cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
00104   }
00105 }
00106 
00107 
00108 /*
00109  * Convert some rows of samples to the output colorspace.
00110  *
00111  * Note that we change from noninterleaved, one-plane-per-component format
00112  * to interleaved-pixel format.  The output buffer is therefore three times
00113  * as wide as the input buffer.
00114  * A starting row offset is provided only for the input buffer.  The caller
00115  * can easily adjust the passed output_buf value to accommodate any row
00116  * offset required on that side.
00117  */
00118 
00119 METHODDEF(void)
00120 ycc_rgb_convert (j_decompress_ptr cinfo,
00121          JSAMPIMAGE input_buf, JDIMENSION input_row,
00122          JSAMPARRAY output_buf, int num_rows)
00123 {
00124   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
00125   register int y, cb, cr;
00126   register JSAMPROW outptr;
00127   register JSAMPROW inptr0, inptr1, inptr2;
00128   register JDIMENSION col;
00129   JDIMENSION num_cols = cinfo->output_width;
00130   /* copy these pointers into registers if possible */
00131   register JSAMPLE * range_limit = cinfo->sample_range_limit;
00132   register int * Crrtab = cconvert->Cr_r_tab;
00133   register int * Cbbtab = cconvert->Cb_b_tab;
00134   register INT32 * Crgtab = cconvert->Cr_g_tab;
00135   register INT32 * Cbgtab = cconvert->Cb_g_tab;
00136   SHIFT_TEMPS
00137 
00138   while (--num_rows >= 0) {
00139     inptr0 = input_buf[0][input_row];
00140     inptr1 = input_buf[1][input_row];
00141     inptr2 = input_buf[2][input_row];
00142     input_row++;
00143     outptr = *output_buf++;
00144     for (col = 0; col < num_cols; col++) {
00145       y  = GETJSAMPLE(inptr0[col]);
00146       cb = GETJSAMPLE(inptr1[col]);
00147       cr = GETJSAMPLE(inptr2[col]);
00148       /* Range-limiting is essential due to noise introduced by DCT losses. */
00149       outptr[RGB_RED] =   range_limit[y + Crrtab[cr]];
00150       outptr[RGB_GREEN] = range_limit[y +
00151                   ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
00152                          SCALEBITS))];
00153       outptr[RGB_BLUE] =  range_limit[y + Cbbtab[cb]];
00154       outptr += RGB_PIXELSIZE;
00155     }
00156   }
00157 }
00158 
00159 
00160 /**************** Cases other than YCbCr -> RGB **************/
00161 
00162 
00163 /*
00164  * Color conversion for no colorspace change: just copy the data,
00165  * converting from separate-planes to interleaved representation.
00166  */
00167 
00168 METHODDEF(void)
00169 null_convert (j_decompress_ptr cinfo,
00170           JSAMPIMAGE input_buf, JDIMENSION input_row,
00171           JSAMPARRAY output_buf, int num_rows)
00172 {
00173   register JSAMPROW inptr, outptr;
00174   register JDIMENSION count;
00175   register int num_components = cinfo->num_components;
00176   JDIMENSION num_cols = cinfo->output_width;
00177   int ci;
00178 
00179   while (--num_rows >= 0) {
00180     for (ci = 0; ci < num_components; ci++) {
00181       inptr = input_buf[ci][input_row];
00182       outptr = output_buf[0] + ci;
00183       for (count = num_cols; count > 0; count--) {
00184     *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */
00185     outptr += num_components;
00186       }
00187     }
00188     input_row++;
00189     output_buf++;
00190   }
00191 }
00192 
00193 
00194 /*
00195  * Color conversion for grayscale: just copy the data.
00196  * This also works for YCbCr -> grayscale conversion, in which
00197  * we just copy the Y (luminance) component and ignore chrominance.
00198  */
00199 
00200 METHODDEF(void)
00201 grayscale_convert (j_decompress_ptr cinfo,
00202            JSAMPIMAGE input_buf, JDIMENSION input_row,
00203            JSAMPARRAY output_buf, int num_rows)
00204 {
00205   jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0,
00206             num_rows, cinfo->output_width);
00207 }
00208 
00209 
00210 /*
00211  * Convert grayscale to RGB: just duplicate the graylevel three times.
00212  * This is provided to support applications that don't want to cope
00213  * with grayscale as a separate case.
00214  */
00215 
00216 METHODDEF(void)
00217 gray_rgb_convert (j_decompress_ptr cinfo,
00218           JSAMPIMAGE input_buf, JDIMENSION input_row,
00219           JSAMPARRAY output_buf, int num_rows)
00220 {
00221   register JSAMPROW inptr, outptr;
00222   register JDIMENSION col;
00223   JDIMENSION num_cols = cinfo->output_width;
00224 
00225   while (--num_rows >= 0) {
00226     inptr = input_buf[0][input_row++];
00227     outptr = *output_buf++;
00228     for (col = 0; col < num_cols; col++) {
00229       /* We can dispense with GETJSAMPLE() here */
00230       outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col];
00231       outptr += RGB_PIXELSIZE;
00232     }
00233   }
00234 }
00235 
00236 
00237 /*
00238  * Adobe-style YCCK->CMYK conversion.
00239  * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same
00240  * conversion as above, while passing K (black) unchanged.
00241  * We assume build_ycc_rgb_table has been called.
00242  */
00243 
00244 METHODDEF(void)
00245 ycck_cmyk_convert (j_decompress_ptr cinfo,
00246            JSAMPIMAGE input_buf, JDIMENSION input_row,
00247            JSAMPARRAY output_buf, int num_rows)
00248 {
00249   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
00250   register int y, cb, cr;
00251   register JSAMPROW outptr;
00252   register JSAMPROW inptr0, inptr1, inptr2, inptr3;
00253   register JDIMENSION col;
00254   JDIMENSION num_cols = cinfo->output_width;
00255   /* copy these pointers into registers if possible */
00256   register JSAMPLE * range_limit = cinfo->sample_range_limit;
00257   register int * Crrtab = cconvert->Cr_r_tab;
00258   register int * Cbbtab = cconvert->Cb_b_tab;
00259   register INT32 * Crgtab = cconvert->Cr_g_tab;
00260   register INT32 * Cbgtab = cconvert->Cb_g_tab;
00261   SHIFT_TEMPS
00262 
00263   while (--num_rows >= 0) {
00264     inptr0 = input_buf[0][input_row];
00265     inptr1 = input_buf[1][input_row];
00266     inptr2 = input_buf[2][input_row];
00267     inptr3 = input_buf[3][input_row];
00268     input_row++;
00269     outptr = *output_buf++;
00270     for (col = 0; col < num_cols; col++) {
00271       y  = GETJSAMPLE(inptr0[col]);
00272       cb = GETJSAMPLE(inptr1[col]);
00273       cr = GETJSAMPLE(inptr2[col]);
00274       /* Range-limiting is essential due to noise introduced by DCT losses. */
00275       outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])];   /* red */
00276       outptr[1] = range_limit[MAXJSAMPLE - (y +         /* green */
00277                   ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
00278                          SCALEBITS)))];
00279       outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])];   /* blue */
00280       /* K passes through unchanged */
00281       outptr[3] = inptr3[col];  /* don't need GETJSAMPLE here */
00282       outptr += 4;
00283     }
00284   }
00285 }
00286 
00287 
00288 /*
00289  * Empty method for start_pass.
00290  */
00291 
00292 METHODDEF(void)
00293 start_pass_dcolor (j_decompress_ptr cinfo)
00294 {
00295   /* no work needed */
00296 }
00297 
00298 
00299 /*
00300  * Module initialization routine for output colorspace conversion.
00301  */
00302 
00303 GLOBAL(void)
00304 jinit_color_deconverter (j_decompress_ptr cinfo)
00305 {
00306   my_cconvert_ptr cconvert;
00307   int ci;
00308 
00309   cconvert = (my_cconvert_ptr)
00310     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00311                 SIZEOF(my_color_deconverter));
00312   cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert;
00313   cconvert->pub.start_pass = start_pass_dcolor;
00314 
00315   /* Make sure num_components agrees with jpeg_color_space */
00316   switch (cinfo->jpeg_color_space) {
00317   case JCS_GRAYSCALE:
00318     if (cinfo->num_components != 1)
00319       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
00320     break;
00321 
00322   case JCS_RGB:
00323   case JCS_YCbCr:
00324     if (cinfo->num_components != 3)
00325       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
00326     break;
00327 
00328   case JCS_CMYK:
00329   case JCS_YCCK:
00330     if (cinfo->num_components != 4)
00331       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
00332     break;
00333 
00334   default:          /* JCS_UNKNOWN can be anything */
00335     if (cinfo->num_components < 1)
00336       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
00337     break;
00338   }
00339 
00340   /* Set out_color_components and conversion method based on requested space.
00341    * Also clear the component_needed flags for any unused components,
00342    * so that earlier pipeline stages can avoid useless computation.
00343    */
00344 
00345   switch (cinfo->out_color_space) {
00346   case JCS_GRAYSCALE:
00347     cinfo->out_color_components = 1;
00348     if (cinfo->jpeg_color_space == JCS_GRAYSCALE ||
00349     cinfo->jpeg_color_space == JCS_YCbCr) {
00350       cconvert->pub.color_convert = grayscale_convert;
00351       /* For color->grayscale conversion, only the Y (0) component is needed */
00352       for (ci = 1; ci < cinfo->num_components; ci++)
00353     cinfo->comp_info[ci].component_needed = FALSE;
00354     } else
00355       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
00356     break;
00357 
00358   case JCS_RGB:
00359     cinfo->out_color_components = RGB_PIXELSIZE;
00360     if (cinfo->jpeg_color_space == JCS_YCbCr) {
00361       cconvert->pub.color_convert = ycc_rgb_convert;
00362       build_ycc_rgb_table(cinfo);
00363     } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) {
00364       cconvert->pub.color_convert = gray_rgb_convert;
00365     } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) {
00366       cconvert->pub.color_convert = null_convert;
00367     } else
00368       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
00369     break;
00370 
00371   case JCS_CMYK:
00372     cinfo->out_color_components = 4;
00373     if (cinfo->jpeg_color_space == JCS_YCCK) {
00374       cconvert->pub.color_convert = ycck_cmyk_convert;
00375       build_ycc_rgb_table(cinfo);
00376     } else if (cinfo->jpeg_color_space == JCS_CMYK) {
00377       cconvert->pub.color_convert = null_convert;
00378     } else
00379       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
00380     break;
00381 
00382   default:
00383     /* Permit null conversion to same output space */
00384     if (cinfo->out_color_space == cinfo->jpeg_color_space) {
00385       cinfo->out_color_components = cinfo->num_components;
00386       cconvert->pub.color_convert = null_convert;
00387     } else          /* unsupported non-null conversion */
00388       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
00389     break;
00390   }
00391 
00392   if (cinfo->quantize_colors)
00393     cinfo->output_components = 1; /* single colormapped output component */
00394   else
00395     cinfo->output_components = cinfo->out_color_components;
00396 }

Generated on Sat May 26 2012 04:18:11 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.