/[projet1]/public/pc/tools/osdk/main/pictconv/sources/dither_riemersma.cpp
Defence Force logotype

Contents of /public/pc/tools/osdk/main/pictconv/sources/dither_riemersma.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 880 - (show annotations)
Tue Sep 25 23:40:17 2012 UTC (7 years, 1 month ago) by mmu_man
File size: 6606 byte(s)
Fix includes

* Remove unneeded includes or use standard ones in place of windows ones
* Fix case of FreeImage.h includes

1 /* Riemersma dither
2 *
3 * This program reads in an uncompressed gray-scale image with one byte per
4 * pixel and a size of 256*256 pixels (no image header). It dithers the image
5 * and writes an output image in the same format.
6 *
7 * This program was tested with Borland C++ 3.1 16-bit (DOS), compiled in
8 * large memory model. For other compilers, you may have to replace the
9 * calls to malloc() and _ffree() with straight malloc() and free() calls.
10 */
11 #include <malloc.h> // for malloc() and _ffree()
12 #include <math.h> // for exp() and log()
13 #include <string.h> // memmove()
14
15 #include "getpixel.h"
16 #include "image.h"
17
18
19 #define max(a,b) (((a)>(b))?(a):(b))
20
21 #define WIDTH 240 //256
22 #define HEIGHT 200 //256
23
24 #define BLOCKSIZE 16384 // read in chunks of 16 kBytes
25
26 enum
27 {
28 NONE,
29 UP,
30 LEFT,
31 DOWN,
32 RIGHT,
33 };
34
35
36
37 // variables needed for the Riemersma dither algorithm
38 static int cur_x=0, cur_y=0;
39 static int img_width=0, img_height=0;
40 static unsigned char *img_ptr;
41
42 #define SIZE 16 // queue size: number of pixels remembered
43 #define MAX 16 // relative weight of youngest pixel in the queue, versus the oldest pixel
44
45 static int weights[SIZE]; // weights for the errors of recent pixels
46
47 static void init_weights(int a[],int size,int max)
48 {
49 double m = exp(log((double)max)/(size-1));
50 double v;
51 int i;
52
53 for (i=0, v=1.0; i<size; i++)
54 {
55 a[i]=(int)(v+0.5); // store rounded value
56 v*=m; // next value
57 }
58 }
59
60
61
62 static void dither_pixel(unsigned char *pixel)
63 {
64 static int error[SIZE]; // queue with error values of recent pixels
65 int i,pvalue,err;
66
67 for (i=0,err=0L; i<SIZE; i++)
68 err+=error[i]*weights[i];
69 pvalue=*pixel + err/MAX;
70 pvalue = (pvalue>=128) ? 255 : 0;
71 memmove(error,error+1,(SIZE-1)*sizeof error[0]); // shift queue
72 error[SIZE-1] = *pixel - pvalue;
73 *pixel=(unsigned char)pvalue;
74 }
75
76
77
78 static void move(int direction)
79 {
80 // dither the current pixel
81 if (cur_x>=0 && cur_x<img_width && cur_y>=0 && cur_y<img_height)
82 {
83 dither_pixel(img_ptr);
84 }
85
86 // move to the next pixel
87 switch (direction)
88 {
89 case LEFT:
90 cur_x--;
91 img_ptr--;
92 break;
93 case RIGHT:
94 cur_x++;
95 img_ptr++;
96 break;
97 case UP:
98 cur_y--;
99 img_ptr-=img_width;
100 break;
101 case DOWN:
102 cur_y++;
103 img_ptr+=img_width;
104 break;
105 }
106 }
107
108
109
110 void hilbert_level(int level,int direction)
111 {
112 if (level==1)
113 {
114 switch (direction)
115 {
116 case LEFT:
117 move(RIGHT);
118 move(DOWN);
119 move(LEFT);
120 break;
121 case RIGHT:
122 move(LEFT);
123 move(UP);
124 move(RIGHT);
125 break;
126 case UP:
127 move(DOWN);
128 move(RIGHT);
129 move(UP);
130 break;
131 case DOWN:
132 move(UP);
133 move(LEFT);
134 move(DOWN);
135 break;
136 }
137 }
138 else
139 {
140 switch (direction)
141 {
142 case LEFT:
143 hilbert_level(level-1,UP);
144 move(RIGHT);
145 hilbert_level(level-1,LEFT);
146 move(DOWN);
147 hilbert_level(level-1,LEFT);
148 move(LEFT);
149 hilbert_level(level-1,DOWN);
150 break;
151 case RIGHT:
152 hilbert_level(level-1,DOWN);
153 move(LEFT);
154 hilbert_level(level-1,RIGHT);
155 move(UP);
156 hilbert_level(level-1,RIGHT);
157 move(RIGHT);
158 hilbert_level(level-1,UP);
159 break;
160 case UP:
161 hilbert_level(level-1,LEFT);
162 move(DOWN);
163 hilbert_level(level-1,UP);
164 move(RIGHT);
165 hilbert_level(level-1,UP);
166 move(UP);
167 hilbert_level(level-1,RIGHT);
168 break;
169 case DOWN:
170 hilbert_level(level-1,RIGHT);
171 move(UP);
172 hilbert_level(level-1,DOWN);
173 move(LEFT);
174 hilbert_level(level-1,DOWN);
175 move(DOWN);
176 hilbert_level(level-1,LEFT);
177 break;
178 }
179 }
180 }
181
182
183 int log2(int value)
184 {
185 int result=0;
186 while (value>1)
187 {
188 value >>= 1;
189 result++;
190 }
191 return result;
192 }
193
194
195 void dither_riemersma_2(unsigned char *image,int width,int height)
196 {
197 int level,size;
198
199 /* determine the required order of the Hilbert curve */
200 size=max(width,height);
201 level=log2(size);
202 if ((1L << level) < size)
203 level++;
204
205 init_weights(weights,SIZE,MAX);
206 img_ptr=image;
207 img_width=width;
208 img_height=height;
209 cur_x=0;
210 cur_y=0;
211 if (level>0)
212 {
213 hilbert_level(level,UP);
214 }
215
216 move(NONE);
217 }
218
219
220
221
222 void dither_riemersma_monochrom(ImageContainer& sourceImage,int width,int height)
223 {
224 unsigned char *image=(unsigned char*)malloc(width*height);
225
226 //
227 // Create a mono buffer
228 //
229 unsigned char *ptr_image=image;
230 for (int y=0;y<height;y++)
231 {
232 for (int x=0;x<width;x++)
233 {
234 RgbColor rgb=sourceImage.ReadColor(x,y);
235 *ptr_image++=(rgb.m_red+rgb.m_green+rgb.m_blue)/3;
236 /*
237 if (((rgb.m_red+rgb.m_green+rgb.m_blue)/3)>127)
238 {
239 *ptr_image++=255;
240 }
241 else
242 {
243 *ptr_image++=0;
244 }
245 */
246 }
247 }
248
249 //
250 // Perform dithering
251 //
252 dither_riemersma_2(image,width,height);
253
254 //
255 // Convert again
256 //
257 ptr_image=image;
258 for (int y=0;y<height;y++)
259 {
260 for (int x=0;x<width;x++)
261 {
262 RgbColor rgb;
263 if ((*ptr_image)>127)
264 {
265 rgb.m_red =255;
266 rgb.m_green =255;
267 rgb.m_blue =255;
268 }
269 else
270 {
271 rgb.m_red =0;
272 rgb.m_green =0;
273 rgb.m_blue =0;
274 }
275 ptr_image++;
276 sourceImage.WriteColor(rgb,x,y);
277 }
278 }
279
280 free(image);
281 }
282
283
284
285
286 void dither_riemersma_rgb(ImageContainer& sourceImage,int width,int height)
287 {
288 RgbColor rgb1;
289 RgbColor rgb2;
290 RgbColor rgb3;
291
292 unsigned char *image=(unsigned char*)malloc(width*height);
293
294 unsigned char* prgb1=&rgb1.m_red;
295 unsigned char* prgb2=&rgb2.m_red;
296 unsigned char* prgb3=&rgb3.m_red;
297 for (int pass=0;pass<3;pass++)
298 {
299 //
300 // Create a mono buffer
301 //
302 unsigned char *ptr_image=image;
303 for (int y=pass;y<height;y+=3)
304 {
305 for (int x=0;x<width;x++)
306 {
307 rgb1=sourceImage.ReadColor(x,y+0);
308 rgb2=sourceImage.ReadColor(x,y+1);
309 rgb3=sourceImage.ReadColor(x,y+2);
310 *ptr_image++=(prgb1[pass]+prgb2[pass]+prgb3[pass])/3;
311 }
312 }
313
314 //
315 // Perform dithering
316 //
317 dither_riemersma_2(image,width,(height/3));
318
319 //
320 // Convert again
321 //
322 ptr_image=image;
323 for (int y=pass;y<height;y+=3)
324 {
325 for (int x=0;x<width;x++)
326 {
327 rgb1=sourceImage.ReadColor(x,y+0);
328 rgb2=sourceImage.ReadColor(x,y+1);
329 rgb3=sourceImage.ReadColor(x,y+2);
330
331 if ((*ptr_image)>127)
332 {
333 prgb1[pass]=255;
334 prgb2[pass]=255;
335 prgb3[pass]=255;
336 }
337 else
338 {
339 prgb1[pass]=0;
340 prgb2[pass]=0;
341 prgb3[pass]=0;
342 }
343 ptr_image++;
344 sourceImage.WriteColor(rgb1,x,y+0);
345 sourceImage.WriteColor(rgb2,x,y+1);
346 sourceImage.WriteColor(rgb3,x,y+2);
347 }
348 }
349 }
350
351 free(image);
352 }
353
354
355

  ViewVC Help
Powered by ViewVC 1.1.26