• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *   Lookup table routines for CUPS.
3  *
4  *   Copyright 2007 by Apple Inc.
5  *   Copyright 1993-2005 by Easy Software Products.
6  *
7  *   These coded instructions, statements, and computer programs are the
8  *   property of Apple Inc. and are protected by Federal copyright
9  *   law.  Distribution and use rights are outlined in the file "COPYING"
10  *   which should have been included with this file.
11  *
12  * Contents:
13  *
14  *   cupsLutDelete() - Free the memory used by a lookup table.
15  *   cupsLutLoad()   - Load a LUT from a PPD file.
16  *   cupsLutNew()    - Make a lookup table from a list of pixel values.
17  */
18 
19 /*
20  * Include necessary headers.
21  */
22 
23 #include "driver.h"
24 #include <math.h>
25 
26 
27 /*
28  * 'cupsLutDelete()' - Free the memory used by a lookup table.
29  */
30 
31 void
cupsLutDelete(cups_lut_t * lut)32 cupsLutDelete(cups_lut_t *lut)		/* I - Lookup table to free */
33 {
34   if (lut != NULL)
35     free(lut);
36 }
37 
38 
39 /*
40  * 'cupsLutLoad()' - Load a LUT from a PPD file.
41  */
42 
43 cups_lut_t *				/* O - New lookup table */
cupsLutLoad(ppd_file_t * ppd,const char * colormodel,const char * media,const char * resolution,const char * ink)44 cupsLutLoad(ppd_file_t *ppd,		/* I - PPD file */
45             const char *colormodel,	/* I - Color model */
46             const char *media,		/* I - Media type */
47             const char *resolution,	/* I - Resolution */
48 	    const char *ink)		/* I - Ink name */
49 {
50   char		name[PPD_MAX_NAME],	/* Attribute name */
51 		spec[PPD_MAX_NAME];	/* Attribute spec */
52   ppd_attr_t	*attr;			/* Attribute */
53   int		nvals;			/* Number of values */
54   float		vals[4];		/* Values */
55 
56 
57  /*
58   * Range check input...
59   */
60 
61   if (!ppd || !colormodel || !media || !resolution || !ink)
62     return (NULL);
63 
64  /*
65   * Try to find the LUT values...
66   */
67 
68   snprintf(name, sizeof(name), "cups%sDither", ink);
69 
70   if ((attr = cupsFindAttr(ppd, name, colormodel, media, resolution, spec,
71                            sizeof(spec))) == NULL)
72     attr = cupsFindAttr(ppd, "cupsAllDither", colormodel, media,
73                         resolution, spec, sizeof(spec));
74 
75   if (!attr)
76     return (NULL);
77 
78   vals[0] = 0.0;
79   vals[1] = 0.0;
80   vals[2] = 0.0;
81   vals[3] = 0.0;
82   nvals   = sscanf(attr->value, "%f%f%f", vals + 1, vals + 2, vals + 3) + 1;
83 
84   fprintf(stderr, "DEBUG: Loaded LUT %s from PPD with values [%.3f %.3f %.3f %.3f]\n",
85           name, vals[0], vals[1], vals[2], vals[3]);
86 
87   return (cupsLutNew(nvals, vals));
88 }
89 
90 
91 /*
92  * 'cupsLutNew()' - Make a lookup table from a list of pixel values.
93  *
94  * Returns a pointer to the lookup table on success, NULL on failure.
95  */
96 
97 cups_lut_t *				/* O - New lookup table */
cupsLutNew(int num_values,const float * values)98 cupsLutNew(int         num_values,	/* I - Number of values */
99 	   const float *values)		/* I - Lookup table values */
100 {
101   int		pixel;			/* Pixel value */
102   cups_lut_t	*lut;			/* Lookup table */
103   int		start,			/* Start value */
104 		end,			/* End value */
105 		maxval;			/* Maximum value */
106 
107 
108  /*
109   * Range check...
110   */
111 
112   if (!num_values || !values)
113     return (NULL);
114 
115  /*
116   * Allocate memory for the lookup table...
117   */
118 
119   if ((lut = (cups_lut_t *)calloc((CUPS_MAX_LUT + 1),
120                                   sizeof(cups_lut_t))) == NULL)
121     return (NULL);
122 
123  /*
124   * Generate the dither lookup table.  The pixel values are roughly
125   * defined by a piecewise linear curve that has an intensity value
126   * at each output pixel.  This isn't perfectly accurate, but it's
127   * close enough for jazz.
128   */
129 
130   maxval = CUPS_MAX_LUT / values[num_values - 1];
131 
132   for (start = 0; start <= CUPS_MAX_LUT; start ++)
133     lut[start].intensity = start * maxval / CUPS_MAX_LUT;
134 
135   for (pixel = 0; pixel < num_values; pixel ++)
136   {
137    /*
138     * Select start and end values for this pixel...
139     */
140 
141     if (pixel == 0)
142       start = 0;
143     else
144       start = (int)(0.5 * maxval * (values[pixel - 1] +
145                                     values[pixel])) + 1;
146 
147     if (start < 0)
148       start = 0;
149     else if (start > CUPS_MAX_LUT)
150       start = CUPS_MAX_LUT;
151 
152     if (pixel == (num_values - 1))
153       end = CUPS_MAX_LUT;
154     else
155       end = (int)(0.5 * maxval * (values[pixel] + values[pixel + 1]));
156 
157     if (end < 0)
158       end = 0;
159     else if (end > CUPS_MAX_LUT)
160       end = CUPS_MAX_LUT;
161 
162     if (start == end)
163       break;
164 
165    /*
166     * Generate lookup values and errors for each pixel.
167     */
168 
169     while (start <= end)
170     {
171       lut[start].pixel = pixel;
172       if (start == 0)
173         lut[0].error = 0;
174       else
175         lut[start].error = start - maxval * values[pixel];
176 
177       start ++;
178     }
179   }
180 
181  /*
182   * Show the lookup table...
183   */
184 
185   for (start = 0; start <= CUPS_MAX_LUT; start += CUPS_MAX_LUT / 15)
186     fprintf(stderr, "DEBUG: %d = %d/%d/%d\n", start, lut[start].intensity,
187             lut[start].pixel, lut[start].error);
188 
189  /*
190   * Return the lookup table...
191   */
192 
193   return (lut);
194 }
195 
196