Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2 | pj | 1 | /* |
2 | * ordered2.c -- |
||
3 | * |
||
4 | * This file contains C code to implement a faster ordered dither |
||
5 | * than the one found in ordered.c. This dither is the default |
||
6 | * if no dither is specified. |
||
7 | * |
||
8 | */ |
||
9 | |||
10 | /* |
||
11 | * Copyright (c) 1995 The Regents of the University of California. |
||
12 | * All rights reserved. |
||
13 | * |
||
14 | * Permission to use, copy, modify, and distribute this software and its |
||
15 | * documentation for any purpose, without fee, and without written agreement is |
||
16 | * hereby granted, provided that the above copyright notice and the following |
||
17 | * two paragraphs appear in all copies of this software. |
||
18 | * |
||
19 | * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR |
||
20 | * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT |
||
21 | * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF |
||
22 | * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
23 | * |
||
24 | * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, |
||
25 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY |
||
26 | * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
||
27 | * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO |
||
28 | * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
||
29 | */ |
||
30 | |||
31 | #include "video.h" |
||
32 | #include "proto.h" |
||
33 | #include "dither.h" |
||
34 | |||
35 | #define DITH_SIZE 16 |
||
36 | |||
37 | |||
38 | /* Structures used to implement hybrid ordered dither/floyd-steinberg |
||
39 | dither algorithm. |
||
40 | */ |
||
41 | |||
42 | static unsigned char ***ditherPtr[DITH_SIZE]; |
||
43 | |||
44 | |||
45 | /* |
||
46 | *-------------------------------------------------------------- |
||
47 | * |
||
48 | * InitOrderedDither-- |
||
49 | * |
||
50 | * Structures intialized for ordered dithering. |
||
51 | * |
||
52 | * Results: |
||
53 | * None. |
||
54 | * |
||
55 | * Side effects: |
||
56 | * None. |
||
57 | * |
||
58 | *-------------------------------------------------------------- |
||
59 | */ |
||
60 | |||
61 | void |
||
62 | InitOrdered2Dither() |
||
63 | { |
||
64 | unsigned char ****pos_2_cb; |
||
65 | unsigned char ***cb_2_cr; |
||
66 | unsigned char **cr_2_l; |
||
67 | int cb_val, cb_rval, cr_val, cr_rval, l_val, l_rval; |
||
68 | int i, j, pos; |
||
69 | int err_range, threshval; |
||
70 | |||
71 | pos_2_cb = (unsigned char ****) malloc (DITH_SIZE*sizeof(unsigned char ***)); |
||
72 | cb_2_cr = (unsigned char ***) malloc(CB_RANGE*sizeof(unsigned char **)); |
||
73 | cr_2_l = (unsigned char **) malloc(CR_RANGE*sizeof(unsigned char *)); |
||
74 | |||
75 | for (pos=0; pos<DITH_SIZE; pos++) { |
||
76 | |||
77 | pos_2_cb[pos] = (unsigned char ***) malloc(256*(sizeof(unsigned char **))); |
||
78 | |||
79 | for (j=0; j<CB_RANGE; j++) { |
||
80 | cb_2_cr[j] = (unsigned char **) malloc(256*(sizeof(unsigned char *))); |
||
81 | } |
||
82 | |||
83 | for (cb_val=0; cb_val<cb_values[0]; cb_val++) { |
||
84 | (pos_2_cb[pos])[cb_val] = cb_2_cr[0]; |
||
85 | } |
||
86 | |||
87 | for (cb_rval=0; cb_rval<(CB_RANGE-1); cb_rval++) { |
||
88 | err_range = cb_values[cb_rval+1] - cb_values[cb_rval]; |
||
89 | threshval = ((pos*err_range)/DITH_SIZE)+cb_values[cb_rval]; |
||
90 | |||
91 | for (cb_val=cb_values[cb_rval]; cb_val<cb_values[cb_rval+1]; cb_val++) { |
||
92 | if (cb_val>threshval) (pos_2_cb[pos])[cb_val] = cb_2_cr[cb_rval+1]; |
||
93 | else (pos_2_cb[pos])[cb_val] = cb_2_cr[cb_rval]; |
||
94 | } |
||
95 | } |
||
96 | |||
97 | for (cb_val=cb_values[CB_RANGE-1]; cb_val<256; cb_val++) { |
||
98 | (pos_2_cb[pos])[cb_val] = cb_2_cr[CB_RANGE-1]; |
||
99 | } |
||
100 | |||
101 | for (cb_rval=0; cb_rval<CB_RANGE; cb_rval++) { |
||
102 | |||
103 | for (j=0; j<CR_RANGE; j++) { |
||
104 | cr_2_l[j] = (unsigned char *) malloc(256*(sizeof(unsigned char))); |
||
105 | } |
||
106 | |||
107 | for (cr_val=0; cr_val < cr_values[0]; cr_val++) { |
||
108 | (cb_2_cr[cb_rval])[cr_val] = cr_2_l[0]; |
||
109 | } |
||
110 | |||
111 | for (cr_rval=0; cr_rval<(CR_RANGE-1); cr_rval++) { |
||
112 | err_range = cr_values[cr_rval+1] - cr_values[cr_rval]; |
||
113 | threshval = ((pos*err_range)/DITH_SIZE)+cr_values[cr_rval]; |
||
114 | |||
115 | for (cr_val=cr_values[cr_rval]; cr_val<cr_values[cr_rval+1]; cr_val++) { |
||
116 | if (cr_val>threshval) (cb_2_cr[cb_rval])[cr_val] = cr_2_l[cr_rval+1]; |
||
117 | else (cb_2_cr[cb_rval])[cr_val] = cr_2_l[cr_rval]; |
||
118 | } |
||
119 | } |
||
120 | |||
121 | for (cr_val=cr_values[CR_RANGE-1]; cr_val<256; cr_val++) { |
||
122 | (cb_2_cr[cb_rval])[cr_val] = cr_2_l[CR_RANGE-1]; |
||
123 | } |
||
124 | |||
125 | for (cr_rval=0; cr_rval<CR_RANGE; cr_rval++) { |
||
126 | |||
127 | for (l_val = 0; l_val < lum_values[0]; l_val++) { |
||
128 | (cr_2_l[cr_rval])[l_val] = pixel[cb_rval+(cr_rval*CB_RANGE)+ |
||
129 | (0*CR_RANGE*CB_RANGE)]; |
||
130 | } |
||
131 | |||
132 | for (l_rval=0; l_rval<(LUM_RANGE-1); l_rval++) { |
||
133 | err_range = lum_values[l_rval+1] - lum_values[l_rval]; |
||
134 | threshval = ((pos*err_range) /DITH_SIZE) + lum_values[l_rval]; |
||
135 | |||
136 | for (l_val = lum_values[l_rval]; l_val < lum_values[l_rval+1]; l_val++) { |
||
137 | if (l_val>threshval) (cr_2_l[cr_rval])[l_val] = |
||
138 | pixel[cb_rval+(cr_rval*CB_RANGE)+((l_rval+1)*CR_RANGE*CB_RANGE)]; |
||
139 | else (cr_2_l[cr_rval])[l_val] = |
||
140 | pixel[cb_rval+(cr_rval*CB_RANGE)+(l_rval*CR_RANGE*CB_RANGE)]; |
||
141 | } |
||
142 | } |
||
143 | |||
144 | for (l_val = lum_values[LUM_RANGE-1]; l_val < 256; l_val++) { |
||
145 | (cr_2_l[cr_rval])[l_val] = |
||
146 | pixel[cb_rval+(cr_rval*CB_RANGE)+((LUM_RANGE-1)*CR_RANGE*CB_RANGE)]; |
||
147 | } |
||
148 | } |
||
149 | } |
||
150 | } |
||
151 | |||
152 | for (i=0; i<DITH_SIZE; i++) { |
||
153 | ditherPtr[i] = pos_2_cb[i]; |
||
154 | } |
||
155 | } |
||
156 | |||
157 | |||
158 | /* |
||
159 | *-------------------------------------------------------------- |
||
160 | * |
||
161 | * Ordered2DitherImage -- |
||
162 | * |
||
163 | * Dithers an image using an ordered dither. |
||
164 | * Assumptions made: |
||
165 | * 1) The color space is allocated y:cr:cb = 8:4:4 |
||
166 | * 2) The spatial resolution of y:cr:cb is 4:1:1 |
||
167 | * The channels are dithered based on the standard |
||
168 | * ordered dither pattern for a 4x4 area. |
||
169 | * |
||
170 | * Results: |
||
171 | * None. |
||
172 | * |
||
173 | * Side effects: |
||
174 | * None. |
||
175 | * |
||
176 | *-------------------------------------------------------------- |
||
177 | */ |
||
178 | void |
||
179 | Ordered2DitherImage (lum, cr, cb, out, h, w) |
||
180 | unsigned char *lum; |
||
181 | unsigned char *cr; |
||
182 | unsigned char *cb; |
||
183 | unsigned char *out; |
||
184 | int w, h; |
||
185 | { |
||
186 | unsigned char *l, *r, *b, *o1, *o2; |
||
187 | unsigned char *l2; |
||
188 | unsigned char L, R, B; |
||
189 | int i, j; |
||
190 | unsigned char ***dp0 = ditherPtr[0]; |
||
191 | unsigned char ***dp2 = ditherPtr[2]; |
||
192 | unsigned char ***dp4 = ditherPtr[4]; |
||
193 | unsigned char ***dp6 = ditherPtr[6]; |
||
194 | unsigned char ***dp8 = ditherPtr[8]; |
||
195 | unsigned char ***dp10 = ditherPtr[10]; |
||
196 | unsigned char ***dp12 = ditherPtr[12]; |
||
197 | unsigned char ***dp14 = ditherPtr[14]; |
||
198 | unsigned char ***dp1 = ditherPtr[1]; |
||
199 | unsigned char ***dp3 = ditherPtr[3]; |
||
200 | unsigned char ***dp5 = ditherPtr[5]; |
||
201 | unsigned char ***dp7 = ditherPtr[7]; |
||
202 | unsigned char ***dp9 = ditherPtr[9]; |
||
203 | unsigned char ***dp11 = ditherPtr[11]; |
||
204 | unsigned char ***dp13 = ditherPtr[13]; |
||
205 | unsigned char ***dp15 = ditherPtr[15]; |
||
206 | |||
207 | l = lum; |
||
208 | l2 = lum+w; |
||
209 | r = cr; |
||
210 | b = cb; |
||
211 | o1 = out; |
||
212 | o2 = out+w; |
||
213 | |||
214 | for (i=0; i<h; i+=4) { |
||
215 | |||
216 | for (j=0; j<w; j+=8) { |
||
217 | |||
218 | R = r[0]; B = b[0]; |
||
219 | |||
220 | L = l[0]; |
||
221 | o1[0] = ((dp0[B])[R])[L]; |
||
222 | L = l[1]; |
||
223 | o1[1] = ((dp8[B])[R])[L]; |
||
224 | L = l2[0]; |
||
225 | o2[0] = ((dp12[B])[R])[L]; |
||
226 | L = l2[1]; |
||
227 | o2[1] = ((dp4[B])[R])[L]; |
||
228 | |||
229 | R = r[1]; B = b[1]; |
||
230 | |||
231 | L = l[2]; |
||
232 | o1[2] = ((dp2[B])[R])[L]; |
||
233 | L = l[3]; |
||
234 | o1[3] = ((dp10[B])[R])[L]; |
||
235 | L = l2[2]; |
||
236 | o2[2] = ((dp14[B])[R])[L]; |
||
237 | L = l2[3]; |
||
238 | o2[3] = ((dp6[B])[R])[L]; |
||
239 | |||
240 | R = r[2]; B = b[2]; |
||
241 | |||
242 | L = l[4]; |
||
243 | o1[4] = ((dp0[B])[R])[L]; |
||
244 | L = l[5]; |
||
245 | o1[5] = ((dp8[B])[R])[L]; |
||
246 | L = l2[4]; |
||
247 | o2[4] = ((dp12[B])[R])[L]; |
||
248 | L = l2[5]; |
||
249 | o2[5] = ((dp4[B])[R])[L]; |
||
250 | |||
251 | R = r[3]; B = b[3]; |
||
252 | |||
253 | L = l[6]; |
||
254 | o1[6] = ((dp2[B])[R])[L]; |
||
255 | L = l[7]; |
||
256 | o1[7] = ((dp10[B])[R])[L]; |
||
257 | L = l2[6]; |
||
258 | o2[6] = ((dp14[B])[R])[L]; |
||
259 | L = l2[7]; |
||
260 | o2[7] = ((dp6[B])[R])[L]; |
||
261 | |||
262 | l += 8; |
||
263 | l2 += 8; |
||
264 | r += 4; |
||
265 | b += 4; |
||
266 | o1 += 8; |
||
267 | o2 += 8; |
||
268 | } |
||
269 | |||
270 | l += w; |
||
271 | l2 += w; |
||
272 | o1 += w; |
||
273 | o2 += w; |
||
274 | |||
275 | for (j=0; j<w; j+=8) { |
||
276 | |||
277 | R = r[0]; B = b[0]; |
||
278 | |||
279 | L = l[0]; |
||
280 | o1[0] = ((dp3[B])[R])[L]; |
||
281 | L = l[1]; |
||
282 | o1[1] = ((dp11[B])[R])[L]; |
||
283 | L = l2[0]; |
||
284 | o2[0] = ((dp15[B])[R])[L]; |
||
285 | L = l2[1]; |
||
286 | o2[1] = ((dp7[B])[R])[L]; |
||
287 | |||
288 | R = r[1]; B = b[1]; |
||
289 | |||
290 | L = l[2]; |
||
291 | o1[2] = ((dp1[B])[R])[L]; |
||
292 | L = l[3]; |
||
293 | o1[3] = ((dp9[B])[R])[L]; |
||
294 | L = l2[2]; |
||
295 | o2[2] = ((dp13[B])[R])[L]; |
||
296 | L = l2[3]; |
||
297 | o2[3] = ((dp5[B])[R])[L]; |
||
298 | |||
299 | R = r[2]; B = b[2]; |
||
300 | |||
301 | L = l[4]; |
||
302 | o1[4] = ((dp3[B])[R])[L]; |
||
303 | L = l[5]; |
||
304 | o1[5] = ((dp11[B])[R])[L]; |
||
305 | L = l2[4]; |
||
306 | o2[4] = ((dp15[B])[R])[L]; |
||
307 | L = l2[5]; |
||
308 | o2[5] = ((dp7[B])[R])[L]; |
||
309 | |||
310 | R = r[3]; B = b[3]; |
||
311 | |||
312 | L = l[6]; |
||
313 | o1[6] = ((dp1[B])[R])[L]; |
||
314 | L = l[7]; |
||
315 | o1[7] = ((dp9[B])[R])[L]; |
||
316 | L = l2[6]; |
||
317 | o2[6] = ((dp13[B])[R])[L]; |
||
318 | L = l2[7]; |
||
319 | o2[7] = ((dp5[B])[R])[L]; |
||
320 | |||
321 | l += 8; |
||
322 | l2 += 8; |
||
323 | r += 4; |
||
324 | b += 4; |
||
325 | o1 += 8; |
||
326 | o2 += 8; |
||
327 | } |
||
328 | |||
329 | l += w; |
||
330 | l2 += w; |
||
331 | o1 += w; |
||
332 | o2 += w; |
||
333 | } |
||
334 | } |
||
335 | |||
336 | |||
337 |