home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume44 / jpeg / part19 / jccolor.c next >
C/C++ Source or Header  |  1994-09-27  |  14KB  |  450 lines

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