1 /*
2 * Test the CMYK color separation code for CUPS.
3 *
4 * Copyright 2007-2011 by Apple Inc.
5 * Copyright 1993-2006 by Easy Software Products, All Rights Reserved.
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 * test_gray() - Test grayscale separations...
15 * test_rgb() - Test color separations...
16 * main() - Do color separation tests.
17 */
18
19 /*
20 * Include necessary headers.
21 */
22
23 #include <config.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include "driver.h"
27 #include <sys/stat.h>
28
29
30 void test_gray(int num_comps, const char *basename);
31 void test_rgb(int num_comps, const char *basename);
32
33
34 /*
35 * 'main()' - Do color separation tests.
36 */
37
38 int /* O - Exit status */
main(int argc,char * argv[])39 main(int argc, /* I - Number of command-line arguments */
40 char *argv[]) /* I - Command-line arguments */
41 {
42 /*
43 * Make the test directory...
44 */
45
46 mkdir("test", 0755);
47
48 /*
49 * Run tests for K, Kk, CMY, CMYK, CcMmYK, and CcMmYKk separations...
50 */
51
52 test_rgb(1, "test/K-rgb");
53 test_rgb(2, "test/Kk-rgb");
54 test_rgb(3, "test/CMY-rgb");
55 test_rgb(4, "test/CMYK-rgb");
56 test_rgb(6, "test/CcMmYK-rgb");
57 test_rgb(7, "test/CcMmYKk-rgb");
58
59 test_gray(1, "test/K-gray");
60 test_gray(2, "test/Kk-gray");
61 test_gray(3, "test/CMY-gray");
62 test_gray(4, "test/CMYK-gray");
63 test_gray(6, "test/CcMmYK-gray");
64 test_gray(7, "test/CcMmYKk-gray");
65
66 /*
67 * Return with no errors...
68 */
69
70 return (0);
71 }
72
73
74 /*
75 * 'test_gray()' - Test grayscale separations...
76 */
77
78 void
test_gray(int num_comps,const char * basename)79 test_gray(int num_comps, /* I - Number of components */
80 const char *basename) /* I - Base filename of output */
81 {
82 int i; /* Looping var */
83 char filename[255]; /* Output filename */
84 char line[255]; /* Line from PGM file */
85 int width, height; /* Width and height of test image */
86 int x, y; /* Current coordinate in image */
87 int r, g, b; /* Current RGB color */
88 unsigned char input[7000]; /* Line to separate */
89 short output[48000], /* Output separation data */
90 *outptr; /* Pointer in output */
91 FILE *in; /* Input PPM file */
92 FILE *out[CUPS_MAX_CHAN];
93 /* Output PGM files */
94 FILE *comp; /* Composite output */
95 cups_cmyk_t *cmyk; /* Color separation */
96
97
98 /*
99 * Open the test image...
100 */
101
102 in = fopen("image.pgm", "rb");
103 while (fgets(line, sizeof(line), in) != NULL)
104 if (isdigit(line[0]))
105 break;
106
107 sscanf(line, "%d%d", &width, &height);
108
109 fgets(line, sizeof(line), in);
110
111 /*
112 * Create the color separation...
113 */
114
115 cmyk = cupsCMYKNew(num_comps);
116
117 switch (num_comps)
118 {
119 case 2 : /* Kk */
120 cupsCMYKSetLtDk(cmyk, 0, 0.5, 1.0);
121 break;
122
123 case 4 :
124 cupsCMYKSetGamma(cmyk, 2, 1.0, 0.9);
125 cupsCMYKSetBlack(cmyk, 0.5, 1.0);
126 break;
127
128 case 6 : /* CcMmYK */
129 cupsCMYKSetLtDk(cmyk, 0, 0.5, 1.0);
130 cupsCMYKSetLtDk(cmyk, 2, 0.5, 1.0);
131 cupsCMYKSetGamma(cmyk, 4, 1.0, 0.9);
132 cupsCMYKSetBlack(cmyk, 0.5, 1.0);
133 break;
134
135 case 7 : /* CcMmYKk */
136 cupsCMYKSetLtDk(cmyk, 0, 0.5, 1.0);
137 cupsCMYKSetLtDk(cmyk, 2, 0.5, 1.0);
138 cupsCMYKSetGamma(cmyk, 4, 1.0, 0.9);
139 cupsCMYKSetLtDk(cmyk, 5, 0.5, 1.0);
140 break;
141 }
142
143 /*
144 * Open the color separation files...
145 */
146
147 for (i = 0; i < num_comps; i ++)
148 {
149 sprintf(filename, "%s%d.pgm", basename, i);
150 out[i] = fopen(filename, "wb");
151
152 fprintf(out[i], "P5\n%d %d 255\n", width, height);
153 }
154
155 sprintf(filename, "%s.ppm", basename);
156 comp = fopen(filename, "wb");
157
158 fprintf(comp, "P6\n%d %d 255\n", width, height);
159
160 /*
161 * Read the image and do the separations...
162 */
163
164 for (y = 0; y < height; y ++)
165 {
166 fread(input, width, 1, in);
167
168 cupsCMYKDoGray(cmyk, input, output, width);
169
170 for (x = 0, outptr = output; x < width; x ++, outptr += num_comps)
171 {
172 for (i = 0; i < num_comps; i ++)
173 putc(255 - 255 * outptr[i] / 4095, out[i]);
174
175 r = 4095;
176 g = 4095;
177 b = 4095;
178
179 switch (num_comps)
180 {
181 case 1 :
182 r -= outptr[0];
183 g -= outptr[0];
184 b -= outptr[0];
185 break;
186 case 2 :
187 r -= outptr[0];
188 g -= outptr[0];
189 b -= outptr[0];
190
191 r -= outptr[1] / 2;
192 g -= outptr[1] / 2;
193 b -= outptr[1] / 2;
194 break;
195 case 3 :
196 r -= outptr[0];
197 g -= outptr[1];
198 b -= outptr[2];
199 break;
200 case 4 :
201 r -= outptr[0];
202 g -= outptr[1];
203 b -= outptr[2];
204
205 r -= outptr[3];
206 g -= outptr[3];
207 b -= outptr[3];
208 break;
209 case 6 :
210 r -= outptr[0] + outptr[1] / 2;
211 g -= outptr[2] + outptr[3] / 3;
212 b -= outptr[4];
213
214 r -= outptr[5];
215 g -= outptr[5];
216 b -= outptr[5];
217 break;
218 case 7 :
219 r -= outptr[0] + outptr[1] / 2;
220 g -= outptr[2] + outptr[3] / 3;
221 b -= outptr[4];
222
223 r -= outptr[5] + outptr[6] / 2;
224 g -= outptr[5] + outptr[6] / 2;
225 b -= outptr[5] + outptr[6] / 2;
226 break;
227 }
228
229 if (r < 0)
230 putc(0, comp);
231 else
232 putc(255 * r / 4095, comp);
233
234 if (g < 0)
235 putc(0, comp);
236 else
237 putc(255 * g / 4095, comp);
238
239 if (b < 0)
240 putc(0, comp);
241 else
242 putc(255 * b / 4095, comp);
243 }
244 }
245
246 for (i = 0; i < num_comps; i ++)
247 fclose(out[i]);
248
249 fclose(comp);
250 fclose(in);
251
252 cupsCMYKDelete(cmyk);
253 }
254
255
256 /*
257 * 'test_rgb()' - Test color separations...
258 */
259
260 void
test_rgb(int num_comps,const char * basename)261 test_rgb(int num_comps, /* I - Number of components */
262 const char *basename) /* I - Base filename of output */
263 {
264 int i; /* Looping var */
265 char filename[255]; /* Output filename */
266 char line[255]; /* Line from PPM file */
267 int width, height; /* Width and height of test image */
268 int x, y; /* Current coordinate in image */
269 int r, g, b; /* Current RGB color */
270 unsigned char input[7000]; /* Line to separate */
271 short output[48000], /* Output separation data */
272 *outptr; /* Pointer in output */
273 FILE *in; /* Input PPM file */
274 FILE *out[CUPS_MAX_CHAN];
275 /* Output PGM files */
276 FILE *comp; /* Composite output */
277 cups_cmyk_t *cmyk; /* Color separation */
278
279
280 /*
281 * Open the test image...
282 */
283
284 in = fopen("image.ppm", "rb");
285 while (fgets(line, sizeof(line), in) != NULL)
286 if (isdigit(line[0]))
287 break;
288
289 sscanf(line, "%d%d", &width, &height);
290
291 fgets(line, sizeof(line), in);
292
293 /*
294 * Create the color separation...
295 */
296
297 cmyk = cupsCMYKNew(num_comps);
298
299 cupsCMYKSetBlack(cmyk, 0.5, 1.0);
300
301 switch (num_comps)
302 {
303 case 2 : /* Kk */
304 cupsCMYKSetLtDk(cmyk, 0, 0.5, 1.0);
305 break;
306 case 6 : /* CcMmYK */
307 cupsCMYKSetGamma(cmyk, 0, 1.0, 0.8);
308 cupsCMYKSetLtDk(cmyk, 0, 0.5, 1.0);
309 cupsCMYKSetGamma(cmyk, 2, 1.0, 0.8);
310 cupsCMYKSetLtDk(cmyk, 2, 0.5, 1.0);
311 break;
312 case 7 : /* CcMmYKk */
313 cupsCMYKSetGamma(cmyk, 0, 1.0, 0.8);
314 cupsCMYKSetLtDk(cmyk, 0, 0.5, 1.0);
315 cupsCMYKSetGamma(cmyk, 2, 1.0, 0.8);
316 cupsCMYKSetLtDk(cmyk, 2, 0.5, 1.0);
317 cupsCMYKSetLtDk(cmyk, 5, 0.5, 1.0);
318 break;
319 }
320
321 /*
322 * Open the color separation files...
323 */
324
325 for (i = 0; i < num_comps; i ++)
326 {
327 sprintf(filename, "%s%d.pgm", basename, i);
328 out[i] = fopen(filename, "wb");
329
330 fprintf(out[i], "P5\n%d %d 255\n", width, height);
331 }
332
333 sprintf(filename, "%s.ppm", basename);
334 comp = fopen(filename, "wb");
335
336 fprintf(comp, "P6\n%d %d 255\n", width, height);
337
338 /*
339 * Read the image and do the separations...
340 */
341
342 for (y = 0; y < height; y ++)
343 {
344 fread(input, width, 3, in);
345
346 cupsCMYKDoRGB(cmyk, input, output, width);
347
348 for (x = 0, outptr = output; x < width; x ++, outptr += num_comps)
349 {
350 for (i = 0; i < num_comps; i ++)
351 putc(255 - 255 * outptr[i] / 4095, out[i]);
352
353 r = 4095;
354 g = 4095;
355 b = 4095;
356
357 switch (num_comps)
358 {
359 case 1 :
360 r -= outptr[0];
361 g -= outptr[0];
362 b -= outptr[0];
363 break;
364 case 2 :
365 r -= outptr[0];
366 g -= outptr[0];
367 b -= outptr[0];
368
369 r -= outptr[1] / 2;
370 g -= outptr[1] / 2;
371 b -= outptr[1] / 2;
372 break;
373 case 3 :
374 r -= outptr[0];
375 g -= outptr[1];
376 b -= outptr[2];
377 break;
378 case 4 :
379 r -= outptr[0];
380 g -= outptr[1];
381 b -= outptr[2];
382
383 r -= outptr[3];
384 g -= outptr[3];
385 b -= outptr[3];
386 break;
387 case 6 :
388 r -= outptr[0] + outptr[1] / 2;
389 g -= outptr[2] + outptr[3] / 3;
390 b -= outptr[4];
391
392 r -= outptr[5];
393 g -= outptr[5];
394 b -= outptr[5];
395 break;
396 case 7 :
397 r -= outptr[0] + outptr[1] / 2;
398 g -= outptr[2] + outptr[3] / 3;
399 b -= outptr[4];
400
401 r -= outptr[5] + outptr[6] / 2;
402 g -= outptr[5] + outptr[6] / 2;
403 b -= outptr[5] + outptr[6] / 2;
404 break;
405 }
406
407 if (r < 0)
408 putc(0, comp);
409 else
410 putc(255 * r / 4095, comp);
411
412 if (g < 0)
413 putc(0, comp);
414 else
415 putc(255 * g / 4095, comp);
416
417 if (b < 0)
418 putc(0, comp);
419 else
420 putc(255 * b / 4095, comp);
421 }
422 }
423
424 for (i = 0; i < num_comps; i ++)
425 fclose(out[i]);
426
427 fclose(comp);
428 fclose(in);
429
430 cupsCMYKDelete(cmyk);
431 }
432
433