Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2 | pj | 1 | /* |
2 | * 2x2.c -- |
||
3 | * |
||
4 | * Procedures concerned with 2x2 dithering. |
||
5 | * |
||
6 | */ |
||
7 | |||
8 | /* |
||
9 | * Copyright (c) 1995 The Regents of the University of California. |
||
10 | * All rights reserved. |
||
11 | * |
||
12 | * Permission to use, copy, modify, and distribute this software and its |
||
13 | * documentation for any purpose, without fee, and without written agreement is |
||
14 | * hereby granted, provided that the above copyright notice and the following |
||
15 | * two paragraphs appear in all copies of this software. |
||
16 | * |
||
17 | * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR |
||
18 | * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT |
||
19 | * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF |
||
20 | * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
21 | * |
||
22 | * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, |
||
23 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY |
||
24 | * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
||
25 | * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO |
||
26 | * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
||
27 | */ |
||
28 | |||
29 | #include "video.h" |
||
30 | #include "dither.h" |
||
31 | #include "proto.h" |
||
32 | #ifdef __STDC__ |
||
33 | #include <stdlib.h> |
||
34 | #endif |
||
35 | |||
36 | #define RAND_ERR_RANGE 7 |
||
37 | #define RAND_ERR_SUBVAL 3 |
||
38 | |||
39 | #define NO_LRAND48 |
||
40 | #define NO_RANDOM |
||
41 | |||
42 | /* Array containing actual pixel values for each possible 2x2 dither pattern. */ |
||
43 | |||
44 | static unsigned char *dith_a; |
||
45 | |||
46 | /* Arrays mapping lum, cr, and cb values to portions of dither pattern code. |
||
47 | The addtion of one value from each array yields a valid dither pattern |
||
48 | code. |
||
49 | */ |
||
50 | |||
51 | static int lval_a[256+RAND_ERR_RANGE-1]; |
||
52 | static int rval_a[256+RAND_ERR_RANGE-1]; |
||
53 | static int bval_a[256+RAND_ERR_RANGE-1]; |
||
54 | |||
55 | /* Range of possible dither patterns in each channel. */ |
||
56 | |||
57 | #define L_DITH_RANGE (((LUM_RANGE-1)*4)+1) |
||
58 | #define CR_DITH_RANGE (((CR_RANGE-1)*4)+1) |
||
59 | #define CB_DITH_RANGE (((CB_RANGE-1)*4)+1) |
||
60 | |||
61 | /* Arrays of random error terms added to break up contours. */ |
||
62 | |||
63 | static int *randval_a; |
||
64 | static int **randptr_a; |
||
65 | |||
66 | |||
67 | /* |
||
68 | *-------------------------------------------------------------- |
||
69 | * |
||
70 | * Init2x2Dither-- |
||
71 | * |
||
72 | * Initializes structures used for 2x2 dithering. |
||
73 | * |
||
74 | * Results: |
||
75 | * None. |
||
76 | * |
||
77 | * Side effects: |
||
78 | * None. |
||
79 | * |
||
80 | *-------------------------------------------------------------- |
||
81 | */ |
||
82 | |||
83 | void |
||
84 | Init2x2Dither() |
||
85 | { |
||
86 | unsigned char *dith_ca; |
||
87 | int numcodes; |
||
88 | int l_range, cr_range, cb_range; |
||
89 | int p1, p2, p3, p4; |
||
90 | int l_dith, cr_dith, cb_dith; |
||
91 | int big_part, small_part; |
||
92 | int i, j; |
||
93 | |||
94 | l_range = L_DITH_RANGE; |
||
95 | cr_range = CR_DITH_RANGE; |
||
96 | cb_range = CB_DITH_RANGE; |
||
97 | |||
98 | numcodes = l_range * cr_range * cb_range; |
||
99 | |||
100 | dith_a = (unsigned char *) malloc(numcodes*4); |
||
101 | |||
102 | dith_ca = dith_a; |
||
103 | |||
104 | for (i=0; i<numcodes; i++) { |
||
105 | l_dith = i % l_range; |
||
106 | |||
107 | big_part = l_dith / 4; |
||
108 | small_part = l_dith % 4; |
||
109 | |||
110 | p1 = big_part + ((small_part > 0) ? 1 : 0); |
||
111 | p2 = big_part + ((small_part > 2) ? 1 : 0); |
||
112 | p3 = big_part; |
||
113 | p4 = big_part + ((small_part > 1) ? 1 : 0); |
||
114 | |||
115 | p1 *= CR_RANGE * CB_RANGE; |
||
116 | p2 *= CR_RANGE * CB_RANGE; |
||
117 | p3 *= CR_RANGE * CB_RANGE; |
||
118 | p4 *= CR_RANGE * CB_RANGE; |
||
119 | |||
120 | cr_dith = (i/l_range) % cr_range; |
||
121 | |||
122 | big_part = cr_dith / 4; |
||
123 | small_part = cr_dith % 4; |
||
124 | |||
125 | p1 += (big_part + ((small_part > 0) ? 1 : 0))*CB_RANGE; |
||
126 | p2 += (big_part + ((small_part > 2) ? 1 : 0))*CB_RANGE; |
||
127 | p3 += (big_part)*CB_RANGE; |
||
128 | p4 += (big_part + ((small_part > 1) ? 1 : 0))*CB_RANGE; |
||
129 | |||
130 | cb_dith = (i/(cr_range*l_range)) % cb_range; |
||
131 | |||
132 | big_part = cb_dith / 4; |
||
133 | small_part = cb_dith % 4; |
||
134 | |||
135 | p1 += (big_part + ((small_part > 0) ? 1 : 0)); |
||
136 | p2 += (big_part + ((small_part > 2) ? 1 : 0)); |
||
137 | p3 += (big_part); |
||
138 | p4 += (big_part + ((small_part > 1) ? 1 : 0)); |
||
139 | |||
140 | *dith_ca++ = p1; |
||
141 | *dith_ca++ = p2; |
||
142 | *dith_ca++ = p3; |
||
143 | *dith_ca++ = p4; |
||
144 | } |
||
145 | |||
146 | for (i=RAND_ERR_SUBVAL; i<256+RAND_ERR_SUBVAL; i++) { |
||
147 | j = i-RAND_ERR_SUBVAL; |
||
148 | lval_a[i] = (j * L_DITH_RANGE)/256; |
||
149 | rval_a[i] = (j * CR_DITH_RANGE)/256; |
||
150 | bval_a[i] = (j * CB_DITH_RANGE)/256; |
||
151 | |||
152 | bval_a[i] *= CR_DITH_RANGE * L_DITH_RANGE * 4; |
||
153 | rval_a[i] *= L_DITH_RANGE * 4; |
||
154 | lval_a[i] *= 4; |
||
155 | } |
||
156 | |||
157 | for (i=0; i<RAND_ERR_SUBVAL; i++) { |
||
158 | lval_a[i] = lval_a[RAND_ERR_SUBVAL]; |
||
159 | rval_a[i] = rval_a[RAND_ERR_SUBVAL]; |
||
160 | bval_a[i] = bval_a[RAND_ERR_SUBVAL]; |
||
161 | } |
||
162 | |||
163 | for(i=256+RAND_ERR_SUBVAL; i<256+RAND_ERR_RANGE-1; i++) { |
||
164 | lval_a[i] = lval_a[255+RAND_ERR_SUBVAL]; |
||
165 | rval_a[i] = rval_a[255+RAND_ERR_SUBVAL]; |
||
166 | bval_a[i] = bval_a[255+RAND_ERR_SUBVAL]; |
||
167 | } |
||
168 | } |
||
169 | |||
170 | |||
171 | /* |
||
172 | *-------------------------------------------------------------- |
||
173 | * |
||
174 | * RandInit -- |
||
175 | * |
||
176 | * Initializes the random values used for 2x2 dithering. |
||
177 | * |
||
178 | * Results: |
||
179 | * randval_a filled with random values. |
||
180 | * randptr_a filled with random pointers to random value arrays. |
||
181 | * |
||
182 | * Side effects: |
||
183 | * None. |
||
184 | * |
||
185 | *-------------------------------------------------------------- |
||
186 | */ |
||
187 | |||
188 | void RandInit(h, w) |
||
189 | int h, w; |
||
190 | { |
||
191 | int i; |
||
192 | |||
193 | randval_a = (int *) malloc(w*5*sizeof(int)); |
||
194 | randptr_a = (int **) malloc(h*sizeof(int *)); |
||
195 | |||
196 | #ifdef NO_LRAND48 |
||
197 | for (i=0; i<w*5; i++) { |
||
198 | #ifdef NO_RANDOM |
||
199 | #define random() rand() |
||
200 | #else |
||
201 | long int random(); |
||
202 | #endif |
||
203 | |||
204 | randval_a[i] = random() % RAND_ERR_RANGE; |
||
205 | } |
||
206 | |||
207 | for (i=0; i<h; i++) { |
||
208 | #ifndef NO_RANDOM |
||
209 | long int random(); |
||
210 | #endif |
||
211 | |||
212 | randptr_a[i] = randval_a + (random() % (w*2)); |
||
213 | } |
||
214 | #else /* NO_LRAND48 */ |
||
215 | |||
216 | for (i=0; i<w*5; i++) { |
||
217 | long int lrand48(); |
||
218 | |||
219 | randval_a[i] = lrand48() % RAND_ERR_RANGE; |
||
220 | } |
||
221 | |||
222 | for (i=0; i<h; i++) { |
||
223 | long int lrand48(); |
||
224 | |||
225 | randptr_a[i] = randval_a + (lrand48() % (w*2)); |
||
226 | } |
||
227 | #endif |
||
228 | |||
229 | } |
||
230 | |||
231 | |||
232 | /* |
||
233 | *-------------------------------------------------------------- |
||
234 | * |
||
235 | * PostInit2x2Dither-- |
||
236 | * |
||
237 | * Remaps color numbers in dither patterns to actual pixel |
||
238 | * values allocated by the X server. |
||
239 | * |
||
240 | * Results: |
||
241 | * None. |
||
242 | * |
||
243 | * Side effects: |
||
244 | * None. |
||
245 | * |
||
246 | *-------------------------------------------------------------- |
||
247 | */ |
||
248 | |||
249 | void |
||
250 | PostInit2x2Dither() |
||
251 | { |
||
252 | unsigned char *dith_ca; |
||
253 | int i; |
||
254 | |||
255 | dith_ca = dith_a; |
||
256 | |||
257 | for (i=0; i < (L_DITH_RANGE * CR_DITH_RANGE * CB_DITH_RANGE); i++) { |
||
258 | |||
259 | *dith_ca = pixel[*dith_ca]; |
||
260 | dith_ca++; |
||
261 | *dith_ca = pixel[*dith_ca]; |
||
262 | dith_ca++; |
||
263 | *dith_ca = pixel[*dith_ca]; |
||
264 | dith_ca++; |
||
265 | *dith_ca = pixel[*dith_ca]; |
||
266 | dith_ca++; |
||
267 | } |
||
268 | } |
||
269 | |||
270 | |||
271 | /* |
||
272 | *-------------------------------------------------------------- |
||
273 | * |
||
274 | * Twox2DitherImage -- |
||
275 | * |
||
276 | * Dithers lum, cr, and cb channels togethor using predefined |
||
277 | * and computed 2x2 dither patterns. Each possible combination of |
||
278 | * lum, cr, and cb values combines to point to a particular dither |
||
279 | * pattern (2x2) which is used to represent the pixel. This assumes |
||
280 | * That the display plane is 4 times larger than the lumianance |
||
281 | * plane. |
||
282 | * |
||
283 | * Results: |
||
284 | * None. |
||
285 | * |
||
286 | * Side effects: |
||
287 | * None. |
||
288 | * |
||
289 | *-------------------------------------------------------------- |
||
290 | */ |
||
291 | |||
292 | void |
||
293 | Twox2DitherImage(lum, cr, cb, out, h, w) |
||
294 | unsigned char *lum; |
||
295 | unsigned char *cr; |
||
296 | unsigned char *cb; |
||
297 | unsigned char *out; |
||
298 | int w, h; |
||
299 | { |
||
300 | int i, j; |
||
301 | unsigned short *o1, *o2, *o3, *o4; |
||
302 | unsigned char *l1, *l2, *base; |
||
303 | unsigned char B, R; |
||
304 | unsigned short *dith_ca; |
||
305 | int big_adv = 3*w; |
||
306 | int b_val, r_val, l_val; |
||
307 | static int first = 1; |
||
308 | |||
309 | if (first) { |
||
310 | RandInit(h, w); |
||
311 | first = 0; |
||
312 | } |
||
313 | |||
314 | o1 = (unsigned short *)out; |
||
315 | o2 = (unsigned short *)(out+(2*w)); |
||
316 | o3 = (unsigned short *)(out+(4*w)); |
||
317 | o4 = (unsigned short *)(out+(6*w)); |
||
318 | l1 = lum; |
||
319 | l2 = lum+w; |
||
320 | |||
321 | for (i=0; i<h; i+=2) { |
||
322 | for(j=0; j<w; j+= 4) { |
||
323 | |||
324 | B = cb[0]; |
||
325 | b_val = bval_a[B]; |
||
326 | R = cr[0]; |
||
327 | r_val = rval_a[R]; |
||
328 | base = dith_a + b_val + r_val; |
||
329 | |||
330 | l_val = lval_a[l1[0]]; |
||
331 | dith_ca = (unsigned short *)(base + l_val); |
||
332 | o1[0] = dith_ca[0]; |
||
333 | o2[0] = dith_ca[1]; |
||
334 | |||
335 | l_val = lval_a[l1[1]]; |
||
336 | dith_ca = (unsigned short *)(base + l_val); |
||
337 | o1[1] = dith_ca[0]; |
||
338 | o2[1] = dith_ca[1]; |
||
339 | |||
340 | l_val = lval_a[l2[0]]; |
||
341 | dith_ca = (unsigned short *)(base + l_val); |
||
342 | o3[0] = dith_ca[0]; |
||
343 | o4[0] = dith_ca[1]; |
||
344 | |||
345 | l_val = lval_a[l2[1]]; |
||
346 | dith_ca = (unsigned short *)(base + l_val); |
||
347 | o3[1] = dith_ca[0]; |
||
348 | o4[1] = dith_ca[1]; |
||
349 | |||
350 | B = cb[1]; |
||
351 | b_val = bval_a[B]; |
||
352 | R = cr[1]; |
||
353 | r_val = rval_a[R]; |
||
354 | base = dith_a + b_val + r_val; |
||
355 | |||
356 | l_val = lval_a[l1[2]]; |
||
357 | dith_ca = (unsigned short *)(base + l_val); |
||
358 | o1[2] = dith_ca[0]; |
||
359 | o2[2] = dith_ca[1]; |
||
360 | |||
361 | l_val = lval_a[l1[3]]; |
||
362 | dith_ca = (unsigned short *)(base + l_val); |
||
363 | o1[3] = dith_ca[0]; |
||
364 | o2[3] = dith_ca[1]; |
||
365 | |||
366 | l_val = lval_a[l2[2]]; |
||
367 | dith_ca = (unsigned short *)(base + l_val); |
||
368 | o3[2] = dith_ca[0]; |
||
369 | o4[2] = dith_ca[1]; |
||
370 | |||
371 | l_val = lval_a[l2[3]]; |
||
372 | dith_ca = (unsigned short *)(base + l_val); |
||
373 | o3[3] = dith_ca[0]; |
||
374 | o4[3] = dith_ca[1]; |
||
375 | |||
376 | o1 += 4; |
||
377 | o2 += 4; |
||
378 | o3 += 4; |
||
379 | o4 += 4; |
||
380 | l1 += 4; |
||
381 | l2 += 4; |
||
382 | cb += 2; |
||
383 | cr += 2; |
||
384 | } |
||
385 | |||
386 | l1 += w; |
||
387 | l2 += w; |
||
388 | o1 += big_adv; |
||
389 | o2 += big_adv; |
||
390 | o3 += big_adv; |
||
391 | o4 += big_adv; |
||
392 | } |
||
393 | } |