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

jccolor.c
Go to the documentation of this file.
00001 /*
00002  * jccolor.c
00003  *
00004  * Copyright (C) 1991-1996, 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 input 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_converter pub; /* public fields */
00020 
00021   /* Private state for RGB->YCC conversion */
00022   INT32 * rgb_ycc_tab;      /* => table for RGB to YCbCr conversion */
00023 } my_color_converter;
00024 
00025 typedef my_color_converter * my_cconvert_ptr;
00026 
00027 
00028 /**************** RGB -> YCbCr conversion: most common case **************/
00029 
00030 /*
00031  * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
00032  * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
00033  * The conversion equations to be implemented are therefore
00034  *  Y  =  0.29900 * R + 0.58700 * G + 0.11400 * B
00035  *  Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B  + CENTERJSAMPLE
00036  *  Cr =  0.50000 * R - 0.41869 * G - 0.08131 * B  + CENTERJSAMPLE
00037  * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
00038  * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2,
00039  * rather than CENTERJSAMPLE, for Cb and Cr.  This gave equal positive and
00040  * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0)
00041  * were not represented exactly.  Now we sacrifice exact representation of
00042  * maximum red and maximum blue in order to get exact grayscales.
00043  *
00044  * To avoid floating-point arithmetic, we represent the fractional constants
00045  * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
00046  * the products by 2^16, with appropriate rounding, to get the correct answer.
00047  *
00048  * For even more speed, we avoid doing any multiplications in the inner loop
00049  * by precalculating the constants times R,G,B for all possible values.
00050  * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
00051  * for 12-bit samples it is still acceptable.  It's not very reasonable for
00052  * 16-bit samples, but if you want lossless storage you shouldn't be changing
00053  * colorspace anyway.
00054  * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included
00055  * in the tables to save adding them separately in the inner loop.
00056  */
00057 
00058 #define SCALEBITS   16  /* speediest right-shift on some machines */
00059 #define CBCR_OFFSET ((INT32) CENTERJSAMPLE << SCALEBITS)
00060 #define ONE_HALF    ((INT32) 1 << (SCALEBITS-1))
00061 #define FIX(x)      ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
00062 
00063 /* We allocate one big table and divide it up into eight parts, instead of
00064  * doing eight alloc_small requests.  This lets us use a single table base
00065  * address, which can be held in a register in the inner loops on many
00066  * machines (more than can hold all eight addresses, anyway).
00067  */
00068 
00069 #define R_Y_OFF     0           /* offset to R => Y section */
00070 #define G_Y_OFF     (1*(MAXJSAMPLE+1))  /* offset to G => Y section */
00071 #define B_Y_OFF     (2*(MAXJSAMPLE+1))  /* etc. */
00072 #define R_CB_OFF    (3*(MAXJSAMPLE+1))
00073 #define G_CB_OFF    (4*(MAXJSAMPLE+1))
00074 #define B_CB_OFF    (5*(MAXJSAMPLE+1))
00075 #define R_CR_OFF    B_CB_OFF        /* B=>Cb, R=>Cr are the same */
00076 #define G_CR_OFF    (6*(MAXJSAMPLE+1))
00077 #define B_CR_OFF    (7*(MAXJSAMPLE+1))
00078 #define TABLE_SIZE  (8*(MAXJSAMPLE+1))
00079 
00080 
00081 /*
00082  * Initialize for RGB->YCC colorspace conversion.
00083  */
00084 
00085 METHODDEF(void)
00086 rgb_ycc_start (j_compress_ptr cinfo)
00087 {
00088   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
00089   INT32 * rgb_ycc_tab;
00090   INT32 i;
00091 
00092   /* Allocate and fill in the conversion tables. */
00093   cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *)
00094     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00095                 (TABLE_SIZE * SIZEOF(INT32)));
00096 
00097   for (i = 0; i <= MAXJSAMPLE; i++) {
00098     rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i;
00099     rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i;
00100     rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i     + ONE_HALF;
00101     rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i;
00102     rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i;
00103     /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr.
00104      * This ensures that the maximum output will round to MAXJSAMPLE
00105      * not MAXJSAMPLE+1, and thus that we don't have to range-limit.
00106      */
00107     rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i    + CBCR_OFFSET + ONE_HALF-1;
00108 /*  B=>Cb and R=>Cr tables are the same
00109     rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i    + CBCR_OFFSET + ONE_HALF-1;
00110 */
00111     rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i;
00112     rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i;
00113   }
00114 }
00115 
00116 
00117 /*
00118  * Convert some rows of samples to the JPEG colorspace.
00119  *
00120  * Note that we change from the application's interleaved-pixel format
00121  * to our internal noninterleaved, one-plane-per-component format.
00122  * The input buffer is therefore three times as wide as the output buffer.
00123  *
00124  * A starting row offset is provided only for the output buffer.  The caller
00125  * can easily adjust the passed input_buf value to accommodate any row
00126  * offset required on that side.
00127  */
00128 
00129 METHODDEF(void)
00130 rgb_ycc_convert (j_compress_ptr cinfo,
00131          JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
00132          JDIMENSION output_row, int num_rows)
00133 {
00134   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
00135   register int r, g, b;
00136   register INT32 * ctab = cconvert->rgb_ycc_tab;
00137   register JSAMPROW inptr;
00138   register JSAMPROW outptr0, outptr1, outptr2;
00139   register JDIMENSION col;
00140   JDIMENSION num_cols = cinfo->image_width;
00141 
00142   while (--num_rows >= 0) {
00143     inptr = *input_buf++;
00144     outptr0 = output_buf[0][output_row];
00145     outptr1 = output_buf[1][output_row];
00146     outptr2 = output_buf[2][output_row];
00147     output_row++;
00148     for (col = 0; col < num_cols; col++) {
00149       r = GETJSAMPLE(inptr[RGB_RED]);
00150       g = GETJSAMPLE(inptr[RGB_GREEN]);
00151       b = GETJSAMPLE(inptr[RGB_BLUE]);
00152       inptr += RGB_PIXELSIZE;
00153       /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
00154        * must be too; we do not need an explicit range-limiting operation.
00155        * Hence the value being shifted is never negative, and we don't
00156        * need the general RIGHT_SHIFT macro.
00157        */
00158       /* Y */
00159       outptr0[col] = (JSAMPLE)
00160         ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
00161          >> SCALEBITS);
00162       /* Cb */
00163       outptr1[col] = (JSAMPLE)
00164         ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF])
00165          >> SCALEBITS);
00166       /* Cr */
00167       outptr2[col] = (JSAMPLE)
00168         ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF])
00169          >> SCALEBITS);
00170     }
00171   }
00172 }
00173 
00174 
00175 /**************** Cases other than RGB -> YCbCr **************/
00176 
00177 
00178 /*
00179  * Convert some rows of samples to the JPEG colorspace.
00180  * This version handles RGB->grayscale conversion, which is the same
00181  * as the RGB->Y portion of RGB->YCbCr.
00182  * We assume rgb_ycc_start has been called (we only use the Y tables).
00183  */
00184 
00185 METHODDEF(void)
00186 rgb_gray_convert (j_compress_ptr cinfo,
00187           JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
00188           JDIMENSION output_row, int num_rows)
00189 {
00190   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
00191   register int r, g, b;
00192   register INT32 * ctab = cconvert->rgb_ycc_tab;
00193   register JSAMPROW inptr;
00194   register JSAMPROW outptr;
00195   register JDIMENSION col;
00196   JDIMENSION num_cols = cinfo->image_width;
00197 
00198   while (--num_rows >= 0) {
00199     inptr = *input_buf++;
00200     outptr = output_buf[0][output_row];
00201     output_row++;
00202     for (col = 0; col < num_cols; col++) {
00203       r = GETJSAMPLE(inptr[RGB_RED]);
00204       g = GETJSAMPLE(inptr[RGB_GREEN]);
00205       b = GETJSAMPLE(inptr[RGB_BLUE]);
00206       inptr += RGB_PIXELSIZE;
00207       /* Y */
00208       outptr[col] = (JSAMPLE)
00209         ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
00210          >> SCALEBITS);
00211     }
00212   }
00213 }
00214 
00215 
00216 /*
00217  * Convert some rows of samples to the JPEG colorspace.
00218  * This version handles Adobe-style CMYK->YCCK conversion,
00219  * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same
00220  * conversion as above, while passing K (black) unchanged.
00221  * We assume rgb_ycc_start has been called.
00222  */
00223 
00224 METHODDEF(void)
00225 cmyk_ycck_convert (j_compress_ptr cinfo,
00226            JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
00227            JDIMENSION output_row, int num_rows)
00228 {
00229   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
00230   register int r, g, b;
00231   register INT32 * ctab = cconvert->rgb_ycc_tab;
00232   register JSAMPROW inptr;
00233   register JSAMPROW outptr0, outptr1, outptr2, outptr3;
00234   register JDIMENSION col;
00235   JDIMENSION num_cols = cinfo->image_width;
00236 
00237   while (--num_rows >= 0) {
00238     inptr = *input_buf++;
00239     outptr0 = output_buf[0][output_row];
00240     outptr1 = output_buf[1][output_row];
00241     outptr2 = output_buf[2][output_row];
00242     outptr3 = output_buf[3][output_row];
00243     output_row++;
00244     for (col = 0; col < num_cols; col++) {
00245       r = MAXJSAMPLE - GETJSAMPLE(inptr[0]);
00246       g = MAXJSAMPLE - GETJSAMPLE(inptr[1]);
00247       b = MAXJSAMPLE - GETJSAMPLE(inptr[2]);
00248       /* K passes through as-is */
00249       outptr3[col] = inptr[3];  /* don't need GETJSAMPLE here */
00250       inptr += 4;
00251       /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
00252        * must be too; we do not need an explicit range-limiting operation.
00253        * Hence the value being shifted is never negative, and we don't
00254        * need the general RIGHT_SHIFT macro.
00255        */
00256       /* Y */
00257       outptr0[col] = (JSAMPLE)
00258         ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
00259          >> SCALEBITS);
00260       /* Cb */
00261       outptr1[col] = (JSAMPLE)
00262         ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF])
00263          >> SCALEBITS);
00264       /* Cr */
00265       outptr2[col] = (JSAMPLE)
00266         ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF])
00267          >> SCALEBITS);
00268     }
00269   }
00270 }
00271 
00272 
00273 /*
00274  * Convert some rows of samples to the JPEG colorspace.
00275  * This version handles grayscale output with no conversion.
00276  * The source can be either plain grayscale or YCbCr (since Y == gray).
00277  */
00278 
00279 METHODDEF(void)
00280 grayscale_convert (j_compress_ptr cinfo,
00281            JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
00282            JDIMENSION output_row, int num_rows)
00283 {
00284   register JSAMPROW inptr;
00285   register JSAMPROW outptr;
00286   register JDIMENSION col;
00287   JDIMENSION num_cols = cinfo->image_width;
00288   int instride = cinfo->input_components;
00289 
00290   while (--num_rows >= 0) {
00291     inptr = *input_buf++;
00292     outptr = output_buf[0][output_row];
00293     output_row++;
00294     for (col = 0; col < num_cols; col++) {
00295       outptr[col] = inptr[0];   /* don't need GETJSAMPLE() here */
00296       inptr += instride;
00297     }
00298   }
00299 }
00300 
00301 
00302 /*
00303  * Convert some rows of samples to the JPEG colorspace.
00304  * This version handles multi-component colorspaces without conversion.
00305  * We assume input_components == num_components.
00306  */
00307 
00308 METHODDEF(void)
00309 null_convert (j_compress_ptr cinfo,
00310           JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
00311           JDIMENSION output_row, int num_rows)
00312 {
00313   register JSAMPROW inptr;
00314   register JSAMPROW outptr;
00315   register JDIMENSION col;
00316   register int ci;
00317   int nc = cinfo->num_components;
00318   JDIMENSION num_cols = cinfo->image_width;
00319 
00320   while (--num_rows >= 0) {
00321     /* It seems fastest to make a separate pass for each component. */
00322     for (ci = 0; ci < nc; ci++) {
00323       inptr = *input_buf;
00324       outptr = output_buf[ci][output_row];
00325       for (col = 0; col < num_cols; col++) {
00326     outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */
00327     inptr += nc;
00328       }
00329     }
00330     input_buf++;
00331     output_row++;
00332   }
00333 }
00334 
00335 
00336 /*
00337  * Empty method for start_pass.
00338  */
00339 
00340 METHODDEF(void)
00341 null_method (j_compress_ptr cinfo)
00342 {
00343   /* no work needed */
00344 }
00345 
00346 
00347 /*
00348  * Module initialization routine for input colorspace conversion.
00349  */
00350 
00351 GLOBAL(void)
00352 jinit_color_converter (j_compress_ptr cinfo)
00353 {
00354   my_cconvert_ptr cconvert;
00355 
00356   cconvert = (my_cconvert_ptr)
00357     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
00358                 SIZEOF(my_color_converter));
00359   cinfo->cconvert = (struct jpeg_color_converter *) cconvert;
00360   /* set start_pass to null method until we find out differently */
00361   cconvert->pub.start_pass = null_method;
00362 
00363   /* Make sure input_components agrees with in_color_space */
00364   switch (cinfo->in_color_space) {
00365   case JCS_GRAYSCALE:
00366     if (cinfo->input_components != 1)
00367       ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
00368     break;
00369 
00370   case JCS_RGB:
00371 #if RGB_PIXELSIZE != 3
00372     if (cinfo->input_components != RGB_PIXELSIZE)
00373       ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
00374     break;
00375 #endif /* else share code with YCbCr */
00376 
00377   case JCS_YCbCr:
00378     if (cinfo->input_components != 3)
00379       ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
00380     break;
00381 
00382   case JCS_CMYK:
00383   case JCS_YCCK:
00384     if (cinfo->input_components != 4)
00385       ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
00386     break;
00387 
00388   default:          /* JCS_UNKNOWN can be anything */
00389     if (cinfo->input_components < 1)
00390       ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
00391     break;
00392   }
00393 
00394   /* Check num_components, set conversion method based on requested space */
00395   switch (cinfo->jpeg_color_space) {
00396   case JCS_GRAYSCALE:
00397     if (cinfo->num_components != 1)
00398       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
00399     if (cinfo->in_color_space == JCS_GRAYSCALE)
00400       cconvert->pub.color_convert = grayscale_convert;
00401     else if (cinfo->in_color_space == JCS_RGB) {
00402       cconvert->pub.start_pass = rgb_ycc_start;
00403       cconvert->pub.color_convert = rgb_gray_convert;
00404     } else if (cinfo->in_color_space == JCS_YCbCr)
00405       cconvert->pub.color_convert = grayscale_convert;
00406     else
00407       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
00408     break;
00409 
00410   case JCS_RGB:
00411     if (cinfo->num_components != 3)
00412       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
00413     if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3)
00414       cconvert->pub.color_convert = null_convert;
00415     else
00416       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
00417     break;
00418 
00419   case JCS_YCbCr:
00420     if (cinfo->num_components != 3)
00421       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
00422     if (cinfo->in_color_space == JCS_RGB) {
00423       cconvert->pub.start_pass = rgb_ycc_start;
00424       cconvert->pub.color_convert = rgb_ycc_convert;
00425     } else if (cinfo->in_color_space == JCS_YCbCr)
00426       cconvert->pub.color_convert = null_convert;
00427     else
00428       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
00429     break;
00430 
00431   case JCS_CMYK:
00432     if (cinfo->num_components != 4)
00433       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
00434     if (cinfo->in_color_space == JCS_CMYK)
00435       cconvert->pub.color_convert = null_convert;
00436     else
00437       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
00438     break;
00439 
00440   case JCS_YCCK:
00441     if (cinfo->num_components != 4)
00442       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
00443     if (cinfo->in_color_space == JCS_CMYK) {
00444       cconvert->pub.start_pass = rgb_ycc_start;
00445       cconvert->pub.color_convert = cmyk_ycck_convert;
00446     } else if (cinfo->in_color_space == JCS_YCCK)
00447       cconvert->pub.color_convert = null_convert;
00448     else
00449       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
00450     break;
00451 
00452   default:          /* allow null conversion of JCS_UNKNOWN */
00453     if (cinfo->jpeg_color_space != cinfo->in_color_space ||
00454     cinfo->num_components != cinfo->input_components)
00455       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
00456     cconvert->pub.color_convert = null_convert;
00457     break;
00458   }
00459 }

Generated on Fri May 25 2012 04:17:31 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.