]>
git.ipfire.org Git - thirdparty/cups.git/blob - driver/dither.c
4 * Dithering routines for CUPS.
6 * Copyright 2007 by Apple Inc.
7 * Copyright 1993-2005 by Easy Software Products.
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/".
17 * cupsDitherDelete() - Free a dithering buffer.
18 * cupsDitherLine() - Dither a line of pixels...
19 * cupsDitherNew() - Create a dithering buffer.
23 * Include necessary headers.
30 * Random number function to use, in order of preference...
34 # define RANDOM_FUNCTION random
35 #elif defined(HAVE_MRAND48)
36 # define RANDOM_FUNCTION mrand48
37 #elif defined(HAVE_LRAND48)
38 # define RANDOM_FUNCTION lrand48
40 # define RANDOM_FUNCTION rand
41 #endif /* HAVE_RANDOM */
45 * 'cupsDitherDelete()' - Free a dithering buffer.
47 * Returns 0 on success, -1 on failure.
51 cupsDitherDelete(cups_dither_t
*d
) /* I - Dithering buffer */
59 * 'cupsDitherLine()' - Dither a line of pixels...
63 cupsDitherLine(cups_dither_t
*d
, /* I - Dither data */
64 const cups_lut_t
*lut
, /* I - Lookup table */
65 const short *data
, /* I - Separation data */
67 /* I - Number of components */
68 unsigned char *p
) /* O - Pixels */
70 register int x
, /* Horizontal position in line... */
71 pixel
, /* Current adjusted pixel... */
72 e
, /* Current error */
73 e0
,e1
,e2
; /* Error values */
74 register int errval0
, /* First half of error value */
75 errval1
, /* Second half of error value */
76 errbase
, /* Base multiplier */
77 errbase0
, /* Base multiplier for large values */
78 errbase1
, /* Base multiplier for small values */
79 errrange
; /* Range of random multiplier */
80 register int *p0
, /* Error buffer pointers... */
82 static char logtable
[16384]; /* Error magnitude for randomness */
83 static char loginit
= 0; /* Has the table been initialized? */
89 * Initialize a logarithmic table for the magnitude of randomness
96 for (x
= 1; x
< 2049; x
++)
97 logtable
[x
] = (int)(log(x
/ 16.0) / log(2.0) + 1.0);
98 for (; x
< 16384; x
++)
99 logtable
[x
] = logtable
[2049];
105 * Dither from left to right:
108 * e1 e2 == p1[-1] p1[0]
112 p1
= d
->errors
+ 2 + d
->width
+ 4;
118 * Error diffuse each output pixel...
123 x
--, p0
++, p1
++, p
++, data
+= num_channels
)
126 * Skip blank pixels...
140 * Compute the net pixel brightness and brightness error. Set a dot
144 pixel
= lut
[*data
].intensity
+ e0
/ 128;
146 if (pixel
> CUPS_MAX_LUT
)
147 pixel
= CUPS_MAX_LUT
;
151 *p
= lut
[pixel
].pixel
;
152 e
= lut
[pixel
].error
;
155 * Set the randomness factor...
159 errrange
= logtable
[e
];
161 errrange
= logtable
[-e
];
163 errbase
= 8 - errrange
;
164 errrange
= errrange
* 2 + 1;
167 * Randomize the error value.
172 errbase0
= errbase
+ (RANDOM_FUNCTION() % errrange
);
173 errbase1
= errbase
+ (RANDOM_FUNCTION() % errrange
);
176 errbase0
= errbase1
= errbase
;
180 * 3/16 5/16 1/16 = e1 e2
183 errval0
= errbase0
* e
;
184 errval1
= (16 - errbase0
) * e
;
185 e0
= p0
[1] + 7 * errval0
;
186 e1
= e2
+ 5 * errval1
;
188 errval0
= errbase1
* e
;
189 errval1
= (16 - errbase1
) * e
;
191 p1
[-1] = e1
+ 3 * errval1
;
197 * Dither from right to left:
200 * e2 e1 == p1[0] p1[1]
203 p0
= d
->errors
+ d
->width
+ 1 + d
->width
+ 4;
204 p1
= d
->errors
+ d
->width
+ 1;
206 data
+= num_channels
* (d
->width
- 1);
212 * Error diffuse each output pixel...
217 x
--, p0
--, p1
--, p
--, data
-= num_channels
)
220 * Skip blank pixels...
234 * Compute the net pixel brightness and brightness error. Set a dot
238 pixel
= lut
[*data
].intensity
+ e0
/ 128;
240 if (pixel
> CUPS_MAX_LUT
)
241 pixel
= CUPS_MAX_LUT
;
245 *p
= lut
[pixel
].pixel
;
246 e
= lut
[pixel
].error
;
249 * Set the randomness factor...
253 errrange
= logtable
[e
];
255 errrange
= logtable
[-e
];
257 errbase
= 8 - errrange
;
258 errrange
= errrange
* 2 + 1;
261 * Randomize the error value.
266 errbase0
= errbase
+ (RANDOM_FUNCTION() % errrange
);
267 errbase1
= errbase
+ (RANDOM_FUNCTION() % errrange
);
270 errbase0
= errbase1
= errbase
;
274 * 3/16 5/16 1/16 = e1 e2
277 errval0
= errbase0
* e
;
278 errval1
= (16 - errbase0
) * e
;
279 e0
= p0
[-1] + 7 * errval0
;
280 e1
= e2
+ 5 * errval1
;
282 errval0
= errbase1
* e
;
283 errval1
= (16 - errbase1
) * e
;
285 p1
[1] = e1
+ 3 * errval1
;
290 * Update to the next row...
298 * 'cupsDitherNew()' - Create an error-diffusion dithering buffer.
301 cups_dither_t
* /* O - New state array */
302 cupsDitherNew(int width
) /* I - Width of output in pixels */
304 cups_dither_t
*d
; /* New dithering buffer */
307 if ((d
= (cups_dither_t
*)calloc(1, sizeof(cups_dither_t
) +
309 sizeof(int))) == NULL
)