Tizen 2.0 Release
[platform/upstream/cups-filters.git] / cupsfilters / lut.c
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  */