Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1995, 1996 Aladdin Enterprises.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
 
17
/* $Id: gdevstc4.c,v 1.4 2002/02/21 22:24:52 giles Exp $*/
18
/* Epson Stylus-Color Printer-Driver */
19
 
20
/***
21
     This file holds a byte-Implementation of the Floyd-Steinberg error
22
     diffusion-algorithm. This algorithm is an alternative for high quality 
23
     printing in conjunction with the PostScript-Header stcolor.ps:
24
 
25
          gs -sDEVICE=stcolor -sDithering=fs2 <other options> stcolor.ps ...
26
 
27
     THIS ALGORIHM WAS WRITTEN BY STEVEN SINGER (S.Singer@ph.surrey.ac.uk)
28
     AS PART OF escp2cfs2. 
29
     THIS IMPLEMENTATION INCORPORATES ONLY FEW CHANGES TO THE ORIGINAL CODE.
30
 
31
 ***/
32
 
33
#include "gdevstc.h"
34
 
35
/*
36
 * escp2c_pick best scans for best matching color 
37
 */
38
private byte *
39
escp2c_pick_best(byte *col)
40
{
41
    static byte colour[8][3] = {
42
       {  0,  0,  0},{255,  0,  0},{  0,255,  0},{255,255,  0},
43
       {  0,  0,255},{255,  0,255},{  0,255,255},{255,255,255}};
44
    register int x, y, z, dx, dy, dz, dz2, dx2, dx3, dx4;
45
    register byte *p;
46
    register long md, d;
47
 
48
    md = 16777216; /* plenty */
49
 
50
/*
51
   Note that I don't use a simple distance algorithm. That can lead to a block
52
   of (130,127,127) being dithered as red-cyan. This algorithm should make
53
   it use black-white-red. This is very important, as a coloured block in
54
   the middle of a grey block can, via error diffusion, perturb the
55
   surrounding colours sufficiently for this to happen.
56
*/
57
 
58
/*
59
   The next bit is equivalent to this, but faster.
60
 
61
    x = col[0];
62
    y = col[1];
63
    z = col[2];
64
    for(n=8; n--; )
65
    {
66
	dx = x - colour[n][0];
67
	dy = y - colour[n][1];
68
	dz = z - colour[n][2];
69
	d = dx*(dx-(dy>>1)) + dy*(dy-(dz>>1)) + dz*(dz-(dx>>1));
70
	if (d < md)
71
	{
72
	    md = d;
73
	    p = n;
74
	}
75
    }
76
*/
77
 
78
/*
79
 * Test colours in gray code order to reduce number of recalculations.
80
 * I bet you can't find an optimiser that would do this automatically.
81
 */
82
 
83
    x = col[0];
84
    y = col[1];
85
    z = col[2];
86
    dx = x*(x-(y>>1));
87
    dy = y*(y-(z>>1));
88
    dz = z*(z-(x>>1));
89
    md = dx + dy + dz;
90
    p = colour[0];
91
    x -= 255;
92
    dx2 = x*(x-(y>>1));
93
    dz2 = z*(z-(x>>1));
94
    if ((d = dx2 + dy + dz2) < md) {md = d; p = colour[1];}
95
    y -= 255;
96
    dx3 = x*(x-(y>>1));
97
    dy = y*(y-(z>>1));
98
    if ((d = dx3 + dy + dz2) < md) {md = d; p = colour[3];}
99
    x += 255;
100
    dx4 = x*(x-(y>>1));
101
    if ((d = dx4 + dy + dz) < md) {md = d; p = colour[2];}
102
    z -= 255;
103
    dy = y*(y-(z>>1));
104
    dz = z*(z-(x>>1));
105
    if ((d = dx4 + dy + dz) < md) {md = d; p = colour[6];}
106
    x -= 255;
107
    dz2 = z*(z-(x>>1));
108
    if ((d = dx3 + dy + dz2) < md) {md = d; p = colour[7];}
109
    y += 255;
110
    dy = y*(y-(z>>1));
111
    if ((d = dx2 + dy + dz2) < md) {md = d; p = colour[5];}
112
    if ((d = dx + dy + dz) < md) {p = colour[4];}
113
    return(p);
114
}
115
 
116
/*
117
 * escp2c_conv_stc converts into the ouput format used by stcolor
118
 */
119
private void
120
escp2c_conv_stc(byte *p, byte *q, int i)
121
{
122
    for(; i; p+=3, i-=3)
123
        *q++ = (*p & RED) | (p[1] & GREEN) | (p[2] & BLUE);
124
}
125
 
126
 
127
/*
128
 * Limit byte-values
129
 */
130
#define LIMIT(a) if (a > 255) a = 255; if (a < 0) a = 0
131
#define LIMIT2(a) if (a > 127) a = 127; if (a < -128) a = -128; \
132
                if (a < 0) a += 256
133
/*
134
 * Main routine of the algorithm
135
 */
