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