home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / print / print-util.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-10  |  55.6 KB  |  2,266 lines

  1. /*
  2.  * "$Id: print-util.c,v 1.22 2000/12/02 17:06:50 mitch Exp $"
  3.  *
  4.  *   Print plug-in driver utility functions for the GIMP.
  5.  *
  6.  *   Copyright 1997-2000 Michael Sweet (mike@easysw.com) and
  7.  *    Robert Krawitz (rlk@alum.mit.edu)
  8.  *
  9.  *   This program is free software; you can redistribute it and/or modify it
  10.  *   under the terms of the GNU General Public License as published by the Free
  11.  *   Software Foundation; either version 2 of the License, or (at your option)
  12.  *   any later version.
  13.  *
  14.  *   This program is distributed in the hope that it will be useful, but
  15.  *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  16.  *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  17.  *   for more details.
  18.  *
  19.  *   You should have received a copy of the GNU General Public License
  20.  *   along with this program; if not, write to the Free Software
  21.  *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  22.  */
  23.  
  24. /*
  25.  * This file must include only standard C header files.  The core code must
  26.  * compile on generic platforms that don't support glib, gimp, gtk, etc.
  27.  */
  28.  
  29. /* #define PRINT_DEBUG */
  30.  
  31.  
  32. #include "print.h"
  33. #include <math.h>
  34. #include <limits.h>
  35.  
  36. #ifndef __GNUC__
  37. #  define inline
  38. #endif /* !__GNUC__ */
  39.  
  40. typedef struct
  41. {
  42.   unsigned steps;
  43.   unsigned short *composite;
  44.   unsigned short *red;
  45.   unsigned short *green;
  46.   unsigned short *blue;
  47.   unsigned shiftval;
  48.   unsigned bin_size;
  49.   unsigned bin_shift;
  50. } lut_t;
  51.  
  52. /*
  53.  * RGB to grayscale luminance constants...
  54.  */
  55.  
  56. #define LUM_RED        31
  57. #define LUM_GREEN    61
  58. #define LUM_BLUE    8
  59.  
  60. /* rgb/hsv conversions taken from Gimp common/autostretch_hsv.c */
  61.  
  62. static vars_t default_vars =
  63. {
  64.     "",            /* Name of file or command to print to */
  65.     "ps2",            /* Name of printer "driver" */
  66.     "",            /* Name of PPD file */
  67.     OUTPUT_COLOR,        /* Color or grayscale output */
  68.     "",            /* Output resolution */
  69.     "",            /* Size of output media */
  70.     "",            /* Type of output media */
  71.     "",            /* Source of output media */
  72.     "",            /* Ink type */
  73.     "",            /* Dither algorithm */
  74.     1.0,            /* Output brightness */
  75.     100.0,            /* Scaling (100% means entire printable area, */
  76.                 /*          -XXX means scale by PPI) */
  77.     -1,            /* Orientation (-1 = automatic) */
  78.     -1,            /* X offset (-1 = center) */
  79.     -1,            /* Y offset (-1 = center) */
  80.     1.0,            /* Screen gamma */
  81.     1.0,            /* Contrast */
  82.     1.0,            /* Cyan */
  83.     1.0,            /* Magenta */
  84.     1.0,            /* Yellow */
  85.     0,            /* Linear */
  86.     1.0,            /* Output saturation */
  87.     1.0,            /* Density */
  88.     IMAGE_CONTINUOUS,    /* Image type */
  89.     0,            /* Unit 0=Inch */
  90.     1.0,            /* Application gamma placeholder */
  91.     0,            /* Page width */
  92.     0            /* Page height */
  93. };
  94.  
  95. static vars_t min_vars =
  96. {
  97.     "",            /* Name of file or command to print to */
  98.     "ps2",            /* Name of printer "driver" */
  99.     "",            /* Name of PPD file */
  100.     OUTPUT_COLOR,        /* Color or grayscale output */
  101.     "",            /* Output resolution */
  102.     "",            /* Size of output media */
  103.     "",            /* Type of output media */
  104.     "",            /* Source of output media */
  105.     "",            /* Ink type */
  106.     "",            /* Dither algorithm */
  107.     0,            /* Output brightness */
  108.     5.0,            /* Scaling (100% means entire printable area, */
  109.                 /*          -XXX means scale by PPI) */
  110.     -1,            /* Orientation (-1 = automatic) */
  111.     -1,            /* X offset (-1 = center) */
  112.     -1,            /* Y offset (-1 = center) */
  113.     0.1,            /* Screen gamma */
  114.     0,            /* Contrast */
  115.     0,            /* Cyan */
  116.     0,            /* Magenta */
  117.     0,            /* Yellow */
  118.     0,            /* Linear */
  119.     0,            /* Output saturation */
  120.     .1,            /* Density */
  121.     IMAGE_CONTINUOUS,    /* Image type */
  122.     0,            /* Unit 0=Inch */
  123.     1.0,            /* Application gamma placeholder */
  124.     0,            /* Page width */
  125.     0            /* Page height */
  126. };
  127.  
  128. static vars_t max_vars =
  129. {
  130.     "",            /* Name of file or command to print to */
  131.     "ps2",            /* Name of printer "driver" */
  132.     "",            /* Name of PPD file */
  133.     OUTPUT_COLOR,        /* Color or grayscale output */
  134.     "",            /* Output resolution */
  135.     "",            /* Size of output media */
  136.     "",            /* Type of output media */
  137.     "",            /* Source of output media */
  138.     "",            /* Ink type */
  139.     "",            /* Dither algorithm */
  140.     2.0,            /* Output brightness */
  141.     100.0,            /* Scaling (100% means entire printable area, */
  142.                 /*          -XXX means scale by PPI) */
  143.     -1,            /* Orientation (-1 = automatic) */
  144.     -1,            /* X offset (-1 = center) */
  145.     -1,            /* Y offset (-1 = center) */
  146.     4.0,            /* Screen gamma */
  147.     4.0,            /* Contrast */
  148.     4.0,            /* Cyan */
  149.     4.0,            /* Magenta */
  150.     4.0,            /* Yellow */
  151.     0,            /* Linear */
  152.     9.0,            /* Output saturation */
  153.     2.0,            /* Density */
  154.     IMAGE_CONTINUOUS,    /* Image type */
  155.     0,            /* Unit 0=Inch */
  156.     1.0,            /* Application gamma placeholder */
  157.     0,            /* Page width */
  158.     0            /* Page height */
  159. };
  160.  
  161. #define FMAX(a, b) ((a) > (b) ? (a) : (b))
  162. #define FMIN(a, b) ((a) < (b) ? (a) : (b))
  163.  
  164. static inline void
  165. calc_rgb_to_hsl(unsigned short *rgb, double *hue, double *sat,
  166.         double *lightness)
  167. {
  168.   double red, green, blue;
  169.   double h, s, l;
  170.   double min, max;
  171.   double delta;
  172.   int maxval;
  173.  
  174.   red   = rgb[0] / 65535.0;
  175.   green = rgb[1] / 65535.0;
  176.   blue  = rgb[2] / 65535.0;
  177.  
  178.   if (red > green)
  179.     {
  180.       if (red > blue)
  181.     {
  182.       max = red;
  183.       maxval = 0;
  184.     }
  185.       else
  186.     {
  187.       max = blue;
  188.       maxval = 2;
  189.     }
  190.       min = FMIN(green, blue);
  191.     }
  192.   else
  193.     {
  194.       if (green > blue)
  195.     {
  196.       max = green;
  197.       maxval = 1;
  198.     }
  199.       else
  200.     {
  201.       max = blue;
  202.       maxval = 2;
  203.     }
  204.       min = FMIN(red, blue);
  205.     }
  206.  
  207.   l = (max + min) / 2.0;
  208.   delta = max - min;
  209.  
  210.   if (delta < .000001)    /* Suggested by Eugene Anikin <eugene@anikin.com> */
  211.     {
  212.       s = 0.0;
  213.       h = 0.0;
  214.     }
  215.   else
  216.     {
  217.       if (l <= .5)
  218.     s = delta / (max + min);
  219.       else
  220.     s = delta / (2 - max - min);
  221.  
  222.       if (maxval == 0)
  223.     h = (green - blue) / delta;
  224.       else if (maxval == 1)
  225.     h = 2 + (blue - red) / delta;
  226.       else
  227.     h = 4 + (red - green) / delta;
  228.  
  229.       if (h < 0.0)
  230.     h += 6.0;
  231.       else if (h > 6.0)
  232.     h -= 6.0;
  233.     }
  234.  
  235.   *hue = h;
  236.   *sat = s;
  237.   *lightness = l;
  238. }
  239.  
  240. static inline double
  241. hsl_value(double n1, double n2, double hue)
  242. {
  243.   if (hue < 0)
  244.     hue += 6.0;
  245.   else if (hue > 6)
  246.     hue -= 6.0;
  247.   if (hue < 1.0)
  248.     return (n1 + (n2 - n1) * hue);
  249.   else if (hue < 3.0)
  250.     return (n2);
  251.   else if (hue < 4.0)
  252.     return (n1 + (n2 - n1) * (4.0 - hue));
  253.   else
  254.     return (n1);
  255. }
  256.  
  257. static inline void
  258. calc_hsl_to_rgb(unsigned short *rgb, double h, double s, double l)
  259. {
  260.   if (s < .0000001)
  261.     {
  262.       if (l > 1)
  263.     l = 1;
  264.       else if (l < 0)
  265.     l = 0;
  266.       rgb[0] = l * 65535;
  267.       rgb[1] = l * 65535;
  268.       rgb[2] = l * 65535;
  269.     }
  270.   else
  271.     {
  272.       double m1, m2;
  273.       double h1, h2;
  274.       h1 = h + 2;
  275.       h2 = h - 2;
  276.  
  277.       if (l < .5)
  278.     m2 = l * (1 + s);
  279.       else
  280.     m2 = l + s - (l * s);
  281.       m1 = (l * 2) - m2;
  282.       rgb[0] = 65535 * hsl_value(m1, m2, h1);
  283.       rgb[1] = 65535 * hsl_value(m1, m2, h);
  284.       rgb[2] = 65535 * hsl_value(m1, m2, h2);
  285.     }
  286. }
  287.  
  288. static inline void
  289. update_cmyk(unsigned short *rgb)
  290. {
  291.   int c = 65535 - rgb[0];
  292.   int m = 65535 - rgb[1];
  293.   int y = 65535 - rgb[2];
  294.   int nc, nm, ny;
  295.   int k;
  296.   if (c == 0 && m == 0 && y == 0)
  297.     return;
  298.   k = FMIN(FMIN(c, m), y);
  299.  
  300.   /*
  301.    * This is an attempt to achieve better color balance.  The goal
  302.    * is to weaken the pure cyan, magenta, and yellow and strengthen
  303.    * pure red, green, and blue.
  304.    *
  305.    * We also don't want S=1 V=1 cyan to be 100% cyan; it's simply
  306.    * too dark.
  307.    */
  308.  
  309.   nc = (c * 3 + FMIN(c, FMAX(m, y)) * 5 + FMAX(m, y) * 0 + k) / 8;
  310.   nm = (m * 3 + FMIN(m, FMAX(c, y)) * 5 + FMAX(c, y) * 0 + k) / 8;
  311.   ny = (y * 3 + FMIN(y, FMAX(c, m)) * 5 + FMAX(c, m) * 0 + k) / 8;
  312.  
  313.   /*
  314.    * Make sure we didn't go overboard.  We don't want to go too
  315.    * close to white unnecessarily.
  316.    */
  317.   nc = c + (nc - c) / 3;
  318.   nm = m + (nm - m) / 3;
  319.   ny = y + (ny - y) / 3;
  320.  
  321.   if (nc > 65535)
  322.     nc = 65535;
  323.   if (nm > 65535)
  324.     nm = 65535;
  325.   if (ny > 65535)
  326.     ny = 65535;
  327.  
  328.   rgb[0] = 65535 - nc;
  329.   rgb[1] = 65535 - nm;
  330.   rgb[2] = 65535 - ny;
  331. }
  332.  
  333. /*
  334.  * A lot of this stuff needs to be factored out of here
  335.  */
  336. static inline unsigned short
  337. lookup_value(unsigned short value, int lut_size, unsigned short *lut,
  338.          unsigned shiftval, unsigned bin_size, unsigned bin_shift)
  339. {
  340.   unsigned subrange;
  341.   unsigned remainder;
  342.   unsigned below;
  343.   unsigned above;
  344.   if (lut_size == 65536)
  345.     return lut[value];
  346.   subrange = value >> bin_shift;
  347.   remainder = value & (bin_size - 1);
  348.   below = lut[subrange];
  349.   if (remainder == 0)
  350.     return below;
  351.   if (subrange == (bin_size - 1))
  352.     above = lut[subrange];
  353.   else
  354.     above = lut[subrange + 1];
  355.   if (above == below)
  356.     return above;
  357.   else
  358.     return below + (((above - below) * remainder) >> bin_shift);
  359. }
  360.  
  361. /*
  362.  * 'gray_to_gray()' - Convert grayscale image data to grayscale (brightness
  363.  *                    adjusted).
  364.  */
  365.  
  366. static void
  367. gray_to_gray(unsigned char *grayin,    /* I - RGB pixels */
  368.          unsigned short *grayout,    /* O - RGB pixels */
  369.          int        width,        /* I - Width of row */
  370.          int        bpp,        /* I - Bytes-per-pixel in grayin */
  371.          unsigned char *cmap,    /* I - Colormap (unused) */
  372.          const vars_t    *vars
  373.          )
  374. {
  375.   int i0 = -1;
  376.   int i1 = -1;
  377.   int use_previous = 0;
  378.   int o0 = 0;
  379.   lut_t *lut = (lut_t *)(vars->lut);
  380.   while (width > 0)
  381.     {
  382.       if (bpp == 1)
  383.     {
  384.       /*
  385.        * No alpha in image...
  386.        */
  387.       if (i0 == grayin[0])
  388.         use_previous = 1;
  389.       else
  390.         {
  391.           use_previous = 0;
  392.           i0 = grayin[0];
  393.           grayout[0] = lut->composite[grayin[0]];
  394.         }
  395.     }
  396.       else
  397.     {
  398.       if (i0 == grayin[0] && i1 == grayin[1])
  399.         use_previous = 1;
  400.       else
  401.         {
  402.           use_previous = 0;
  403.           i0 = grayin[0];
  404.           i1 = grayin[1];
  405.           grayout[0] = lut->composite[grayin[0] * grayin[1] / 255 +
  406.                            255 - grayin[1]];
  407.         }
  408.     }
  409.       if (use_previous)
  410.     {
  411.       grayout[0] = o0;
  412.     }
  413.       else
  414.     {
  415.       if (vars->density != 1.0)
  416.         {
  417.           double t = (65535.0 + ((grayout[0] - 65535.0) * vars->density));
  418.           if (t < 0.0)
  419.         t = 0.0;
  420.           grayout[0] = t + .5;
  421.         }
  422.       o0 = grayout[0];
  423.     }
  424.       grayin += bpp;
  425.       grayout ++;
  426.       width --;
  427.     }
  428. }
  429.  
  430. static void
  431. gray_to_monochrome(unsigned char *grayin,    /* I - RGB pixels */
  432.            unsigned short *grayout,    /* O - RGB pixels */
  433.            int        width,        /* I - Width of row */
  434.            int        bpp,        /* I - Bytes-per-pixel in grayin */
  435.            unsigned char *cmap,        /* I - Colormap (unused) */
  436.            const vars_t    *vars
  437.            )
  438. {
  439.   int i0 = -1;
  440.   int i1 = -1;
  441.   int use_previous = 0;
  442.   int o0 = 0;
  443.   lut_t *lut = (lut_t *)(vars->lut);
  444.   while (width > 0)
  445.     {
  446.       if (bpp == 1)
  447.     {
  448.       /*
  449.        * No alpha in image...
  450.        */
  451.       if (i0 == grayin[0])
  452.         use_previous = 1;
  453.       else
  454.         {
  455.           use_previous = 0;
  456.           i0 = grayin[0];
  457.           grayout[0] = lut->composite[grayin[0]];
  458.         }
  459.     }
  460.       else
  461.     {
  462.       if (i0 == grayin[0] && i1 == grayin[1])
  463.         use_previous = 1;
  464.       else
  465.         {
  466.           use_previous = 0;
  467.           i0 = grayin[0];
  468.           i1 = grayin[1];
  469.           grayout[0] = lut->composite[grayin[0] * grayin[1] / 255 +
  470.                            255 - grayin[1]];
  471.         }
  472.     }
  473.       if (use_previous)
  474.     {
  475.       grayout[0] = o0;
  476.     }
  477.       else
  478.     {
  479.       if (grayout[0] < 32768)
  480.         grayout[0] = 0;
  481.       else
  482.         grayout[0] = 65535;
  483.       o0 = grayout[0];
  484.     }
  485.       grayin += bpp;
  486.       grayout ++;
  487.       width --;
  488.     }
  489. }
  490.  
  491. /*
  492.  * 'indexed_to_gray()' - Convert indexed image data to grayscale.
  493.  */
  494.  
  495. static void
  496. indexed_to_gray(unsigned char *indexed,        /* I - Indexed pixels */
  497.         unsigned short *gray,        /* O - Grayscale pixels */
  498.         int    width,            /* I - Width of row */
  499.         int    bpp,            /* I - bpp in indexed */
  500.         unsigned char *cmap,        /* I - Colormap */
  501.         const vars_t   *vars
  502.         )
  503. {
  504.   int i0 = -1;
  505.   int i1 = -1;
  506.   int o0 = 0;
  507.   int use_previous = 0;
  508.   int i;
  509.   lut_t *lut = (lut_t *)(vars->lut);
  510.   unsigned char    gray_cmap[256];        /* Grayscale colormap */
  511.  
  512.   /* Really should precompute this silly thing... */
  513.   for (i = 0; i < 256; i ++, cmap += 3)
  514.     gray_cmap[i] = (cmap[0] * LUM_RED +
  515.             cmap[1] * LUM_GREEN +
  516.             cmap[2] * LUM_BLUE) / 100;
  517.  
  518.   while (width > 0)
  519.     {
  520.       if (bpp == 1)
  521.     {
  522.       /*
  523.        * No alpha in image...
  524.        */
  525.       if (i0 == indexed[0])
  526.         use_previous = 1;
  527.       else
  528.         {
  529.           use_previous = 0;
  530.           i0 = indexed[0];
  531.           gray[0] = lut->composite[gray_cmap[i0]];
  532.         }
  533.     }
  534.       else
  535.     {
  536.       if (i0 == indexed[0] && i1 == indexed[1])
  537.         use_previous = 1;
  538.       else
  539.         {
  540.           use_previous = 0;
  541.           i0 = indexed[0];
  542.           i1 = indexed[1];
  543.           gray[0] = lut->composite[gray_cmap[i0 * i1 / 255]
  544.                         + 255 - i1];
  545.         }
  546.     }
  547.       if (use_previous)
  548.     {
  549.       gray[0] = o0;
  550.     }
  551.       else
  552.     {
  553.       if (vars->density != 1.0)
  554.         {
  555.           double t = (65535.0 + ((gray[0] - 65535.0) * vars->density));
  556.           if (t < 0.0)
  557.         t = 0.0;
  558.           gray[0] = t + .5;
  559.         }
  560.       o0 = gray[0];
  561.     }
  562.       indexed += bpp;
  563.       gray ++;
  564.       width --;
  565.     }
  566. }
  567.  
  568. static void
  569. indexed_to_monochrome(unsigned char *indexed,    /* I - Indexed pixels */
  570.               unsigned short *gray,    /* O - Grayscale pixels */
  571.               int    width,        /* I - Width of row */
  572.               int    bpp,        /* I - bpp in indexed */
  573.               unsigned char *cmap,    /* I - Colormap */
  574.               const vars_t   *vars
  575.               )
  576. {
  577.   int i0 = -1;
  578.   int i1 = -1;
  579.   int o0 = 0;
  580.   int use_previous = 0;
  581.   int i;
  582.   lut_t *lut = (lut_t *)(vars->lut);
  583.   unsigned char    gray_cmap[256];        /* Grayscale colormap */
  584.  
  585.   /* Really should precompute this silly thing... */
  586.   for (i = 0; i < 256; i ++, cmap += 3)
  587.     gray_cmap[i] = (cmap[0] * LUM_RED +
  588.             cmap[1] * LUM_GREEN +
  589.             cmap[2] * LUM_BLUE) / 100;
  590.  
  591.   while (width > 0)
  592.     {
  593.       if (bpp == 1)
  594.     {
  595.       /*
  596.        * No alpha in image...
  597.        */
  598.       if (i0 == indexed[0])
  599.         use_previous = 1;
  600.       else
  601.         {
  602.           use_previous = 0;
  603.           i0 = indexed[0];
  604.           gray[0] = lut->composite[gray_cmap[i0]];
  605.         }
  606.     }
  607.       else
  608.     {
  609.       if (i0 == indexed[0] && i1 == indexed[1])
  610.         use_previous = 1;
  611.       else
  612.         {
  613.           use_previous = 0;
  614.           i0 = indexed[0];
  615.           i1 = indexed[1];
  616.           gray[0] = lut->composite[gray_cmap[i0 * i1 / 255]
  617.                       + 255 - i1];
  618.         }
  619.     }
  620.       if (use_previous)
  621.     {
  622.       gray[0] = o0;
  623.     }
  624.       else
  625.     {
  626.       if (gray[0] < 32768)
  627.         gray[0] = 0;
  628.       else
  629.         gray[0] = 65535;
  630.       o0 = gray[0];
  631.     }
  632.       indexed += bpp;
  633.       gray ++;
  634.       width --;
  635.     }
  636. }
  637.  
  638. /*
  639.  * 'rgb_to_gray()' - Convert RGB image data to grayscale.
  640.  */
  641.  
  642. static void
  643. rgb_to_gray(unsigned char *rgb,        /* I - RGB pixels */
  644.         unsigned short *gray,    /* O - Grayscale pixels */
  645.         int    width,        /* I - Width of row */
  646.         int    bpp,            /* I - Bytes-per-pixel in RGB */
  647.         unsigned char *cmap,    /* I - Colormap (unused) */
  648.         const vars_t   *vars
  649.         )
  650. {
  651.   int i0 = -1;
  652.   int i1 = -1;
  653.   int i2 = -1;
  654.   int i3 = -1;
  655.   int o0 = 0;
  656.   int use_previous = 0;
  657.   lut_t *lut = (lut_t *)(vars->lut);
  658.   while (width > 0)
  659.     {
  660.       if (bpp == 3)
  661.     {
  662.       /*
  663.        * No alpha in image...
  664.        */
  665.       if (i0 == rgb[0] && i1 == rgb[1] && i2 == rgb[2])
  666.         use_previous = 1;
  667.       else
  668.         {
  669.           use_previous = 0;
  670.           i0 = rgb[0];
  671.           i1 = rgb[1];
  672.           i2 = rgb[2];
  673.           gray[0] = lut->composite[(rgb[0] * LUM_RED +
  674.                     rgb[1] * LUM_GREEN +
  675.                     rgb[2] * LUM_BLUE) / 100];
  676.         }
  677.     }
  678.       else
  679.     {
  680.       if (i0 == rgb[0] && i1 == rgb[1] && i2 == rgb[2] && i3 == rgb[3])
  681.         use_previous = 1;
  682.       else
  683.         {
  684.           use_previous = 0;
  685.           i0 = rgb[0];
  686.           i1 = rgb[1];
  687.           i2 = rgb[2];
  688.           i3 = rgb[3];
  689.       
  690.           gray[0] = lut->composite[((rgb[0] * LUM_RED +
  691.                      rgb[1] * LUM_GREEN +
  692.                      rgb[2] * LUM_BLUE) *
  693.                     rgb[3] / 25500 + 255 - rgb[3])];
  694.         }
  695.     }
  696.       if (use_previous)
  697.     {
  698.       gray[0] = o0;
  699.     }
  700.       else
  701.     {
  702.       if (vars->density != 1.0)
  703.         {
  704.           double t = (65535.0 + ((gray[0] - 65535.0) * vars->density));
  705.           if (t < 0.0)
  706.         t = 0.0;
  707.           gray[0] = t + .5;
  708.         }
  709.       o0 = gray[0];
  710.     }
  711.       rgb += bpp;
  712.       gray ++;
  713.       width --;
  714.     }
  715. }
  716.  
  717. static void
  718. rgb_to_monochrome(unsigned char *rgb,    /* I - RGB pixels */
  719.           unsigned short *gray,    /* O - Grayscale pixels */
  720.           int    width,        /* I - Width of row */
  721.           int    bpp,        /* I - Bytes-per-pixel in RGB */
  722.           unsigned char *cmap,    /* I - Colormap (unused) */
  723.           const vars_t   *vars
  724.           )
  725. {
  726.   int i0 = -1;
  727.   int i1 = -1;
  728.   int i2 = -1;
  729.   int i3 = -1;
  730.   int o0 = 0;
  731.   int use_previous = 0;
  732.   lut_t *lut = (lut_t *)(vars->lut);
  733.   while (width > 0)
  734.     {
  735.       if (bpp == 3)
  736.     {
  737.       /*
  738.        * No alpha in image...
  739.        */
  740.       if (i0 == rgb[0] && i1 == rgb[1] && i2 == rgb[2])
  741.         use_previous = 1;
  742.       else
  743.         {
  744.           use_previous = 0;
  745.           i0 = rgb[0];
  746.           i1 = rgb[1];
  747.           i2 = rgb[2];
  748.           gray[0] = lut->composite[(rgb[0] * LUM_RED +
  749.                     rgb[1] * LUM_GREEN +
  750.                     rgb[2] * LUM_BLUE) / 100];
  751.         }
  752.     }
  753.       else
  754.     {
  755.       if (i0 == rgb[0] && i1 == rgb[1] && i2 == rgb[2] && i3 == rgb[3])
  756.         use_previous = 1;
  757.       else
  758.         {
  759.           use_previous = 0;
  760.           i0 = rgb[0];
  761.           i1 = rgb[1];
  762.           i2 = rgb[2];
  763.           i3 = rgb[3];
  764.       
  765.           gray[0] = lut->composite[((rgb[0] * LUM_RED +
  766.                      rgb[1] * LUM_GREEN +
  767.                      rgb[2] * LUM_BLUE) *
  768.                     rgb[3] / 25500 + 255 - rgb[3])];
  769.         }
  770.     }
  771.       if (use_previous)
  772.     {
  773.       gray[0] = o0;
  774.     }
  775.       else
  776.     {
  777.       if (gray[0] < 32768)
  778.         gray[0] = 0;
  779.       else
  780.         gray[0] = 65535;
  781.       o0 = gray[0];
  782.     }
  783.       rgb += bpp;
  784.       gray ++;
  785.       width --;
  786.     }
  787. }
  788.  
  789. /*
  790.  * 'rgb_to_rgb()' - Convert rgb image data to RGB.
  791.  */
  792.  
  793. static void
  794. rgb_to_rgb(unsigned char    *rgbin,        /* I - RGB pixels */
  795.        unsigned short     *rgbout,    /* O - RGB pixels */
  796.        int            width,        /* I - Width of row */
  797.        int            bpp,        /* I - Bytes/pix in indexed */
  798.        unsigned char     *cmap,        /* I - Colormap */
  799.        const vars_t      *vars
  800.        )
  801. {
  802.   unsigned ld = vars->density * 65536;
  803.   double isat = 1.0;
  804.   double ssat = vars->saturation;
  805.   int i0 = -1;
  806.   int i1 = -1;
  807.   int i2 = -1;
  808.   int i3 = -1;
  809.   int o0 = 0;
  810.   int o1 = 0;
  811.   int o2 = 0;
  812.   int use_previous = 0;
  813.   lut_t *lut = (lut_t *)(vars->lut);
  814.   int compute_saturation = ssat <= .99999 || ssat >= 1.00001;
  815.   int split_saturation = ssat > 1.4;
  816.   if (split_saturation)
  817.     ssat = sqrt(ssat);
  818.   if (ssat > 1)
  819.     isat = 1.0 / ssat;
  820. #if 0
  821. printf("rgb-to-rgb: ssat=%f, isat=%f, do-sat=%d, split-sat=%d\n", ssat, isat, compute_saturation, split_saturation);
  822. #endif
  823.   while (width > 0)
  824.     {
  825.       double h, s, v;
  826.       switch (bpp)
  827.     {
  828.     case 1:
  829.       /*
  830.        * No alpha in image, using colormap...
  831.        */
  832.       if (i0 == rgbin[0])
  833.         use_previous = 1;
  834.       else
  835.         {
  836.           use_previous = 0;
  837.           i0 = rgbin[0];
  838.           rgbout[0] = cmap[rgbin[0] * 3 + 0] * 257;
  839.           rgbout[1] = cmap[rgbin[0] * 3 + 1] * 257;
  840.           rgbout[2] = cmap[rgbin[0] * 3 + 2] * 257;
  841.         }
  842.       break;
  843.     case 2:
  844.       if (i0 == rgbin[0] && i1 == rgbin[1])
  845.         use_previous = 1;
  846.       else
  847.         {
  848.           use_previous = 0;
  849.           i0 = rgbin[0];
  850.           i1 = rgbin[1];
  851.           rgbout[0] = (cmap[rgbin[0] * 3 + 0] *
  852.                rgbin[1] / 255 + 255 - rgbin[1]) * 257;
  853.           rgbout[1] = (cmap[rgbin[0] * 3 + 0] *
  854.                rgbin[1] / 255 + 255 - rgbin[1]) * 257;
  855.           rgbout[2] = (cmap[rgbin[0] * 3 + 0] *
  856.                rgbin[1] / 255 + 255 - rgbin[1]) * 257;
  857.         }
  858.       break;
  859.     case 3:
  860.       /*
  861.        * No alpha in image...
  862.        */
  863.       if (i0 == rgbin[0] && i1 == rgbin[1] && i2 == rgbin[2])
  864.         use_previous = 1;
  865.       else
  866.         {
  867.           use_previous = 0;
  868.           i0 = rgbin[0];
  869.           i1 = rgbin[1];
  870.           i2 = rgbin[2];
  871.           rgbout[0] = rgbin[0] * 257;
  872.           rgbout[1] = rgbin[1] * 257;
  873.           rgbout[2] = rgbin[2] * 257;
  874.         }
  875.       break;
  876.     case 4:
  877.       if (i0 == rgbin[0] && i1 == rgbin[1] && i2 == rgbin[2] &&
  878.           i3 == rgbin[3])
  879.         use_previous = 1;
  880.       else
  881.         {
  882.           use_previous = 0;
  883.           i0 = rgbin[0];
  884.           i1 = rgbin[1];
  885.           i2 = rgbin[2];
  886.           i3 = rgbin[3];
  887.           rgbout[0] = (rgbin[0] * rgbin[3] / 255 + 255 - rgbin[3]) * 257;
  888.           rgbout[1] = (rgbin[1] * rgbin[3] / 255 + 255 - rgbin[3]) * 257;
  889.           rgbout[2] = (rgbin[2] * rgbin[3] / 255 + 255 - rgbin[3]) * 257;
  890.         }
  891.       break;
  892.     }
  893.       if (use_previous)
  894.     {
  895.       rgbout[0] = o0;
  896.       rgbout[1] = o1;
  897.       rgbout[2] = o2;
  898.     }
  899.       else
  900.     {
  901.       if (compute_saturation &&
  902.           (rgbout[0] != rgbout[1] || rgbout[0] != rgbout[2]))
  903.         {
  904.           rgbout[0] = 65535 - rgbout[0];
  905.           rgbout[1] = 65535 - rgbout[1];
  906.           rgbout[2] = 65535 - rgbout[2];
  907.           calc_rgb_to_hsl(rgbout, &h, &s, &v);
  908.           if (ssat < 1)
  909.         s *= ssat;
  910.           else
  911.         {
  912.           double s1 = s * ssat;
  913.           double s2 = 1.0 - ((1.0 - s) * isat);
  914.           s = FMIN(s1, s2);
  915.         }
  916.           if (s > 1)
  917.         s = 1.0;
  918.           calc_hsl_to_rgb(rgbout, h, s, v);
  919.           rgbout[0] = 65535 - rgbout[0];
  920.           rgbout[1] = 65535 - rgbout[1];
  921.           rgbout[2] = 65535 - rgbout[2];
  922.         }
  923.       update_cmyk(rgbout);    /* Fiddle with the INPUT */
  924.       rgbout[0] = lookup_value(rgbout[0], lut->steps,
  925.                    lut->red, lut->shiftval,
  926.                    lut->bin_size, lut->bin_shift);
  927.       rgbout[1] = lookup_value(rgbout[1], lut->steps,
  928.                    lut->green, lut->shiftval,
  929.                    lut->bin_size, lut->bin_shift);
  930.       rgbout[2] = lookup_value(rgbout[2], lut->steps,
  931.                    lut->blue, lut->shiftval,
  932.                    lut->bin_size, lut->bin_shift);
  933.       if (split_saturation &&
  934.           (rgbout[0] != rgbout[1] || rgbout[0] != rgbout[2]))
  935.         {
  936.           rgbout[0] = 65535 - rgbout[0];
  937.           rgbout[1] = 65535 - rgbout[1];
  938.           rgbout[2] = 65535 - rgbout[2];
  939.           calc_rgb_to_hsl(rgbout, &h, &s, &v);
  940.           if (ssat < 1)
  941.         s *= ssat;
  942.           else
  943.         {
  944.           double s1 = s * ssat;
  945.           double s2 = 1.0 - ((1.0 - s) * isat);
  946.           s = FMIN(s1, s2);
  947.         }
  948.           if (s > 1)
  949.         s = 1.0;
  950.           calc_hsl_to_rgb(rgbout, h, s, v);
  951.           rgbout[0] = 65535 - rgbout[0];
  952.           rgbout[1] = 65535 - rgbout[1];
  953.           rgbout[2] = 65535 - rgbout[2];
  954.         }
  955.       if (ld < 65536)
  956.         {
  957.           int i;
  958.           for (i = 0; i < 3; i++)
  959.         {
  960.           unsigned t = rgbout[i];
  961.           t = 65535 - (65535 - t) * ld / 65536;
  962.           rgbout[i] = (unsigned short) t;
  963.         }
  964.         }
  965.       o0 = rgbout[0];
  966.       o1 = rgbout[1];
  967.       o2 = rgbout[2];
  968.     }
  969.       rgbin += bpp;
  970.       rgbout += 3;
  971.       width --;
  972.     }
  973. }
  974.  
  975. static void
  976. indexed_to_rgb(unsigned char *indexed,    /* I - Indexed pixels */
  977.            unsigned short *rgb,    /* O - RGB pixels */
  978.            int    width,        /* I - Width of row */
  979.            int    bpp,        /* I - Bytes-per-pixel in indexed */
  980.            unsigned char *cmap,    /* I - Colormap */
  981.            const vars_t   *vars
  982.            )
  983. {
  984.   rgb_to_rgb(indexed, rgb, width, bpp, cmap, vars);
  985. }
  986.  
  987. /*
  988.  * 'gray_to_rgb()' - Convert gray image data to RGB.
  989.  */
  990.  
  991. static void
  992. gray_to_rgb(unsigned char    *grayin,    /* I - grayscale pixels */
  993.         unsigned short     *rgbout,    /* O - RGB pixels */
  994.         int            width,        /* I - Width of row */
  995.         int            bpp,        /* I - Bytes/pix in indexed */
  996.         unsigned char     *cmap,        /* I - Colormap */
  997.         const vars_t      *vars
  998.         )
  999. {
  1000.   int use_previous = 0;
  1001.   int i0 = -1;
  1002.   int i1 = -1;
  1003.   int o0 = 0;
  1004.   int o1 = 0;
  1005.   int o2 = 0;
  1006.   lut_t *lut = (lut_t *)(vars->lut);
  1007.   while (width > 0)
  1008.     {
  1009.       unsigned short trgb[3];
  1010.       if (bpp == 1)
  1011.     {
  1012.       /*
  1013.        * No alpha in image...
  1014.        */
  1015.       if (i0 == grayin[0])
  1016.         use_previous = 1;
  1017.       else
  1018.         {
  1019.           use_previous = 0;
  1020.           i0 = grayin[0];
  1021.           trgb[0] = grayin[0] * 257;
  1022.           trgb[1] = grayin[0] * 257;
  1023.           trgb[2] = grayin[0] * 257;
  1024.         }
  1025.     }
  1026.       else
  1027.     {
  1028.       if (i0 == grayin[0] && i1 == grayin[1])
  1029.         use_previous = 1;
  1030.       else
  1031.         {
  1032.           int lookup = (grayin[0] * grayin[1] / 255 + 255 - grayin[1]) *
  1033.         257;
  1034.           use_previous = 0;
  1035.           i0 = grayin[0];
  1036.           i1 = grayin[1];
  1037.           trgb[0] = lookup;
  1038.           trgb[1] = lookup;
  1039.           trgb[2] = lookup;
  1040.         }
  1041.     }
  1042.       if (use_previous)
  1043.     {
  1044.       rgbout[0] = o0;
  1045.       rgbout[1] = o1;
  1046.       rgbout[2] = o2;
  1047.     }
  1048.       else
  1049.     {
  1050.       update_cmyk(trgb);
  1051.       rgbout[0] = lookup_value(trgb[0], lut->steps,
  1052.                    lut->red, lut->shiftval,
  1053.                    lut->bin_size, lut->bin_shift);
  1054.       rgbout[1] = lookup_value(trgb[1], lut->steps,
  1055.                    lut->green, lut->shiftval,
  1056.                    lut->bin_size, lut->bin_shift);
  1057.       rgbout[2] = lookup_value(trgb[2], lut->steps,
  1058.                    lut->blue, lut->shiftval,
  1059.                    lut->bin_size, lut->bin_shift);
  1060.       if (vars->saturation != 1.0)
  1061.         {
  1062.           double t;
  1063.           int i;
  1064.           for (i = 0; i < 3; i++)
  1065.         {
  1066.           t = (65535.0 + ((rgbout[i] - 65535.0) * vars->density));
  1067.           if (t < 0.0)
  1068.             t = 0.0;
  1069.           rgbout[i] = t + .5;
  1070.         }
  1071.         }
  1072.       o0 = rgbout[0];
  1073.       o1 = rgbout[1];
  1074.       o2 = rgbout[2];
  1075.     }
  1076.       grayin += bpp;
  1077.       rgbout += 3;
  1078.       width --;
  1079.     }
  1080. }
  1081.  
  1082. static void
  1083. fast_indexed_to_rgb(unsigned char *indexed,    /* I - Indexed pixels */
  1084.             unsigned short *rgb,    /* O - RGB pixels */
  1085.             int    width,        /* I - Width of row */
  1086.             int    bpp,        /* I - Bytes-per-pixel in indexed */
  1087.             unsigned char *cmap,    /* I - Colormap */
  1088.             const vars_t   *vars
  1089.             )
  1090. {
  1091.   int i0 = -1;
  1092.   int i1 = -1;
  1093.   int o0 = 0;
  1094.   int o1 = 0;
  1095.   int o2 = 0;
  1096.   lut_t *lut = (lut_t *)(vars->lut);
  1097.   int use_previous = 0;
  1098.   double isat = 1.0;
  1099.   if (vars->saturation > 1)
  1100.     isat = 1.0 / vars->saturation;
  1101.   while (width > 0)
  1102.     {
  1103.       double h, s, v;
  1104.       if (bpp == 1)
  1105.     {
  1106.       /*
  1107.        * No alpha in image...
  1108.        */
  1109.       if (i0 == indexed[0])
  1110.         use_previous = 1;
  1111.       else
  1112.         {
  1113.           use_previous = 0;
  1114.           i0 = indexed[0];
  1115.           rgb[0] = lut->red[cmap[i0 * 3 + 0]];
  1116.           rgb[1] = lut->green[cmap[i0 * 3 + 1]];
  1117.           rgb[2] = lut->blue[cmap[i0 * 3 + 2]];
  1118.         }
  1119.     }
  1120.       else
  1121.     {
  1122.       if (i0 == indexed[0] && i1 == indexed[1])
  1123.         use_previous = 1;
  1124.       else
  1125.         {
  1126.           use_previous = 0;
  1127.           i0 = indexed[0];
  1128.           i1 = indexed[1];
  1129.           rgb[0] = lut->red[cmap[i0 * 3 + 0] * i1 / 255 + 255 - i1];
  1130.           rgb[1] = lut->green[cmap[i0 * 3 + 1] * i1 / 255 + 255 -i1];
  1131.           rgb[2] = lut->blue[cmap[i0 * 3 + 2] * i1 / 255 + 255 - i1];
  1132.         }
  1133.     }
  1134.       if (use_previous)
  1135.     {
  1136.       rgb[0] = o0;
  1137.       rgb[1] = o1;
  1138.       rgb[2] = o2;
  1139.     }
  1140.       else
  1141.     {
  1142.       if (vars->saturation != 1.0)
  1143.         {
  1144.           calc_rgb_to_hsl(rgb, &h, &s, &v);
  1145.           if (vars->saturation < 1)
  1146.         s *= vars->saturation;
  1147.           else
  1148.         {
  1149.           double s1 = s * vars->saturation;
  1150.           double s2 = 1.0 - ((1.0 - s) * isat);
  1151.           s = FMIN(s1, s2);
  1152.         }
  1153.           if (s > 1)
  1154.         s = 1.0;
  1155.           calc_hsl_to_rgb(rgb, h, s, v);
  1156.         }
  1157.       if (vars->density != 1.0)
  1158.         {
  1159.           double t;
  1160.           int i;
  1161.           for (i = 0; i < 3; i++)
  1162.         {
  1163.           t = (65535.0 + ((rgb[i] - 65535.0) * vars->density));
  1164.           if (t < 0.0)
  1165.             t = 0.0;
  1166.           rgb[i] = t + .5;
  1167.         }
  1168.         }
  1169.       o0 = rgb[0];
  1170.       o1 = rgb[1];
  1171.       o2 = rgb[2];
  1172.     }
  1173.       indexed += bpp;
  1174.       rgb += 3;
  1175.       width --;
  1176.     }
  1177. }
  1178.  
  1179. /*
  1180.  * 'rgb_to_rgb()' - Convert rgb image data to RGB.
  1181.  */
  1182.  
  1183. static void
  1184. fast_rgb_to_rgb(unsigned char    *rgbin,        /* I - RGB pixels */
  1185.         unsigned short     *rgbout,    /* O - RGB pixels */
  1186.         int            width,        /* I - Width of row */
  1187.         int            bpp,        /* I - Bytes/pix in indexed */
  1188.         unsigned char     *cmap,        /* I - Colormap */
  1189.         const vars_t      *vars
  1190.         )
  1191. {
  1192.   unsigned ld = vars->density * 65536;
  1193.   int i0 = -1;
  1194.   int i1 = -1;
  1195.   int i2 = -1;
  1196.   int i3 = -1;
  1197.   int o0 = 0;
  1198.   int o1 = 0;
  1199.   int o2 = 0;
  1200.   lut_t *lut = (lut_t *)(vars->lut);
  1201.   int use_previous = 0;
  1202.   double isat = 1.0;
  1203.   if (vars->saturation > 1)
  1204.     isat = 1.0 / vars->saturation;
  1205.   while (width > 0)
  1206.     {
  1207.       double h, s, v;
  1208.       if (bpp == 3)
  1209.     {
  1210.       /*
  1211.        * No alpha in image...
  1212.        */
  1213.       if (i0 == rgbin[0] && i1 == rgbin[1] && i2 == rgbin[2])
  1214.         use_previous = 1;
  1215.       else
  1216.         {
  1217.           use_previous = 0;
  1218.           i0 = rgbin[0];
  1219.           i1 = rgbin[1];
  1220.           i2 = rgbin[2];
  1221.           rgbout[0] = lut->red[rgbin[0]];
  1222.           rgbout[1] = lut->green[rgbin[1]];
  1223.           rgbout[2] = lut->blue[rgbin[2]];
  1224.         }
  1225.     }
  1226.       else
  1227.     {
  1228.       if (i0 == rgbin[0] && i1 == rgbin[1] && i2 == rgbin[2] &&
  1229.           i3 == rgbin[3])
  1230.         use_previous = 1;
  1231.       else
  1232.         {
  1233.           use_previous = 0;
  1234.           i0 = rgbin[0];
  1235.           i1 = rgbin[1];
  1236.           i2 = rgbin[2];
  1237.           i3 = rgbin[3];
  1238.           rgbout[0] = lut->red[i0 * i3 / 255 + 255 - i3];
  1239.           rgbout[1] = lut->green[i1 * i3 / 255 + 255 - i3];
  1240.           rgbout[2] = lut->blue[i2 * i3 / 255 + 255 - i3];
  1241.         }
  1242.     }
  1243.       if (use_previous)
  1244.     {
  1245.       rgbout[0] = o0;
  1246.       rgbout[1] = o1;
  1247.       rgbout[2] = o2;
  1248.     }
  1249.       else
  1250.     {
  1251.       if (vars->saturation != 1.0)
  1252.         {
  1253.           calc_rgb_to_hsl(rgbout, &h, &s, &v);
  1254.           if (vars->saturation < 1)
  1255.         s *= vars->saturation;
  1256.           else
  1257.         {
  1258.           double s1 = s * vars->saturation;
  1259.           double s2 = 1.0 - ((1.0 - s) * isat);
  1260.           s = FMIN(s1, s2);
  1261.         }
  1262.           if (s > 1)
  1263.         s = 1.0;
  1264.           calc_hsl_to_rgb(rgbout, h, s, v);
  1265.         }
  1266.       if (ld < 65536)
  1267.         {
  1268.           int i;
  1269.           for (i = 0; i < 3; i++)
  1270.         {
  1271.           unsigned t = rgbout[i];
  1272.           t = 65535 - (65535 - t) * ld / 65536;
  1273.           rgbout[i] = (unsigned short) t;
  1274.         }
  1275.         }
  1276.       o0 = rgbout[0];
  1277.       o1 = rgbout[1];
  1278.       o2 = rgbout[2];
  1279.     }
  1280.       rgbin += bpp;
  1281.       rgbout += 3;
  1282.       width --;
  1283.     }
  1284. }
  1285.  
  1286. /*
  1287.  * 'gray_to_rgb()' - Convert gray image data to RGB.
  1288.  */
  1289.  
  1290. static void
  1291. fast_gray_to_rgb(unsigned char    *grayin,    /* I - grayscale pixels */
  1292.          unsigned short *rgbout,    /* O - RGB pixels */
  1293.          int        width,        /* I - Width of row */
  1294.          int        bpp,        /* I - Bytes/pix in indexed */
  1295.          unsigned char     *cmap,        /* I - Colormap */
  1296.          const vars_t      *vars
  1297.          )
  1298. {
  1299.   int use_previous = 0;
  1300.   int i0 = -1;
  1301.   int i1 = -1;
  1302.   int o0 = 0;
  1303.   int o1 = 0;
  1304.   int o2 = 0;
  1305.   lut_t *lut = (lut_t *)(vars->lut);
  1306.   while (width > 0)
  1307.     {
  1308.       if (bpp == 1)
  1309.     {
  1310.       /*
  1311.        * No alpha in image...
  1312.        */
  1313.       if (i0 == grayin[0])
  1314.         use_previous = 1;
  1315.       else
  1316.         {
  1317.           use_previous = 0;
  1318.           i0 = grayin[0];
  1319.           rgbout[0] = lut->red[grayin[0]];
  1320.           rgbout[1] = lut->green[grayin[0]];
  1321.           rgbout[2] = lut->blue[grayin[0]];
  1322.         }
  1323.     }
  1324.       else
  1325.     {
  1326.       if (i0 == grayin[0] && i1 == grayin[1])
  1327.         use_previous = 1;
  1328.       else
  1329.         {
  1330.           int lookup = (grayin[0] * grayin[1] / 255 +
  1331.                 255 - grayin[1]);
  1332.           use_previous = 0;
  1333.           i0 = grayin[0];
  1334.           i1 = grayin[1];
  1335.           rgbout[0] = lut->red[lookup];
  1336.           rgbout[1] = lut->green[lookup];
  1337.           rgbout[2] = lut->blue[lookup];
  1338.         }
  1339.     }
  1340.       if (use_previous)
  1341.     {
  1342.       rgbout[0] = o0;
  1343.       rgbout[1] = o1;
  1344.       rgbout[2] = o2;
  1345.     }
  1346.       else
  1347.     {
  1348.       if (vars->density != 1.0)
  1349.         {
  1350.           double t;
  1351.           int i;
  1352.           for (i = 0; i < 3; i++)
  1353.         {
  1354.           t = (65535.0 + ((rgbout[i] - 65535.0) * vars->density));
  1355.           if (t < 0.0)
  1356.             t = 0.0;
  1357.           rgbout[i] = t + .5;
  1358.         }
  1359.         }
  1360.             o0 = rgbout[0];
  1361.       o1 = rgbout[1];
  1362.       o2 = rgbout[2];
  1363.     }
  1364.       grayin += bpp;
  1365.       rgbout += 3;
  1366.       width --;
  1367.     }
  1368. }
  1369.  
  1370. #define ICLAMP(value)                \
  1371. do                        \
  1372. {                        \
  1373.   if (user->value < min->value)            \
  1374.     user->value = min->value;            \
  1375.   else if (user->value > max->value)        \
  1376.     user->value = max->value;            \
  1377. } while (0)
  1378.  
  1379. void
  1380. merge_printvars(vars_t *user, const vars_t *print)
  1381. {
  1382.   const vars_t *max = print_maximum_settings();
  1383.   const vars_t *min = print_minimum_settings();
  1384.   user->cyan = (user->cyan * print->cyan);
  1385.   ICLAMP(cyan);
  1386.   user->magenta = (user->magenta * print->magenta);
  1387.   ICLAMP(magenta);
  1388.   user->yellow = (user->yellow * print->yellow);
  1389.   ICLAMP(yellow);
  1390.   user->contrast = (user->contrast * print->contrast);
  1391.   ICLAMP(contrast);
  1392.   user->brightness = (user->brightness * print->brightness);
  1393.   ICLAMP(brightness);
  1394.   user->gamma /= print->gamma;
  1395.   ICLAMP(gamma);
  1396.   user->saturation *= print->saturation;
  1397.   ICLAMP(saturation);
  1398.   user->density *= print->density;
  1399.   ICLAMP(density);
  1400. }
  1401.  
  1402. static lut_t *
  1403. allocate_lut(size_t steps)
  1404. {
  1405.   int i;
  1406.   lut_t *ret = malloc(sizeof(lut_t));
  1407.   ret->steps = steps;
  1408.   ret->composite = malloc(sizeof(unsigned short) * steps);
  1409.   ret->red = malloc(sizeof(unsigned short) * steps);
  1410.   ret->green = malloc(sizeof(unsigned short) * steps);
  1411.   ret->blue = malloc(sizeof(unsigned short) * steps);
  1412.   ret->shiftval = 0;
  1413.   for (i = 1; i < steps; i += i)
  1414.     ret->shiftval++;
  1415.   ret->bin_size = 65536 / steps;
  1416.   ret->bin_shift = 16 - ret->shiftval;
  1417.   return ret;
  1418. }
  1419.  
  1420. void
  1421. free_lut(vars_t *v)
  1422. {
  1423.   if (v->lut)
  1424.     {
  1425.       lut_t *lut = (lut_t *)(v->lut);
  1426.       if (lut->composite)
  1427.     free(lut->composite);
  1428.       if (lut->red)
  1429.     free(lut->red);
  1430.       if (lut->green)
  1431.     free(lut->green);
  1432.       if (lut->blue)
  1433.     free(lut->blue);
  1434.       lut->steps = 0;
  1435.       lut->composite = NULL;
  1436.       lut->red = NULL;
  1437.       lut->green = NULL;
  1438.       lut->blue = NULL;
  1439.       free(v->lut);
  1440.       v->lut = NULL;
  1441.     }
  1442. }
  1443.  
  1444. /* #define PRINT_LUT */
  1445.  
  1446. void
  1447. compute_lut(size_t steps, vars_t *uv)
  1448. {
  1449.   double    pixel,        /* Pixel value */
  1450.         red_pixel,    /* Pixel value */
  1451.         green_pixel,    /* Pixel value */
  1452.         blue_pixel;    /* Pixel value */
  1453.   int i;
  1454. #ifdef PRINT_LUT
  1455.   FILE *ltfile = fopen("/mnt1/lut", "w");
  1456. #endif
  1457.   /*
  1458.    * Got an output file/command, now compute a brightness lookup table...
  1459.    */
  1460.  
  1461.   double cyan = uv->cyan;
  1462.   double magenta = uv->magenta;
  1463.   double yellow = uv->yellow;
  1464.   double print_gamma = uv->gamma;
  1465.   double contrast = uv->contrast;
  1466.   double app_gamma = uv->app_gamma;
  1467.   double brightness = uv->brightness;
  1468.   double screen_gamma = app_gamma / 1.7;    /* Why 1.7??? */
  1469.   lut_t *lut;
  1470.  
  1471.   /*
  1472.    * Monochrome mode simply thresholds the input
  1473.    * to decide whether to print at all.  The printer gamma
  1474.    * is intended to represent the analog response of the printer.
  1475.    * Using it shifts the threshold, which is not the intent
  1476.    * of how this works.
  1477.    */
  1478.   if (uv->image_type == IMAGE_MONOCHROME)
  1479.     print_gamma = 1.0;
  1480.  
  1481.   uv->lut = allocate_lut(steps);
  1482.   lut = (lut_t *)(uv->lut);
  1483.   for (i = 0; i < steps; i ++)
  1484.     {
  1485.       double temp_pixel;
  1486.       pixel = (double) i / (double) (steps - 1);
  1487.  
  1488.       /*
  1489.        * First, correct contrast
  1490.        */
  1491.       if (pixel >= .5)
  1492.     temp_pixel = 1.0 - pixel;
  1493.       else
  1494.     temp_pixel = pixel;
  1495.       if (temp_pixel <= .000001 && contrast <= .0001)
  1496.     temp_pixel = .5;
  1497.       else if (temp_pixel > 1)
  1498.     temp_pixel = .5 * pow(2 * temp_pixel, pow(contrast, contrast));
  1499.       else if (temp_pixel < 1)
  1500.     temp_pixel = 0.5 -
  1501.       ((0.5 - .5 * pow(2 * temp_pixel, contrast)) * contrast);
  1502.       if (temp_pixel > .5)
  1503.     temp_pixel = .5;
  1504.       else if (temp_pixel < 0)
  1505.     temp_pixel = 0;
  1506.       if (pixel < .5)
  1507.     pixel = temp_pixel;
  1508.       else
  1509.     pixel = 1 - temp_pixel;
  1510.  
  1511.       /*
  1512.        * Second, do brightness
  1513.        */
  1514.       if (brightness < 1)
  1515.     pixel = pixel * brightness;
  1516.       else
  1517.     pixel = 1 - ((1 - pixel) * (2 - brightness));
  1518.  
  1519.       /*
  1520.        * Third, correct for the screen gamma
  1521.        */
  1522.       pixel = 1.0 - pow(pixel, screen_gamma);
  1523.  
  1524.       /*
  1525.        * Third, fix up cyan, magenta, yellow values
  1526.        */
  1527.       if (pixel < 0.0)
  1528.     pixel = 0.0;
  1529.       else if (pixel > 1.0)
  1530.     pixel = 1.0;
  1531.  
  1532.       if (pixel > .9999 && cyan < .00001)
  1533.     red_pixel = 0;
  1534.       else
  1535.     red_pixel = 1 - pow(1 - pixel, cyan);
  1536.       if (pixel > .9999 && magenta < .00001)
  1537.     green_pixel = 0;
  1538.       else
  1539.     green_pixel = 1 - pow(1 - pixel, magenta);
  1540.       if (pixel > .9999 && yellow < .00001)
  1541.     blue_pixel = 0;
  1542.       else
  1543.     blue_pixel = 1 - pow(1 - pixel, yellow);
  1544.  
  1545.       /*
  1546.        * Finally, fix up print gamma and scale
  1547.        */
  1548.  
  1549.       pixel = 65535 * (1 - pow(pixel, print_gamma)) + .5;
  1550.       red_pixel = 65535 * (1 - pow(red_pixel, print_gamma)) + .5;
  1551.       green_pixel = 65535 * (1 - pow(green_pixel, print_gamma)) + .5;
  1552.       blue_pixel = 65535 * (1 - pow(blue_pixel, print_gamma)) + .5;
  1553.  
  1554.       if (pixel <= 0.0)
  1555.     lut->composite[i] = 0;
  1556.       else if (pixel >= 65535.0)
  1557.     lut->composite[i] = 65535;
  1558.       else
  1559.     lut->composite[i] = (unsigned)(pixel);
  1560.  
  1561.       if (red_pixel <= 0.0)
  1562.     lut->red[i] = 0;
  1563.       else if (red_pixel >= 65535.0)
  1564.     lut->red[i] = 65535;
  1565.       else
  1566.     lut->red[i] = (unsigned)(red_pixel);
  1567.  
  1568.       if (green_pixel <= 0.0)
  1569.     lut->green[i] = 0;
  1570.       else if (green_pixel >= 65535.0)
  1571.     lut->green[i] = 65535;
  1572.       else
  1573.     lut->green[i] = (unsigned)(green_pixel);
  1574.  
  1575.       if (blue_pixel <= 0.0)
  1576.     lut->blue[i] = 0;
  1577.       else if (blue_pixel >= 65535.0)
  1578.     lut->blue[i] = 65535;
  1579.       else
  1580.     lut->blue[i] = (unsigned)(blue_pixel);
  1581. #ifdef PRINT_LUT
  1582.       fprintf(ltfile, "%3i  %5d  %5d  %5d  %5d  %f %f %f %f  %f %f %f  %f\n",
  1583.           i, lut->composite[i], lut->red[i],
  1584.           lut->green[i], lut->blue[i], pixel, red_pixel,
  1585.           green_pixel, blue_pixel, print_gamma, screen_gamma,
  1586.           print_gamma, app_gamma);
  1587. #endif
  1588.     }
  1589.  
  1590. #ifdef PRINT_LUT
  1591.   fclose(ltfile);
  1592. #endif
  1593. }
  1594.  
  1595. /*
  1596.  * 'default_media_size()' - Return the size of a default page size.
  1597.  */
  1598.  
  1599. /*
  1600.  * Sizes are converted to 1/72in, then rounded down so that we don't
  1601.  * print off the edge of the paper.
  1602.  */
  1603. const static papersize_t paper_sizes[] =
  1604. {
  1605.   /* Common imperial page sizes */
  1606.   { "Letter",   612,  792, PAPERSIZE_ENGLISH },    /* 8.5in x 11in */
  1607.   { "Legal",    612, 1008, PAPERSIZE_ENGLISH },    /* 8.5in x 14in */
  1608.   { "Tabloid",  792, 1224, PAPERSIZE_ENGLISH },    /*  11in x 17in */
  1609.   { "Executive", 522, 756, PAPERSIZE_ENGLISH },    /* 7.25 * 10.5in */
  1610.   { "Postcard", 283,  416, PAPERSIZE_ENGLISH },    /* 100mm x 147mm */
  1611.   { "3x5",    216,  360, PAPERSIZE_ENGLISH },
  1612.   { "4x6",      288,  432, PAPERSIZE_ENGLISH },
  1613.   { "Epson 4x6 Photo Paper", 306, 495, PAPERSIZE_ENGLISH },
  1614.   { "5x7",      360,  504, PAPERSIZE_ENGLISH },
  1615.   { "5x8",      360,  576, PAPERSIZE_ENGLISH },
  1616.   { "HalfLetter", 396, 612, PAPERSIZE_ENGLISH },
  1617.   { "6x8",      432,  576, PAPERSIZE_ENGLISH },
  1618.   { "8x10",     576,  720, PAPERSIZE_ENGLISH },
  1619.   { "Manual",   396,  612, PAPERSIZE_ENGLISH },    /* 5.5in x 8.5in */
  1620.   { "12x18",    864, 1296, PAPERSIZE_ENGLISH },
  1621.   { "13x19",    936, 1368, PAPERSIZE_ENGLISH },
  1622.  
  1623.   /* Other common photographic paper sizes */
  1624.   { "8x12",    576,  864, PAPERSIZE_ENGLISH }, /* Sometimes used for 35 mm */
  1625.   { "11x14",    792, 1008, PAPERSIZE_ENGLISH },
  1626.   { "16x20",   1152, 1440, PAPERSIZE_ENGLISH },
  1627.   { "16x24",   1152, 1728, PAPERSIZE_ENGLISH }, /* 20x24 for 35 mm */
  1628.   { "20x24",   1440, 1728, PAPERSIZE_ENGLISH },
  1629.   { "20x30",   1440, 2160, PAPERSIZE_ENGLISH },    /* 24x30 for 35 mm */
  1630.   { "24x30",   1728, 2160, PAPERSIZE_ENGLISH },
  1631.   { "24x36",   1728, 2592, PAPERSIZE_ENGLISH }, /* Sometimes used for 35 mm */
  1632.   { "30x40",   2160, 2880, PAPERSIZE_ENGLISH },
  1633.  
  1634.   /* International Paper Sizes (mostly taken from BS4000:1968) */
  1635.  
  1636.   /*
  1637.    * "A" series: Paper and boards, trimmed sizes
  1638.    *
  1639.    * "A" sizes are in the ratio 1 : sqrt(2).  A0 has a total area
  1640.    * of 1 square metre.  Everything is rounded to the nearest
  1641.    * millimetre.  Thus, A0 is 841mm x 1189mm.  Every other A
  1642.    * size is obtained by doubling or halving another A size.
  1643.    */
  1644.   { "4A",       4768, 6749, PAPERSIZE_METRIC },    /* 1682mm x 2378mm */
  1645.   { "2A",       3370, 4768, PAPERSIZE_METRIC },    /* 1189mm x 1682mm */
  1646.   { "A0",       2384, 3370, PAPERSIZE_METRIC },    /*  841mm x 1189mm */
  1647.   { "A1",       1684, 2384, PAPERSIZE_METRIC },    /*  594mm x  841mm */
  1648.   { "A2",       1191, 1684, PAPERSIZE_METRIC },    /*  420mm x  594mm */
  1649.   { "A3",        842, 1191, PAPERSIZE_METRIC },    /*  297mm x  420mm */
  1650.   { "A4",        595,  842, PAPERSIZE_METRIC },    /*  210mm x  297mm */
  1651.   { "A5",        420,  595, PAPERSIZE_METRIC },    /*  148mm x  210mm */
  1652.   { "A6",        297,  420, PAPERSIZE_METRIC },    /*  105mm x  148mm */
  1653.   { "A7",        210,  297, PAPERSIZE_METRIC },    /*   74mm x  105mm */
  1654.   { "A8",        148,  210, PAPERSIZE_METRIC },    /*   52mm x   74mm */
  1655.   { "A9",        105,  148, PAPERSIZE_METRIC },    /*   37mm x   52mm */
  1656.   { "A10",        73,  105, PAPERSIZE_METRIC },    /*   26mm x   37mm */
  1657.  
  1658.   /*
  1659.    * Stock sizes for normal trims.
  1660.    * Allowance for trim is 3 millimetres.
  1661.    */
  1662.   { "RA0",      2437, 3458, PAPERSIZE_METRIC },    /*  860mm x 1220mm */
  1663.   { "RA1",      1729, 2437, PAPERSIZE_METRIC },    /*  610mm x  860mm */
  1664.   { "RA2",      1218, 1729, PAPERSIZE_METRIC },    /*  430mm x  610mm */
  1665.   { "RA3",       864, 1218, PAPERSIZE_METRIC },    /*  305mm x  430mm */
  1666.   { "RA4",       609,  864, PAPERSIZE_METRIC },    /*  215mm x  305mm */
  1667.  
  1668.   /*
  1669.    * Stock sizes for bled work or extra trims.
  1670.    */
  1671.   { "SRA0",     2551, 3628, PAPERSIZE_METRIC },    /*  900mm x 1280mm */
  1672.   { "SRA1",     1814, 2551, PAPERSIZE_METRIC },    /*  640mm x  900mm */
  1673.   { "SRA2",     1275, 1814, PAPERSIZE_METRIC },    /*  450mm x  640mm */
  1674.   { "SRA3",      907, 1275, PAPERSIZE_METRIC },    /*  320mm x  450mm */
  1675.   { "SRA4",      637,  907, PAPERSIZE_METRIC },    /*  225mm x  320mm */
  1676.  
  1677.   /*
  1678.    * "B" series: Posters, wall charts and similar items.
  1679.    */
  1680.   { "4B ISO",   5669, 8016, PAPERSIZE_METRIC },    /* 2000mm x 2828mm */
  1681.   { "2B ISO",   4008, 5669, PAPERSIZE_METRIC },    /* 1414mm x 2000mm */
  1682.   { "B0 ISO",   2834, 4008, PAPERSIZE_METRIC },    /* 1000mm x 1414mm */
  1683.   { "B1 ISO",   2004, 2834, PAPERSIZE_METRIC },    /*  707mm x 1000mm */
  1684.   { "B2 ISO",   1417, 2004, PAPERSIZE_METRIC },    /*  500mm x  707mm */
  1685.   { "B3 ISO",   1000, 1417, PAPERSIZE_METRIC },    /*  353mm x  500mm */
  1686.   { "B4 ISO",    708, 1000, PAPERSIZE_METRIC },    /*  250mm x  353mm */
  1687.   { "B5 ISO",    498,  708, PAPERSIZE_METRIC },    /*  176mm x  250mm */
  1688.   { "B6 ISO",    354,  498, PAPERSIZE_METRIC },    /*  125mm x  176mm */
  1689.   { "B7 ISO",    249,  354, PAPERSIZE_METRIC },    /*   88mm x  125mm */
  1690.   { "B8 ISO",    175,  249, PAPERSIZE_METRIC },    /*   62mm x   88mm */
  1691.   { "B9 ISO",    124,  175, PAPERSIZE_METRIC },    /*   44mm x   62mm */
  1692.   { "B10 ISO",    87,  124, PAPERSIZE_METRIC },    /*   31mm x   44mm */
  1693.   
  1694.   { "B0 JIS",   2919, 4127, PAPERSIZE_METRIC },
  1695.   { "B1 JIS",   2063, 2919, PAPERSIZE_METRIC },
  1696.   { "B2 JIS",   1459, 2063, PAPERSIZE_METRIC },
  1697.   { "B3 JIS",   1029, 1459, PAPERSIZE_METRIC },
  1698.   { "B4 JIS",    727, 1029, PAPERSIZE_METRIC },
  1699.   { "B5 JIS",    518,  727, PAPERSIZE_METRIC },
  1700.   { "B6 JIS",    362,  518, PAPERSIZE_METRIC },
  1701.   { "B7 JIS",    257,  362, PAPERSIZE_METRIC },
  1702.   { "B8 JIS",    180,  257, PAPERSIZE_METRIC },
  1703.   { "B9 JIS",    127,  180, PAPERSIZE_METRIC },
  1704.   { "B10 JIS",    90,  127, PAPERSIZE_METRIC },
  1705.  
  1706.   /*
  1707.    * "C" series: Envelopes or folders suitable for A size stationery.
  1708.    */
  1709.   { "C0",       2599, 3676, PAPERSIZE_METRIC },    /*  917mm x 1297mm */
  1710.   { "C1",       1836, 2599, PAPERSIZE_METRIC },    /*  648mm x  917mm */
  1711.   { "C2",       1298, 1836, PAPERSIZE_METRIC },    /*  458mm x  648mm */
  1712.   { "C3",        918, 1298, PAPERSIZE_METRIC },    /*  324mm x  458mm */
  1713.   { "C4",        649,  918, PAPERSIZE_METRIC },    /*  229mm x  324mm */
  1714.   { "C5",        459,  649, PAPERSIZE_METRIC },    /*  162mm x  229mm */
  1715.   { "B6-C4",     354,  918, PAPERSIZE_METRIC },    /*  125mm x  324mm */
  1716.   { "C6",        323,  459, PAPERSIZE_METRIC },    /*  114mm x  162mm */
  1717.   { "DL",        311,  623, PAPERSIZE_METRIC },    /*  110mm x  220mm */
  1718.   { "C7-6",      229,  459, PAPERSIZE_METRIC },    /*   81mm x  162mm */
  1719.   { "C7",        229,  323, PAPERSIZE_METRIC },    /*   81mm x  114mm */
  1720.   { "C8",        161,  229, PAPERSIZE_METRIC },    /*   57mm x   81mm */
  1721.   { "C9",        113,  161, PAPERSIZE_METRIC },    /*   40mm x   57mm */
  1722.   { "C10",        79,  113, PAPERSIZE_METRIC },    /*   28mm x   40mm */
  1723.  
  1724.   /*
  1725.    * US CAD standard paper sizes
  1726.    */
  1727.   { "ArchA",     648,  864, PAPERSIZE_ENGLISH },
  1728.   { "ArchB",     864, 1296, PAPERSIZE_ENGLISH },
  1729.   { "ArchC",    1296, 1728, PAPERSIZE_ENGLISH },
  1730.   { "ArchD",    1728, 2592, PAPERSIZE_ENGLISH },
  1731.   { "ArchE",    2592, 3456, PAPERSIZE_ENGLISH },
  1732.  
  1733.   /*
  1734.    * Foolscap
  1735.    */
  1736.   { "flsa",     612,  936, PAPERSIZE_ENGLISH }, /* American foolscap */
  1737.   { "flse",     648,  936, PAPERSIZE_ENGLISH }, /* European foolscap */
  1738.  
  1739.   /*
  1740.    * Sizes for book production
  1741.    * The BPIF and the Publishers Association jointly recommend ten
  1742.    * standard metric sizes for case-bound titles as follows:
  1743.    */
  1744.   { "Crown Quarto",       535,  697, PAPERSIZE_METRIC }, /* 189mm x 246mm */
  1745.   { "Large Crown Quarto", 569,  731, PAPERSIZE_METRIC }, /* 201mm x 258mm */
  1746.   { "Demy Quarto",        620,  782, PAPERSIZE_METRIC }, /* 219mm x 276mm */
  1747.   { "Royal Quarto",       671,  884, PAPERSIZE_METRIC }, /* 237mm x 312mm */
  1748. /*{ "ISO A4",             595,  841, PAPERSIZE_METRIC },    210mm x 297mm */
  1749.   { "Crown Octavo",       348,  527, PAPERSIZE_METRIC }, /* 123mm x 186mm */
  1750.   { "Large Crown Octavo", 365,  561, PAPERSIZE_METRIC }, /* 129mm x 198mm */
  1751.   { "Demy Octavo",        391,  612, PAPERSIZE_METRIC }, /* 138mm x 216mm */
  1752.   { "Royal Octavo",       442,  663, PAPERSIZE_METRIC }, /* 156mm x 234mm */
  1753. /*{ "ISO A5",             419,  595, PAPERSIZE_METRIC },    148mm x 210mm */
  1754.  
  1755.   /* Paperback sizes in common usage */
  1756.   { "Small paperback",         314, 504, PAPERSIZE_METRIC }, /* 111mm x 178mm */
  1757.   { "Penguin small paperback", 314, 513, PAPERSIZE_METRIC }, /* 111mm x 181mm */
  1758.   { "Penguin large paperback", 365, 561, PAPERSIZE_METRIC }, /* 129mm x 198mm */
  1759.  
  1760.   /* Miscellaneous sizes */
  1761.   { "Hagaki Card", 283, 420, PAPERSIZE_METRIC }, /* 100 x 148 mm */
  1762.   { "Oufuku Card", 420, 567, PAPERSIZE_METRIC }, /* 148 x 200 mm */
  1763.   { "Long 3", 340, 666, PAPERSIZE_METRIC }, /* Japanese long envelope #3 */
  1764.   { "Long 4", 255, 581, PAPERSIZE_METRIC }, /* Japanese long envelope #4 */
  1765.   { "Kaku", 680, 941, PAPERSIZE_METRIC }, /* Japanese Kaku envelope #4 */
  1766.   { "Commercial 10", 297, 684, PAPERSIZE_ENGLISH }, /* US Commercial 10 env */
  1767.   { "A2 Invitation", 315, 414, PAPERSIZE_ENGLISH }, /* US A2 invitation */
  1768.  
  1769.   { "",           0,    0, PAPERSIZE_METRIC }
  1770. };
  1771.  
  1772. int
  1773. known_papersizes(void)
  1774. {
  1775.   return sizeof(paper_sizes) / sizeof(papersize_t);
  1776. }
  1777.  
  1778. const papersize_t *
  1779. get_papersizes(void)
  1780. {
  1781.   return paper_sizes;
  1782. }
  1783.  
  1784. const papersize_t *
  1785. get_papersize_by_name(const char *name)
  1786. {
  1787.   const papersize_t *val = &(paper_sizes[0]);
  1788.   while (strlen(val->name) > 0)
  1789.     {
  1790.       if (!strcasecmp(val->name, name))
  1791.     return val;
  1792.       val++;
  1793.     }
  1794.   return NULL;
  1795. }
  1796.  
  1797. #define IABS(a) ((a) > 0 ? a : -(a))
  1798.  
  1799. static int
  1800. paper_size_mismatch(int l, int w, const papersize_t *val)
  1801. {
  1802.   int hdiff = IABS(l - (int) val->length);
  1803.   int vdiff = fabs(w - (int) val->width);
  1804.   return hdiff + vdiff;
  1805. }
  1806.  
  1807. const papersize_t *
  1808. get_papersize_by_size(int l, int w)
  1809. {
  1810.   int score = INT_MAX;
  1811.   const papersize_t *ref = NULL;
  1812.   const papersize_t *val = &(paper_sizes[0]);
  1813.   while (strlen(val->name) > 0)
  1814.     {
  1815.       if (val->width == w && val->length == l)
  1816.     return val;
  1817.       else
  1818.     {
  1819.       int myscore = paper_size_mismatch(l, w, val);
  1820.       if (myscore < score && myscore < 20)
  1821.         {
  1822.           ref = val;
  1823.           score = myscore;
  1824.         }
  1825.     }
  1826.       val++;
  1827.     }
  1828.   return ref;
  1829. }
  1830.  
  1831. void
  1832. default_media_size(const printer_t *printer,
  1833.                     /* I - Printer model (not used) */
  1834.            const vars_t *v,    /* I */
  1835.                int  *width,        /* O - Width in points */
  1836.                int  *length)    /* O - Length in points */
  1837. {
  1838.   if (v->page_width > 0 && v->page_height > 0)
  1839.     {
  1840.       *width = v->page_width;
  1841.       *length = v->page_height;
  1842.     }
  1843.   else
  1844.     {
  1845.       const papersize_t *papersize = get_papersize_by_name(v->media_size);
  1846.       if (!papersize)
  1847.     {
  1848.       *width = 1;
  1849.       *length = 1;
  1850.     }
  1851.       else
  1852.     {
  1853.       *width = papersize->width;
  1854.       *length = papersize->length;
  1855.     }
  1856.     }
  1857. }
  1858.  
  1859. /*
  1860.  * The list of printers has been moved to printers.c
  1861.  */
  1862. #include "print-printers.c"
  1863.  
  1864. int
  1865. known_printers(void)
  1866. {
  1867.   return printer_count;
  1868. }
  1869.  
  1870. const printer_t *
  1871. get_printers(void)
  1872. {
  1873.   return printers;
  1874. }
  1875.  
  1876. const printer_t *
  1877. get_printer_by_index(int idx)
  1878. {
  1879.   return &(printers[idx]);
  1880. }
  1881.  
  1882. const printer_t *
  1883. get_printer_by_long_name(const char *long_name)
  1884. {
  1885.   const printer_t *val = &(printers[0]);
  1886.   int i;
  1887.   for (i = 0; i < known_printers(); i++)
  1888.     {
  1889.       if (!strcmp(val->long_name, long_name))
  1890.     return val;
  1891.       val++;
  1892.     }
  1893.   return NULL;
  1894. }
  1895.  
  1896. const printer_t *
  1897. get_printer_by_driver(const char *driver)
  1898. {
  1899.   const printer_t *val = &(printers[0]);
  1900.   int i;
  1901.   for (i = 0; i < known_printers(); i++)
  1902.     {
  1903.       if (!strcmp(val->driver, driver))
  1904.     return val;
  1905.       val++;
  1906.     }
  1907.   return NULL;
  1908. }
  1909.  
  1910. int
  1911. get_printer_index_by_driver(const char *driver)
  1912. {
  1913.   int idx = 0;
  1914.   const printer_t *val = &(printers[0]);
  1915.   for (idx = 0; idx < known_printers(); idx++)
  1916.     {
  1917.       if (!strcmp(val->driver, driver))
  1918.     return idx;
  1919.       val++;
  1920.     }
  1921.   return -1;
  1922. }
  1923.  
  1924. const char *
  1925. default_dither_algorithm(void)
  1926. {
  1927.   return dither_algo_names[0];
  1928. }
  1929.  
  1930. convert_t
  1931. choose_colorfunc(int output_type,
  1932.          int image_bpp,
  1933.          const unsigned char *cmap,
  1934.          int *out_bpp,
  1935.          const vars_t *v)
  1936. {
  1937.   if (v->image_type == IMAGE_MONOCHROME)
  1938.     {
  1939.       *out_bpp = 1;
  1940.  
  1941.       if (image_bpp >= 3)
  1942.     return rgb_to_monochrome;
  1943.       else if (cmap == NULL)
  1944.     return gray_to_monochrome;
  1945.       else
  1946.     return indexed_to_monochrome;
  1947.     }
  1948.   else if (output_type == OUTPUT_COLOR)
  1949.     {
  1950.       *out_bpp = 3;
  1951.  
  1952.       if (image_bpp >= 3)
  1953.     {
  1954.       if (v->image_type == IMAGE_CONTINUOUS)
  1955.         return rgb_to_rgb;
  1956.       else
  1957.         return fast_rgb_to_rgb;
  1958.     }
  1959.       else if (cmap == NULL)
  1960.         {
  1961.           if (v->image_type == IMAGE_CONTINUOUS)
  1962.         return gray_to_rgb;
  1963.           else
  1964.         return fast_gray_to_rgb;
  1965.         }
  1966.       else
  1967.     {
  1968.       if (v->image_type == IMAGE_CONTINUOUS)
  1969.         return indexed_to_rgb;
  1970.       else
  1971.         return fast_indexed_to_rgb;
  1972.     }
  1973.     }
  1974.   else
  1975.     {
  1976.       *out_bpp = 1;
  1977.  
  1978.       if (image_bpp >= 3)
  1979.     return rgb_to_gray;
  1980.       else if (cmap == NULL)
  1981.     return gray_to_gray;
  1982.       else
  1983.     return indexed_to_gray;
  1984.     }
  1985. }
  1986.  
  1987. void
  1988. compute_page_parameters(int page_right,    /* I */
  1989.             int page_left, /* I */
  1990.             int page_top, /* I */
  1991.             int page_bottom, /* I */
  1992.             double scaling, /* I */
  1993.             int image_width, /* I */
  1994.             int image_height, /* I */
  1995.             Image image, /* IO */
  1996.             int *orientation, /* IO */
  1997.             int *page_width, /* O */
  1998.             int *page_height, /* O */
  1999.             int *out_width,    /* O */
  2000.             int *out_height, /* O */
  2001.             int *left, /* O */
  2002.             int *top) /* O */
  2003. {
  2004.   *page_width  = page_right - page_left;
  2005.   *page_height = page_top - page_bottom;
  2006.  
  2007.   /* In AUTO orientation, just orient the paper the same way as the image. */
  2008.  
  2009.   if (*orientation == ORIENT_AUTO)
  2010.     {
  2011.       if ((*page_width >= *page_height && image_width >= image_height)
  2012.          || (*page_height >= *page_width && image_height >= image_width))
  2013.         *orientation = ORIENT_PORTRAIT;
  2014.       else
  2015.         *orientation = ORIENT_LANDSCAPE;
  2016.     }
  2017.  
  2018.   if (*orientation == ORIENT_LANDSCAPE)
  2019.       Image_rotate_ccw(image);
  2020.   else if (*orientation == ORIENT_UPSIDEDOWN)
  2021.       Image_rotate_180(image);
  2022.   else if (*orientation == ORIENT_SEASCAPE)
  2023.       Image_rotate_cw(image);
  2024.  
  2025.   image_width  = Image_width(image);
  2026.   image_height = Image_height(image);
  2027.  
  2028.   /*
  2029.    * Calculate width/height...
  2030.    */
  2031.  
  2032.   if (scaling == 0.0)
  2033.     {
  2034.       *out_width  = *page_width;
  2035.       *out_height = *page_height;
  2036.     }
  2037.   else if (scaling < 0.0)
  2038.     {
  2039.       /*
  2040.        * Scale to pixels per inch...
  2041.        */
  2042.  
  2043.       *out_width  = image_width * -72.0 / scaling;
  2044.       *out_height = image_height * -72.0 / scaling;
  2045.     }
  2046.   else
  2047.     {
  2048.       /*
  2049.        * Scale by percent...
  2050.        */
  2051.  
  2052.       /*
  2053.        * Decide which orientation gives the proper fit
  2054.        * If we ask for 50%, we do not want to exceed that
  2055.        * in either dimension!
  2056.        */
  2057.  
  2058.       int twidth0 = *page_width * scaling / 100.0;
  2059.       int theight0 = twidth0 * image_height / image_width;
  2060.       int theight1 = *page_height * scaling / 100.0;
  2061.       int twidth1 = theight1 * image_width / image_height;
  2062.  
  2063.       *out_width = FMIN(twidth0, twidth1);
  2064.       *out_height = FMIN(theight0, theight1);
  2065.     }
  2066.  
  2067.   if (*out_width == 0)
  2068.     *out_width = 1;
  2069.   if (*out_height == 0)
  2070.     *out_height = 1;
  2071.  
  2072.   /*
  2073.    * Adjust offsets depending on the page orientation...
  2074.    */
  2075.  
  2076.   if (*orientation == ORIENT_LANDSCAPE || *orientation == ORIENT_SEASCAPE)
  2077.     {
  2078.       int x;
  2079.  
  2080.       x     = *left;
  2081.       *left = *top;
  2082.       *top  = x;
  2083.     }
  2084.  
  2085.   if ((*orientation == ORIENT_UPSIDEDOWN || *orientation == ORIENT_SEASCAPE)
  2086.       && *left >= 0)
  2087.     {
  2088.       *left = *page_width - *left - *out_width;
  2089.       if (*left < 0) {
  2090.     *left = 0;
  2091.       }
  2092.     }
  2093.  
  2094.   if ((*orientation == ORIENT_UPSIDEDOWN || *orientation == ORIENT_LANDSCAPE)
  2095.       && *top >= 0)
  2096.     {
  2097.       *top = *page_height - *top - *out_height;
  2098.       if (*top < 0) {
  2099.     *top = 0;
  2100.       }
  2101.     }
  2102.  
  2103.   if (*left < 0)
  2104.     *left = (*page_width - *out_width) / 2;
  2105.  
  2106.   if (*top < 0)
  2107.     *top  = (*page_height - *out_height) / 2;
  2108. }
  2109.  
  2110. int
  2111. verify_printer_params(const printer_t *p, const vars_t *v)
  2112. {
  2113.   char **vptr;
  2114.   int count;
  2115.   int i;
  2116.   int answer = 1;
  2117.  
  2118.   if (strlen(v->media_size) > 0)
  2119.     {
  2120.       vptr = (*p->parameters)(p, NULL, "PageSize", &count);
  2121.       if (count > 0)
  2122.     {
  2123.       for (i = 0; i < count; i++)
  2124.         if (!strcmp(v->media_size, vptr[i]))
  2125.           goto good_page_size;
  2126.       answer = 0;
  2127.       fprintf(stderr, "%s is not a valid page size\n", v->media_size);
  2128.     }
  2129.     good_page_size:
  2130.       for (i = 0; i < count; i++)
  2131.     free(vptr[i]);
  2132.       free(vptr);
  2133.     }
  2134.   else
  2135.     {
  2136.       int height, width;
  2137.       (*p->limit)(p, v, &width, &height);
  2138. #if 0
  2139.       fprintf(stderr, "limit %d %d dims %d %d\n", width, height,
  2140.           v->page_width, v->page_height);
  2141. #endif
  2142.       if (v->page_height <= 0 || v->page_height > height ||
  2143.       v->page_width <= 0 || v->page_width > width)
  2144.     {
  2145.       answer = 0;
  2146.       fprintf(stderr, "Image size is not valid\n");
  2147.     }
  2148.     }
  2149.  
  2150.   if (strlen(v->media_type) > 0)
  2151.     {
  2152.       vptr = (*p->parameters)(p, NULL, "MediaType", &count);
  2153.       if (count > 0)
  2154.     {
  2155.       for (i = 0; i < count; i++)
  2156.         if (!strcmp(v->media_type, vptr[i]))
  2157.           goto good_media_type;
  2158.       answer = 0;
  2159.       fprintf(stderr, "%s is not a valid media type\n", v->media_type);
  2160.     }
  2161.     good_media_type:
  2162.       for (i = 0; i < count; i++)
  2163.     free(vptr[i]);
  2164.       free(vptr);
  2165.     }
  2166.  
  2167.   if (strlen(v->media_source) > 0)
  2168.     {
  2169.       vptr = (*p->parameters)(p, NULL, "InputSlot", &count);
  2170.       if (count > 0)
  2171.     {
  2172.       for (i = 0; i < count; i++)
  2173.         if (!strcmp(v->media_source, vptr[i]))
  2174.           goto good_media_source;
  2175.       answer = 0;
  2176.       fprintf(stderr, "%s is not a valid media source\n", v->media_source);
  2177.     }
  2178.     good_media_source:
  2179.       for (i = 0; i < count; i++)
  2180.     free(vptr[i]);
  2181.       free(vptr);
  2182.     }
  2183.  
  2184.   if (strlen(v->resolution) > 0)
  2185.     {
  2186.       vptr = (*p->parameters)(p, NULL, "Resolution", &count);
  2187.       if (count > 0)
  2188.     {
  2189.       for (i = 0; i < count; i++)
  2190.         if (!strcmp(v->resolution, vptr[i]))
  2191.           goto good_resolution;
  2192.       answer = 0;
  2193.       fprintf(stderr, "%s is not a valid resolution\n", v->resolution);
  2194.     }
  2195.     good_resolution:
  2196.       for (i = 0; i < count; i++)
  2197.     free(vptr[i]);
  2198.       free(vptr);
  2199.     }
  2200.  
  2201.   if (strlen(v->ink_type) > 0)
  2202.     {
  2203.       vptr = (*p->parameters)(p, NULL, "InkType", &count);
  2204.       if (count > 0)
  2205.     {
  2206.       for (i = 0; i < count; i++)
  2207.         if (!strcmp(v->ink_type, vptr[i]))
  2208.           goto good_ink_type;
  2209.       answer = 0;
  2210.       fprintf(stderr, "%s is not a valid ink type\n", v->ink_type);
  2211.     }
  2212.     good_ink_type:
  2213.       for (i = 0; i < count; i++)
  2214.     free(vptr[i]);
  2215.       free(vptr);
  2216.     }
  2217.  
  2218.   for (i = 0; i < num_dither_algos; i++)
  2219.     if (!strcmp(v->dither_algorithm, dither_algo_names[i]))
  2220.       return answer;
  2221.  
  2222.   fprintf(stderr, "%s is not a valid dither algorithm\n", v->dither_algorithm);
  2223.   return 0;
  2224. }
  2225.  
  2226. const vars_t *
  2227. print_default_settings()
  2228. {
  2229.   return &default_vars;
  2230. }
  2231.  
  2232. const vars_t *
  2233. print_maximum_settings()
  2234. {
  2235.   return &max_vars;
  2236. }
  2237.  
  2238. const vars_t *
  2239. print_minimum_settings()
  2240. {
  2241.   return &min_vars;
  2242. }
  2243.  
  2244. #ifdef QUANTIFY
  2245. unsigned quantify_counts[NUM_QUANTIFY_BUCKETS] = {0};
  2246. struct timeval quantify_buckets[NUM_QUANTIFY_BUCKETS] = {{0,0}};
  2247. int quantify_high_index = 0;
  2248. int quantify_first_time = 1;
  2249. struct timeval quantify_cur_time;
  2250. struct timeval quantify_prev_time;
  2251.  
  2252. void print_timers() 
  2253. {
  2254.     int i;
  2255.  
  2256.     printf("Quantify timers:\n");
  2257.     for (i = 0; i <= quantify_high_index; i++) {
  2258.        if (quantify_counts[i] == 0) continue;
  2259.         printf("Bucket %d:\t%ld.%ld s\thit %u times\n", i, quantify_buckets[i].tv_sec, quantify_buckets[i].tv_usec, quantify_counts[i]);
  2260.         quantify_buckets[i].tv_sec = 0;
  2261.         quantify_buckets[i].tv_usec = 0;
  2262.         quantify_counts[i] = 0;
  2263.     }
  2264. }
  2265. #endif
  2266.