136
int 
137
stc_fs2(stcolor_device *sd,int npixel,byte *in,byte *buf,byte *out)
138
{
139
   int fullcolor_line_size = npixel*3;
140
 
141
/* ============================================================= */
142
   if(npixel > 0) {  /* npixel >  0 -> scanline-processing       */
143
/* ============================================================= */
144
 
145
/*    -------------------------------------------------------------------- */
146
      if(in == NULL) { /* clear the error-buffer upon white-lines */
147
/*    -------------------------------------------------------------------- */
148
 
149
         memset(buf,0,fullcolor_line_size);
150
 
151
/*    ------------------------------------------------------------------- */
152
      } else {                 /* do the actual dithering                 */
153
/*    ------------------------------------------------------------------- */
154
    int i, j, k, e, l, i2, below[3][3], *fb, *b, *bb, *tb;
155
    byte *p, *q, *cp;
156
    static int dir = 1;
157
 
158
    p = buf;
159
    if (*p != 0 || memcmp((char *) p, (char *) p + 1, fullcolor_line_size - 1))
160
    {
161
	for(p = in, q=buf, i=fullcolor_line_size;
162
	    i--; p++, q++ )
163
	{
164
	    j = *p + ((*q & 128) ? *q - 256 : *q);
165
	    LIMIT(j);
166
	    *p = j;
167
	}
168
    }
169
 
170
    p = in;
171
 
172
	fb = below[2];
173
	b = below[1];
174
	bb = below[0];
175
	*b = b[1] = b[2] = *bb = bb[1] = bb[2] = 0;
176
 
177
	if (dir)
178
	{
179
	    for(p = in, q=buf-3,
180
		i=fullcolor_line_size; i; i-=3)
181
	    {
182
		cp = escp2c_pick_best(p);
183
		for(i2=3; i2--; p++, q++, fb++, b++, bb++)
184
		{
185
		    j = *p;
186
		    *p = *cp++;
187
		    j -= *p;
188
		    if (j != 0)
189
		    {
190
			l = (e = (j>>1)) - (*fb = (j>>4));
191
			if (i > 2)
192
			{
193
			    k = p[3] + l;
194
			    LIMIT(k);
195
			    p[3] = k;
196
			}
197
			*b += e - (l = (j>>2) - *fb);
198
			if (i < fullcolor_line_size)
199
			{
200
			    l += *bb;
201
			    LIMIT2(l);
202
			    *q = l;
203
			}
204
		    }
205
		    else
206
			*fb = 0;
207
		}
208
		tb = bb-3;
209
		bb = b-3;
210
		b = fb-3;
211
		fb = tb;
212
	    }
213
	    *q = *bb;
214
	    q[1] = bb[1];
215
	    q[2] = bb[2];
216
	    dir = 0;
217
	}
218
	else
219
	{
220
	    for(p = in+fullcolor_line_size-1,
221
		q = buf+fullcolor_line_size+2, i=fullcolor_line_size; 
222
                i; i-=3)
223
	    {
224
		cp = escp2c_pick_best(p-2) + 2;
225
		for(i2=3; i2--; p--, q--, fb++, b++, bb++)
226
		{
227
		    j = *p;
228
		    *p = *cp--;
229
		    j -= *p;
230
		    if (j != 0)
231
		    {
232
			l = (e = (j>>1)) - (*fb = (j>>4));
233
			if (i > 2)
234
			{
235
			    k = p[-3] + l;
236
			    LIMIT(k);
237
			    p[-3] = k;
238
			}
239
			*b += e - (l = (j>>2) - *fb);
240
			if (i < fullcolor_line_size)
241
			{
242
			    l += *bb;
243
			    LIMIT2(l);
244
			    *q = l;
245
			}
246
		    }
247
		    else
248
			*fb = 0;
249
		}
250
		tb = bb-3;
251
		bb = b-3;
252
		b = fb-3;
253
		fb = tb;
254
	    }
255
	    *q = *bb;
256
	    q[1] = bb[1];
257
	    q[2] = bb[2];
258
	    dir = 1;
259
	}
260
 
261
    escp2c_conv_stc(in, out, fullcolor_line_size);
262
 
263
/*    ------------------------------------------------------------------- */
264
      }                        /* buffer-reset | dithering                */
265
/*    ------------------------------------------------------------------- */
266
 
267
 
268
/* ============================================================= */
269
   } else {          /* npixel <= 0 -> initialisation            */
270
/* ============================================================= */
271
 
272
 
273
/*
274
 * check wether the number of components is valid
275
 */
276
      if(sd->color_info.num_components != 3)                       return -1;
277
 
278
/*
279
 * check wether stcdither & TYPE are correct
280
 */
281
      if(( sd->stc.dither                    == NULL) ||
282
         ((sd->stc.dither->flags & STC_TYPE) != STC_BYTE))         return -2;
283
 
284
/*
285
 * check wether the buffer-size is sufficiently large
286
 */
287
      if((sd->stc.dither->flags/STC_SCAN) < 1)                     return -3;
288
 
289
/*
290
 * finally clear the buffer
291
 */
292
      memset(buf,0,-fullcolor_line_size);
293
 
294
/* ============================================================= */
295
   } /* scanline-processing or initialisation */
296
/* ============================================================= */
297
 
298
   return 0;
299
}