1 /*
2  * Author:    Yoichiro Ueno (ueno@cs.titech.ac.jp)
3  *
4  * Copyright (C) 1991, 1992, Yoichiro Ueno.
5  *
6  * Permission to use, copy, modify, and distribute this software and
7  * its documentation for any purpose is hereby granted by the Author without
8  * fee, provided that the above copyright notice appear in all copies and
9  * that both the copyright notice and this permission notice appear in
10  * supporting documentation, and that the name of the Author not be used
11  * in advertising or publicity pertaining to distribution of the software
12  * without specific, written prior permission.  The Author makes no
13  * representations about the suitability of this software for any purpose.
14  * It is provided "as is" without express or implied warranty.
15  *
16  * THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
20  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22  * PERFORMANCE OF THIS SOFTWARE.
23  *
24  */
25 
26 #include "video.h"
27 #include "proto.h"
28 #include "dither.h"
29 
30 
31 
32 /*
33  *--------------------------------------------------------------
34  *
35  * MonoDitherImage --
36  *
37  *    Dithers image into monochrome.
38  *    Dither algorithm is based on dither.c in xli.1.11.
39  *
40  * Results:
41  *    None.
42  *
43  * Side effects:
44  *    None.
45  *
46  *--------------------------------------------------------------
47  */
48 #define MaxGrey        65280
49 #define Threshold    (MaxGrey/2)
50 #define MinGrey        0
51 
52 #if LITTLE_ENDIAN_ARCHITECTURE
53 #    define SEED_BIT 0x01
54 #    define OPP_SEED_BIT 0x80
55 #    define SHIFT_SEED_BIT(b) (b <<= 1)
56 #    define OPP_SHIFT_SEED_BIT(b) (b >>= 1)
57 #else
58 #    define SEED_BIT 0x80
59 #    define OPP_SEED_BIT 0x01
60 #    define SHIFT_SEED_BIT(b) (b >>= 1)
61 #    define OPP_SHIFT_SEED_BIT(b) (b <<= 1)
62 #endif
63 
64 static int    *curr = NULL;
65 static int    *next = NULL;
66 
67 void
MonoDitherImage(lum,cr,cb,out,h,w)68 MonoDitherImage(lum, cr, cb, out, h, w)
69     register unsigned char *lum;
70     unsigned char *cr;
71     unsigned char *cb;
72     register unsigned char *out;
73     int w, h;
74 {
75   int bit_r2l;
76   register unsigned int bit;
77   register unsigned int data;
78   int i;
79   register int j;
80   int *swap;
81   register int out_err;
82   register int next1;
83   register int next2;
84 
85   if (curr == NULL) {
86     curr = (int *)malloc((unsigned int) sizeof(int) * (w + 2));
87     curr += 1;
88   }
89   if (next == NULL) {
90     next = (int *)malloc((unsigned int) sizeof(int) * (w + 2));
91     next += 1;
92   }
93 
94   memset ((char *)curr, 0, (size_t)w * sizeof(*curr));
95 
96   bit_r2l = SEED_BIT << (w - 1 & 7);
97   for (i = 0; i < h; i ++) {
98     if (i & 0x01) {                /* Right to Left */
99       bit = bit_r2l;
100       data = 0;
101       out_err = curr[w-1];
102       next1 = 0;
103       next2 = 0;
104       for (j=(w-1); j>=0; j--)
105       {
106         out_err = (out_err >> 4) + (lum[j] << 8);
107         if (out_err > Threshold) {
108           data |= bit;
109           out_err -= MaxGrey;
110         }
111         else
112           out_err -= MinGrey;
113 
114         next[j+1] = next1 +     (out_err * 3);
115         next1     = next2 +     (out_err * 5);
116         next2     =             (out_err * 1);
117         out_err   = curr[j-1] + (out_err * 7);
118 
119         OPP_SHIFT_SEED_BIT(bit);
120 #if LITTLE_ENDIAN_ARCHITECTURE
121         if (bit == 0) {
122 #else
123         if (bit > 0x80) {
124 #endif
125           out[j >> 3] = data;
126           bit = OPP_SEED_BIT;
127           data = 0;
128         }
129       }
130       next[0] = next1;
131     }
132     else {                    /* Left to Right */
133       bit = SEED_BIT;
134       data = 0;
135       out_err = curr[0];
136       next1 = 0;
137       next2 = 0;
138       for (j=0; j<w; j++)
139       {
140         out_err = (out_err >> 4) + (lum[j] << 8);
141         if (out_err > Threshold) {
142           data |= bit;
143           out_err = out_err - MaxGrey;
144         }
145         else
146           out_err = out_err - MinGrey;
147 
148         next[j-1] = next1 +     (out_err * 3);
149         next1     = next2 +     (out_err * 5);
150         next2     =             (out_err * 1);
151         out_err   = curr[j+1] + (out_err * 7);
152 
153         SHIFT_SEED_BIT(bit);
154 #if LITTLE_ENDIAN_ARCHITECTURE
155         if (bit > 0x80) {
156 #else
157         if (bit == 0) {
158 #endif
159           out[j >> 3] = data;
160           bit = SEED_BIT;
161           data = 0;
162         }
163       }
164       next[w-1] = next1;
165     }
166 
167     lum += w;
168     out += w >> 3;
169     swap = curr;
170     curr = next;
171     next = swap;
172   }
173 }
174 
175 
176 
177 /*
178  *--------------------------------------------------------------
179  *
180  * MonoThresholdImage --
181  *
182  *    convert image into monochrome with threshold.
183  *
184  * Results:
185  *    None.
186  *
187  * Side effects:
188  *    None.
189  *
190  *--------------------------------------------------------------
191  */
192 void
MonoThresholdImage(lum,cr,cb,out,h,w)193 MonoThresholdImage(lum, cr, cb, out, h, w)
194     unsigned char *lum;
195     unsigned char *cr;
196     unsigned char *cb;
197     unsigned char *out;
198     int w, h;
199 {
200   unsigned char bit;
201   unsigned char data;
202 
203   bit = SEED_BIT;
204   data = 0;
205   for (w*=h; w>0; w--) {
206     if(*lum++>128)
207       data |= bit;
208 
209     SHIFT_SEED_BIT(bit);
210     if(bit == 0) {
211       *out ++ = data;
212       bit = SEED_BIT;
213       data = 0;
214     }
215   }
216 }
217