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