source: trunk/JPGPROC/source/gbmsrc/gbmerr.c@ 2

Last change on this file since 2 was 2, checked in by stevenhl, 8 years ago

Import sources from cwmm-full.zip dated 2005-03-21

File size: 33.4 KB
Line 
1/*
2
3gbmerr.c - Error diffusion Module
4
5*/
6
7/*...sincludes:0:*/
8#include <stdio.h>
9#include <stddef.h>
10#include <stdlib.h>
11#include <string.h>
12#include "gbm.h"
13
14/*...vgbm\46\h:0:*/
15/*...e*/
16/*...svars:0:*/
17static BOOLEAN inited = FALSE;
18
19/*
20Tables used for quick saturated addition and subtraction.
21*/
22
23static byte usat[256+256+256];
24#define U_SAT_ADD(a,b) usat[(a)+(b)+256]
25
26static short ssat[256+256+256+256];
27#define S_SAT_ADD(a,b) ssat[(a)+(b)+512]
28
29/*
30For 6Rx6Gx6B, 7Rx8Gx4B palettes etc.
31*/
32
33static byte index4[0x100];
34static byte index6[0x100];
35static byte index7[0x100];
36static byte index8[0x100];
37static byte index16[0x100];
38static byte scale4[] = { 0, 85, 170, 255 };
39static byte scale6[] = { 0, 51, 102, 153, 204, 255 };
40static byte scale7[] = { 0, 43, 85, 128, 170, 213, 255 };
41static byte scale8[] = { 0, 36, 73, 109, 146, 182, 219, 255 };
42static byte scale16[] = { 0, 17, 34, 51, 68, 85, 102, 119, 136,
43 153, 170, 187, 204, 221, 238, 255 };
44
45static word randtab[0x100];
46static int randinx = 0;
47/*...e*/
48/*...sinit:0:*/
49/*
50This function initialises this module.
51It does this by preparing the quick saturated addition and subraction tables.
52*/
53
54/*...snearest_inx:0:*/
55#ifndef abs
56#define abs(x) (((x)>=0)?(x):-(x))
57#endif
58
59static byte nearest_inx(byte value, const byte ab[], unsigned short cb)
60 {
61 byte b, inx, inx_min;
62 short diff, diff_min;
63
64 b = ab[0];
65 diff_min = abs((short) value - (short) b);
66 inx_min = 0;
67 for ( inx = 1; (unsigned short) inx < cb; inx++ )
68 {
69 b = ab[inx];
70 diff = abs((short) value - (short) b);
71 if ( diff < diff_min )
72 {
73 diff_min = diff;
74 inx_min = inx;
75 }
76 }
77 return inx_min;
78 }
79/*...e*/
80
81static void init(void)
82 {
83 int i;
84
85 if ( inited )
86 return;
87
88 memset(usat, 0, 0x100);
89 for ( i = 0; i < 0x100; i++ )
90 usat[i + 0x100] = (byte) i;
91 memset(usat + 0x200, 0xff, 0x100);
92
93 for ( i = -0x200; i < -0x100; i++ )
94 ssat[i + 0x200] = -0x100;
95 for ( i = -0x100; i < 0x100; i++ )
96 ssat[i + 0x200] = i;
97 for ( i = 0x100; i < 0x200; i++ )
98 ssat[i + 0x200] = 0xff;
99
100 /* For 7 Red x 8 Green x 4 Blue palettes etc. */
101
102 for ( i = 0; i < 0x100; i++ )
103 {
104 index4 [i] = nearest_inx((byte) i, scale4 , sizeof(scale4 ));
105 index6 [i] = nearest_inx((byte) i, scale6 , sizeof(scale6 ));
106 index7 [i] = nearest_inx((byte) i, scale7 , sizeof(scale7 ));
107 index8 [i] = nearest_inx((byte) i, scale8 , sizeof(scale8 ));
108 index16[i] = nearest_inx((byte) i, scale16, sizeof(scale16));
109 }
110
111 /* For faster random number calculation */
112
113 for ( i = 0; i < 0x100; i++ )
114 randtab [i] = (word) (rand() % (51*0x100));
115
116 inited = TRUE;
117 }
118/*...e*/
119/*...serrdiff:0:*/
120static BOOLEAN errdiff(
121 const GBM *gbm, const byte *src, byte *dest,
122 int dest_bpp,
123 void (*errdiff_line)(byte *src, byte *dest, short *errs, int cx)
124 )
125 {
126 int stride_src = ((gbm->w * 3 + 3) & ~3);
127 int stride_dest = ((gbm->w * dest_bpp + 31) / 32) * 4;
128 byte *buf;
129 short *errs;
130 int y;
131
132 if ( (buf = malloc((size_t) stride_src + 3)) == NULL )
133 return FALSE;
134
135 if ( (errs = malloc((size_t) ((gbm->w + 1) * 3 * sizeof(short)))) == NULL )
136 {
137 free(buf);
138 return FALSE;
139 }
140
141 memset(errs, 0, (gbm->w + 1) * 3 * sizeof(short));
142
143 for ( y = 0; y < gbm->h; y++ )
144 {
145 memcpy(buf, src + y * stride_src, stride_src);
146 (*errdiff_line)(buf, dest + y * stride_dest, errs, gbm->w);
147 }
148
149 free(buf);
150 free(errs);
151
152 return TRUE;
153 }
154/*...e*/
155
156/*...sgbm_errdiff_line_24 \45\ error diffuse to fewer bits per pixel one line:0:*/
157/*
158This function takes a line of RGB data, a destination buffer and a buffer of
159error terms and performs one lines worth (a given # of pixels) of error
160diffusion.
161*/
162
163void gbm_errdiff_line_24(byte *src, byte *dest, short *errs, int cx, byte rm, byte gm, byte bm)
164 {
165 int x, ptr = 0;
166
167 init();
168
169 /* Step 1: Add error terms to newly supplied line */
170
171 for ( x = 0; x < cx * 3; x++ )
172 src[x] = U_SAT_ADD((int) src[x], (int) errs[x]);
173
174 /* Step 2: Zero out error terms */
175
176 memset(errs, 0, cx * 3 * sizeof(errs[0]));
177
178 /* Step 3: Go along data, finding nearest colour and propagating error */
179
180 randinx = rand();
181
182 for ( x = 0; x < cx; x++ )
183 {
184 byte b = *src++;
185 byte g = *src++;
186 byte r = *src++;
187 byte bi = (b & bm);
188 byte gi = (g & gm);
189 byte ri = (r & rm);
190 int be = b - (int) bi;
191 int ge = g - (int) gi;
192 int re = r - (int) ri;
193 word rn = randtab[(byte) (randinx++)];
194 int right = (rn >> 8);
195 int down = ((rn & 0xff) % (63 - right));
196 int be1 = ((be * right) >> 6);
197 int ge1 = ((ge * right) >> 6);
198 int re1 = ((re * right) >> 6);
199 int be2 = ((be * down ) >> 6);
200 int ge2 = ((ge * down ) >> 6);
201 int re2 = ((re * down ) >> 6);
202 int be3 = be - be1 - be2;
203 int ge3 = ge - ge1 - ge2;
204 int re3 = re - re1 - re2;
205
206 *dest++ = bi;
207 *dest++ = gi;
208 *dest++ = ri;
209
210 src[0] = U_SAT_ADD((int) src[0], be1);
211 src[1] = U_SAT_ADD((int) src[1], ge1);
212 src[2] = U_SAT_ADD((int) src[2], re1);
213
214 errs[ptr ] = S_SAT_ADD((int) errs[ptr ], be2);
215 errs[ptr + 1] = S_SAT_ADD((int) errs[ptr + 1], ge2);
216 errs[ptr + 2] = S_SAT_ADD((int) errs[ptr + 2], re2);
217
218 ptr += 3;
219
220 errs[ptr ] = S_SAT_ADD((int) errs[ptr ], be3);
221 errs[ptr + 1] = S_SAT_ADD((int) errs[ptr + 1], ge3);
222 errs[ptr + 2] = S_SAT_ADD((int) errs[ptr + 2], re3);
223 }
224 }
225/*...e*/
226/*...sgbm_errdiff_24 \45\ error diffuse to fewer bits per pixel:0:*/
227BOOLEAN gbm_errdiff_24(const GBM *gbm, const byte *data24, byte *data24a, byte rm, byte gm, byte bm)
228 {
229 int stride = ((gbm->w * 3 + 3) & ~3);
230 byte *buf;
231 short *errs;
232 int y;
233
234 if ( (buf = malloc((size_t) (stride + 3))) == NULL )
235 return FALSE;
236
237 if ( (errs = malloc((size_t) ((gbm->w + 1) * 3 * sizeof(short)))) == NULL )
238 {
239 free(buf);
240 return FALSE;
241 }
242
243 memset(errs, 0, (gbm->w + 1) * 3 * sizeof(short));
244
245 for ( y = 0; y < gbm->h; y++ )
246 {
247 memcpy(buf, data24 + y * stride, stride);
248 gbm_errdiff_line_24(buf, data24a + y * stride, errs, gbm->w, rm, gm, bm);
249 }
250
251 free(buf);
252 free(errs);
253
254 return TRUE;
255 }
256/*...e*/
257
258/*...sgbm_errdiff_pal_6R6G6B \45\ return 6Rx6Gx6B palette:0:*/
259/*
260This function makes the palette for the 6 red x 6 green x 6 blue palette.
261216 palette entrys used. Remaining 40 left blank.
262*/
263
264void gbm_errdiff_pal_6R6G6B(GBMRGB *gbmrgb)
265 {
266 byte volatile r; /* C-Set/2 optimiser fix */
267 byte volatile g;
268 byte volatile b;
269
270 init();
271 memset(gbmrgb, 0x80, 0x100 * sizeof(GBMRGB));
272 for ( r = 0; r < 6; r++ )
273 for ( g = 0; g < 6; g++ )
274 for ( b = 0; b < 6; b++ )
275 {
276 gbmrgb->r = scale6[r];
277 gbmrgb->g = scale6[g];
278 gbmrgb->b = scale6[b];
279 gbmrgb++;
280 }
281 }
282/*...e*/
283/*...sgbm_errdiff_line_6R6G6B \45\ error diffuse to 6Rx6Gx6B one line:0:*/
284/*
285This function takes a line of RGB data, a destination buffer and a buffer of
286error terms and performs one lines worth (a given # of pixels) of error
287diffusion.
288*/
289
290void gbm_errdiff_line_6R6G6B(byte *src, byte *dest, short *errs, int cx)
291 {
292 int x, ptr = 0;
293
294 init();
295
296 /* Step 1: Add error terms to newly supplied line */
297
298 for ( x = 0; x < cx * 3; x++ )
299 src[x] = U_SAT_ADD((int) src[x], (int) errs[x]);
300
301 /* Step 2: Zero out error terms */
302
303 memset(errs, 0, (cx + 1) * 3 * sizeof(errs[0]));
304
305 /* Step 3: Go along data, finding nearest colour and propagating error */
306
307 randinx = rand();
308
309 for ( x = 0; x < cx; x++ )
310 {
311 byte b = *src++;
312 byte g = *src++;
313 byte r = *src++;
314 byte bi = index6[b];
315 byte gi = index6[g];
316 byte ri = index6[r];
317 int be = b - ((int) scale6[bi]);
318 int ge = g - ((int) scale6[gi]);
319 int re = r - ((int) scale6[ri]);
320 word rn = randtab[(byte) (randinx++)];
321 int right = (int) (rn >> 8);
322 int down = (int) ((rn & 0xff) % (63 - right));
323 int be1 = ((be * right) >> 6);
324 int ge1 = ((ge * right) >> 6);
325 int re1 = ((re * right) >> 6);
326 int be2 = ((be * down ) >> 6);
327 int ge2 = ((ge * down ) >> 6);
328 int re2 = ((re * down ) >> 6);
329 int be3 = be - be1 - be2;
330 int ge3 = ge - ge1 - ge2;
331 int re3 = re - re1 - re2;
332
333 *dest++ = (byte) (6 * (6 * ri + gi) + bi);
334
335 src[0] = U_SAT_ADD((int) src[0], be1);
336 src[1] = U_SAT_ADD((int) src[1], ge1);
337 src[2] = U_SAT_ADD((int) src[2], re1);
338
339 errs[ptr ] = S_SAT_ADD((int) errs[ptr ], be2);
340 errs[ptr + 1] = S_SAT_ADD((int) errs[ptr + 1], ge2);
341 errs[ptr + 2] = S_SAT_ADD((int) errs[ptr + 2], re2);
342
343 ptr += 3;
344
345 errs[ptr ] = S_SAT_ADD((int) errs[ptr ], be3);
346 errs[ptr + 1] = S_SAT_ADD((int) errs[ptr + 1], ge3);
347 errs[ptr + 2] = S_SAT_ADD((int) errs[ptr + 2], re3);
348 }
349 }
350/*...e*/
351/*...sgbm_errdiff_6R6G6B \45\ error diffuse to 6Rx6Gx6B:0:*/
352BOOLEAN gbm_errdiff_6R6G6B(const GBM *gbm, const byte *data24, byte *data8)
353 {
354 return errdiff(gbm, data24, data8, 8, gbm_errdiff_line_6R6G6B);
355 }
356/*...e*/
357
358/*...sgbm_errdiff_pal_7R8G4B \45\ return 7Rx8Gx4B palette:0:*/
359/*
360This function makes the palette for the 7 red x 8 green x 4 blue palette.
361224 palette entrys used. Remaining 32 left blank.
362Colours calculated to match those used by 8514/A PM driver.
363*/
364
365void gbm_errdiff_pal_7R8G4B(GBMRGB *gbmrgb)
366 {
367 byte volatile r; /* C-Set/2 optimiser fix */
368 byte volatile g;
369 byte volatile b;
370
371 init();
372
373 memset(gbmrgb, 0x80, 0x100 * sizeof(GBMRGB));
374 for ( r = 0; r < 7; r++ )
375 for ( g = 0; g < 8; g++ )
376 for ( b = 0; b < 4; b++ )
377 {
378 gbmrgb->r = scale7[r];
379 gbmrgb->g = scale8[g];
380 gbmrgb->b = scale4[b];
381 gbmrgb++;
382 }
383 }
384/*...e*/
385/*...sgbm_errdiff_line_7R8G4B \45\ error diffuse to 7Rx8Gx4B one line:0:*/
386/*
387This function takes a line of RGB data, a destination buffer and a buffer of
388error terms and performs one lines worth (a given # of pixels) of error
389diffusion.
390*/
391
392void gbm_errdiff_line_7R8G4B(byte *src, byte *dest, short *errs, int cx)
393 {
394 int x, ptr = 0;
395
396 init();
397
398 /* Step 1: Add error terms to newly supplied line */
399
400 for ( x = 0; x < cx * 3; x++ )
401 src[x] = U_SAT_ADD((int) src[x], (int) errs[x]);
402
403 /* Step 2: Zero out error terms */
404
405 memset(errs, 0, (cx + 1) * 3 * sizeof(errs[0]));
406
407 /* Step 3: Go along data, finding nearest colour and propagating error */
408
409 randinx = rand();
410
411 for ( x = 0; x < cx; x++ )
412 {
413 byte b = *src++;
414 byte g = *src++;
415 byte r = *src++;
416 byte bi = index4[b];
417 byte gi = index8[g];
418 byte ri = index7[r];
419 int be = b - ((int) scale4[bi]);
420 int ge = g - ((int) scale8[gi]);
421 int re = r - ((int) scale7[ri]);
422 word rn = randtab[(byte) (randinx++)];
423 int right = (rn >> 8);
424 int down = ((rn & 0xff) % (63 - right));
425 int be1 = ((be * right) >> 6);
426 int ge1 = ((ge * right) >> 6);
427 int re1 = ((re * right) >> 6);
428 int be2 = ((be * down ) >> 6);
429 int ge2 = ((ge * down ) >> 6);
430 int re2 = ((re * down ) >> 6);
431 int be3 = be - be1 - be2;
432 int ge3 = ge - ge1 - ge2;
433 int re3 = re - re1 - re2;
434
435 *dest++ = (byte) (4 * (8 * ri + gi) + bi);
436
437 src[0] = U_SAT_ADD((int) src[0], be1);
438 src[1] = U_SAT_ADD((int) src[1], ge1);
439 src[2] = U_SAT_ADD((int) src[2], re1);
440
441 errs[ptr ] = S_SAT_ADD((int) errs[ptr ], be2);
442 errs[ptr + 1] = S_SAT_ADD((int) errs[ptr + 1], ge2);
443 errs[ptr + 2] = S_SAT_ADD((int) errs[ptr + 2], re2);
444
445 ptr += 3;
446
447 errs[ptr ] = S_SAT_ADD((int) errs[ptr ], be3);
448 errs[ptr + 1] = S_SAT_ADD((int) errs[ptr + 1], ge3);
449 errs[ptr + 2] = S_SAT_ADD((int) errs[ptr + 2], re3);
450 }
451 }
452/*...e*/
453/*...sgbm_errdiff_7R8G4B \45\ error diffuse to 7Rx8Gx4B:0:*/
454BOOLEAN gbm_errdiff_7R8G4B(const GBM *gbm, const byte *data24, byte *data8)
455 {
456 return errdiff(gbm, data24, data8, 8, gbm_errdiff_line_7R8G4B);
457 }
458/*...e*/
459
460/*...sgbm_errdiff_pal_VGA \45\ return default VGA palette:0:*/
461/*
462This function makes the palette for the 16 colour VGA palette.
463*/
464
465static GBMRGB gbmrgb_vga[] =
466 {
467 0, 0, 0,
468 128, 0, 0,
469 0,128, 0,
470 128,128, 0,
471 0, 0,128,
472 128, 0,128,
473 0,128,128,
474 128,128,128,
475 204,204,204,
476 255, 0, 0,
477 0,255, 0,
478 255,255, 0,
479 0, 0,255,
480 255, 0,255,
481 0,255,255,
482 255,255,255,
483 };
484
485void gbm_errdiff_pal_VGA(GBMRGB *gbmrgb)
486 {
487 init();
488 memcpy((char *) gbmrgb, (char *) gbmrgb_vga, sizeof(gbmrgb_vga));
489 }
490/*...e*/
491/*...sgbm_errdiff_line_VGA \45\ error diffuse to default VGA palette one line:0:*/
492/*
493This function takes a line of RGB data, a destination buffer and a buffer of
494error terms and performs one lines worth (a given # of pixels) of error
495diffusion.
496*/
497
498/*...scalc_nearest:0:*/
499/*
500This function, when given am RGB colour, finds the VGA palette entry closest
501to it. We deliberately bias away from the two grey palette entries.
502*/
503
504static byte calc_nearest(byte r, byte g, byte b)
505 {
506 long min_dist = 3L * 256L * 256L * 10L;
507 byte bi, bi_min;
508
509 for ( bi = 0; bi < 0x10; bi++ )
510 {
511 long b_dist = ((long) b - (long) gbmrgb_vga[bi].b);
512 long g_dist = ((long) g - (long) gbmrgb_vga[bi].g);
513 long r_dist = ((long) r - (long) gbmrgb_vga[bi].r);
514 long dist = r_dist * r_dist + g_dist * g_dist + b_dist * b_dist;
515
516 if ( bi == 7 || bi == 8 )
517 /* Bias away from this colour */
518 dist <<= 3;
519
520 if ( dist < min_dist )
521 {
522 min_dist = dist;
523 bi_min = bi;
524 }
525 }
526 return bi_min;
527 }
528/*...e*/
529/*...snearest_colour:0:*/
530/*
531This function finds the closest VGA palette colour to a given RGB value.
532It uses a lookup table to avoid performing distance calculations to the
53316 palette entrys. The table is pre-calculated.
534*/
535
536/*...squick lookup table:0:*/
537/*...v_gbmerr\46\c \45\ used to make quick_tab:0:*/
538
539static byte quick_tab[16][16][16] =
540 {
541 0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
542 0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
543 0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
544 0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
545 255,255,255,255,255,255,255,255,255,255,255,255,255,12,12,12,
546 2,2,2,2,255,6,6,6,6,6,6,6,6,255,12,12,
547 2,2,2,2,255,6,6,6,6,6,6,6,6,6,255,12,
548 2,2,2,2,255,6,6,6,6,6,6,6,6,6,6,255,
549 2,2,2,2,255,6,6,6,6,6,6,6,6,6,6,255,
550 2,2,2,2,255,6,6,6,6,6,6,6,6,6,255,14,
551 2,2,2,2,255,6,6,6,6,6,6,6,6,255,14,14,
552 2,2,2,2,255,6,6,6,6,6,6,6,255,14,14,14,
553 10,10,10,10,255,6,6,6,6,6,6,255,14,14,14,14,
554 10,10,10,10,10,255,6,6,6,6,255,14,14,14,14,14,
555 10,10,10,10,10,10,255,6,6,255,14,14,14,14,14,14,
556 10,10,10,10,10,10,10,255,255,14,14,14,14,14,14,14,
557 0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
558 0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
559 0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
560 0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
561 255,255,255,255,255,255,255,255,255,255,255,255,255,12,12,12,
562 2,2,2,2,255,6,6,6,6,6,6,6,6,255,12,12,
563 2,2,2,2,255,6,6,6,6,6,6,6,6,6,255,12,
564 2,2,2,2,255,6,6,6,6,6,6,6,6,6,6,255,
565 2,2,2,2,255,6,6,6,6,6,6,6,6,6,6,255,
566 2,2,2,2,255,6,6,6,6,6,6,6,6,6,255,14,
567 2,2,2,2,255,6,6,6,6,6,6,6,6,255,14,14,
568 2,2,2,2,255,6,6,6,6,6,6,6,255,14,14,14,
569 10,10,10,10,255,6,6,6,6,6,6,255,14,14,14,14,
570 10,10,10,10,10,255,6,6,6,6,255,14,14,14,14,14,
571 10,10,10,10,10,10,255,6,6,255,14,14,14,14,14,14,
572 10,10,10,10,10,10,10,255,255,14,14,14,14,14,14,14,
573 0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
574 0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
575 0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
576 0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
577 255,255,255,255,255,255,255,255,255,255,255,255,255,12,12,12,
578 2,2,2,2,255,6,6,6,6,6,6,6,6,255,12,12,
579 2,2,2,2,255,6,6,6,6,6,6,6,6,6,255,12,
580 2,2,2,2,255,6,6,6,6,6,6,6,6,6,6,255,
581 2,2,2,2,255,6,6,6,6,6,6,6,6,6,6,255,
582 2,2,2,2,255,6,6,6,6,6,6,6,6,6,255,14,
583 2,2,2,2,255,6,6,6,6,6,6,6,6,255,14,14,
584 2,2,2,2,255,6,6,6,6,6,6,6,255,14,14,14,
585 10,10,10,10,255,6,6,6,6,6,6,255,14,14,14,14,
586 10,10,10,10,10,255,6,6,6,6,255,14,14,14,14,14,
587 10,10,10,10,10,10,255,6,6,255,14,14,14,14,14,14,
588 10,10,10,10,10,10,10,255,255,14,14,14,14,14,14,14,
589 0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
590 0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
591 0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
592 0,0,0,0,255,4,4,4,4,4,4,4,12,12,12,12,
593 255,255,255,255,255,255,255,255,255,255,255,255,255,12,12,12,
594 2,2,2,2,255,6,6,6,6,6,6,6,6,255,12,12,
595 2,2,2,2,255,6,6,6,6,6,6,6,6,6,255,12,
596 2,2,2,2,255,6,6,6,6,6,6,6,6,6,6,255,
597 2,2,2,2,255,6,6,6,6,6,6,6,6,6,6,255,
598 2,2,2,2,255,6,6,6,6,6,6,6,6,6,255,14,
599 2,2,2,2,255,6,6,6,6,6,6,6,6,255,14,14,
600 2,2,2,2,255,6,6,6,6,6,6,6,255,14,14,14,
601 10,10,10,10,255,6,6,6,6,6,6,255,14,14,14,14,
602 10,10,10,10,10,255,6,6,6,6,255,14,14,14,14,14,
603 10,10,10,10,10,10,255,6,6,255,14,14,14,14,14,14,
604 10,10,10,10,10,10,10,255,255,14,14,14,14,14,14,14,
605 255,255,255,255,255,255,255,255,255,255,255,255,255,12,12,12,
606 255,255,255,255,255,255,255,255,255,255,255,255,255,12,12,12,
607 255,255,255,255,255,255,255,255,255,255,255,255,255,12,12,12,
608 255,255,255,255,255,255,255,255,255,255,255,255,255,12,12,12,
609 255,255,255,255,255,255,255,255,255,255,255,255,255,12,12,12,
610 255,255,255,255,255,6,6,6,6,6,6,6,6,255,12,12,
611 255,255,255,255,255,6,6,6,6,6,6,6,6,6,255,12,
612 255,255,255,255,255,6,6,6,6,6,6,6,6,6,6,255,
613 255,255,255,255,255,6,6,6,6,6,6,6,6,6,6,255,
614 255,255,255,255,255,6,6,6,6,6,6,6,6,6,255,14,
615 255,255,255,255,255,6,6,6,6,6,6,6,6,255,14,14,
616 255,255,255,255,255,6,6,6,6,6,6,6,255,14,14,14,
617 255,255,255,255,255,6,6,6,6,6,6,255,14,14,14,14,
618 10,10,10,10,10,255,6,6,6,6,255,14,14,14,14,14,
619 10,10,10,10,10,10,255,6,6,255,14,14,14,14,14,14,
620 10,10,10,10,10,10,10,255,255,14,14,14,14,14,14,14,
621 1,1,1,1,255,5,5,5,5,5,5,5,5,255,12,12,
622 1,1,1,1,255,5,5,5,5,5,5,5,5,255,12,12,
623 1,1,1,1,255,5,5,5,5,5,5,5,5,255,12,12,
624 1,1,1,1,255,5,5,5,5,5,5,5,5,255,12,12,
625 255,255,255,255,255,5,5,5,5,5,5,5,5,255,12,12,
626 3,3,3,3,3,255,255,255,255,255,255,255,255,255,12,12,
627 3,3,3,3,3,255,6,6,6,6,6,6,6,6,255,12,
628 3,3,3,3,3,255,6,255,255,6,6,6,6,6,6,255,
629 3,3,3,3,3,255,6,255,255,6,6,6,6,6,6,255,
630 3,3,3,3,3,255,6,6,6,6,6,6,6,6,255,14,
631 3,3,3,3,3,255,6,6,6,6,6,6,6,255,14,14,
632 3,3,3,3,3,255,6,6,6,6,6,6,255,14,14,14,
633 3,3,3,3,3,255,6,6,6,6,6,255,14,14,14,14,
634 255,255,255,255,255,255,6,6,6,6,255,14,14,14,14,14,
635 10,10,10,10,10,10,255,6,6,255,14,14,14,14,14,14,
636 10,10,10,10,10,10,10,255,255,14,14,14,14,14,14,14,
637 1,1,1,1,255,5,5,5,5,5,5,5,5,5,255,12,
638 1,1,1,1,255,5,5,5,5,5,5,5,5,5,255,12,
639 1,1,1,1,255,5,5,5,5,5,5,5,5,5,255,12,
640 1,1,1,1,255,5,5,5,5,5,5,5,5,5,255,12,
641 255,255,255,255,255,5,5,5,5,5,5,5,5,5,255,12,
642 3,3,3,3,3,255,5,5,5,5,5,5,5,5,255,12,
643 3,3,3,3,3,3,255,255,255,255,255,255,255,255,255,12,
644 3,3,3,3,3,3,255,255,255,255,255,6,6,6,6,255,
645 3,3,3,3,3,3,255,255,255,255,255,6,6,6,6,255,
646 3,3,3,3,3,3,255,255,255,255,255,6,6,6,255,14,
647 3,3,3,3,3,3,255,255,255,255,6,6,6,255,14,14,
648 3,3,3,3,3,3,255,6,6,6,6,6,255,14,14,14,
649 3,3,3,3,3,3,255,6,6,6,6,255,14,14,14,14,
650 3,3,3,3,3,3,255,6,6,6,255,14,14,14,14,14,
651 255,255,255,255,255,255,255,6,6,255,14,14,14,14,14,14,
652 10,10,10,10,10,10,10,255,255,14,14,14,14,14,14,14,
653 1,1,1,1,255,5,5,5,5,5,5,5,5,5,5,255,
654 1,1,1,1,255,5,5,5,5,5,5,5,5,5,5,255,
655 1,1,1,1,255,5,5,5,5,5,5,5,5,5,5,255,
656 1,1,1,1,255,5,5,5,5,5,5,5,5,5,5,255,
657 255,255,255,255,255,5,5,5,5,5,5,5,5,5,5,255,
658 3,3,3,3,3,255,5,255,255,5,5,5,5,5,5,255,
659 3,3,3,3,3,3,255,255,255,255,255,5,5,5,5,255,
660 3,3,3,3,3,255,255,7,7,7,255,255,255,255,255,255,
661 3,3,3,3,3,255,255,7,7,7,255,6,6,6,6,255,
662 3,3,3,3,3,3,255,7,7,255,255,6,6,6,255,14,
663 3,3,3,3,3,3,255,255,255,255,255,6,6,255,14,14,
664 3,3,3,3,3,3,3,255,6,6,6,6,255,14,14,14,
665 3,3,3,3,3,3,3,255,6,6,6,255,14,14,14,14,
666 3,3,3,3,3,3,3,255,6,6,255,14,14,14,14,14,
667 3,3,3,3,3,3,3,255,6,255,14,14,14,14,14,14,
668 255,255,255,255,255,255,255,255,255,14,14,14,14,14,14,14,
669 1,1,1,1,255,5,5,5,5,5,5,5,5,5,5,255,
670 1,1,1,1,255,5,5,5,5,5,5,5,5,5,5,255,
671 1,1,1,1,255,5,5,5,5,5,5,5,5,5,5,255,
672 1,1,1,1,255,5,5,5,5,5,5,5,5,5,5,255,
673 255,255,255,255,255,5,5,5,5,5,5,5,5,5,5,255,
674 3,3,3,3,3,255,5,255,255,5,5,5,5,5,5,255,
675 3,3,3,3,3,3,255,255,255,255,255,5,5,5,5,255,
676 3,3,3,3,3,255,255,7,7,7,255,5,5,5,5,255,
677 3,3,3,3,3,255,255,7,7,7,255,255,255,255,255,255,
678 3,3,3,3,3,3,255,7,7,7,255,255,255,255,255,15,
679 3,3,3,3,3,3,255,255,255,255,255,255,255,255,15,15,
680 3,3,3,3,3,3,3,3,255,255,255,255,255,15,15,15,
681 3,3,3,3,3,3,3,3,255,255,255,255,15,15,15,15,
682 3,3,3,3,3,3,3,3,255,255,255,15,15,15,15,15,
683 3,3,3,3,3,3,3,3,255,255,15,15,15,15,15,15,
684 255,255,255,255,255,255,255,255,255,15,15,15,15,15,15,15,
685 1,1,1,1,255,5,5,5,5,5,5,5,5,5,255,13,
686 1,1,1,1,255,5,5,5,5,5,5,5,5,5,255,13,
687 1,1,1,1,255,5,5,5,5,5,5,5,5,5,255,13,
688 1,1,1,1,255,5,5,5,5,5,5,5,5,5,255,13,
689 255,255,255,255,255,5,5,5,5,5,5,5,5,5,255,13,
690 3,3,3,3,3,255,5,5,5,5,5,5,5,5,255,13,
691 3,3,3,3,3,3,255,255,255,255,255,5,5,5,255,13,
692 3,3,3,3,3,3,255,7,7,255,255,5,5,5,255,13,
693 3,3,3,3,3,3,255,7,7,7,255,255,255,255,255,15,
694 3,3,3,3,3,3,255,255,7,7,255,255,255,15,15,15,
695 3,3,3,3,3,3,255,255,255,255,255,255,15,15,15,15,
696 3,3,3,3,3,3,3,3,255,255,255,15,15,15,15,15,
697 3,3,3,3,3,3,3,3,255,255,15,15,15,15,15,15,
698 3,3,3,3,3,3,3,3,255,15,15,15,15,15,15,15,
699 255,255,255,255,255,255,255,255,255,15,15,15,15,15,15,15,
700 11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
701 1,1,1,1,255,5,5,5,5,5,5,5,5,255,13,13,
702 1,1,1,1,255,5,5,5,5,5,5,5,5,255,13,13,
703 1,1,1,1,255,5,5,5,5,5,5,5,5,255,13,13,
704 1,1,1,1,255,5,5,5,5,5,5,5,5,255,13,13,
705 255,255,255,255,255,5,5,5,5,5,5,5,5,255,13,13,
706 3,3,3,3,3,255,5,5,5,5,5,5,5,255,13,13,
707 3,3,3,3,3,3,255,255,255,255,5,5,5,255,13,13,
708 3,3,3,3,3,3,255,255,255,255,255,5,5,255,13,13,
709 3,3,3,3,3,3,255,255,255,255,255,255,255,255,15,15,
710 3,3,3,3,3,3,255,255,255,255,255,255,15,15,15,15,
711 3,3,3,3,3,3,3,255,255,255,255,255,255,255,15,15,
712 3,3,3,3,3,3,3,3,255,255,255,255,255,255,255,15,
713 3,3,3,3,3,3,3,3,255,15,255,255,255,255,255,15,
714 255,255,255,255,255,255,255,255,255,15,255,255,255,255,15,15,
715 11,11,11,11,11,11,11,11,15,15,15,255,255,15,15,15,
716 11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
717 1,1,1,1,255,5,5,5,5,5,5,5,255,13,13,13,
718 1,1,1,1,255,5,5,5,5,5,5,5,255,13,13,13,
719 1,1,1,1,255,5,5,5,5,5,5,5,255,13,13,13,
720 1,1,1,1,255,5,5,5,5,5,5,5,255,13,13,13,
721 255,255,255,255,255,5,5,5,5,5,5,5,255,13,13,13,
722 3,3,3,3,3,255,5,5,5,5,5,5,255,13,13,13,
723 3,3,3,3,3,3,255,5,5,5,5,5,255,13,13,13,
724 3,3,3,3,3,3,3,255,5,5,5,5,255,13,13,13,
725 3,3,3,3,3,3,3,3,255,255,255,255,255,15,15,15,
726 3,3,3,3,3,3,3,3,255,255,255,15,15,15,15,15,
727 3,3,3,3,3,3,3,3,255,255,255,255,255,255,255,15,
728 3,3,3,3,3,3,3,3,255,15,255,255,8,255,255,15,
729 255,255,255,255,255,255,255,255,255,15,255,8,8,8,255,15,
730 11,11,11,11,11,11,11,11,15,15,255,255,8,255,255,15,
731 11,11,11,11,11,11,11,11,15,15,255,255,255,255,15,15,
732 11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
733 9,9,9,9,255,5,5,5,5,5,5,255,13,13,13,13,
734 9,9,9,9,255,5,5,5,5,5,5,255,13,13,13,13,
735 9,9,9,9,255,5,5,5,5,5,5,255,13,13,13,13,
736 9,9,9,9,255,5,5,5,5,5,5,255,13,13,13,13,
737 255,255,255,255,255,5,5,5,5,5,5,255,13,13,13,13,
738 3,3,3,3,3,255,5,5,5,5,5,255,13,13,13,13,
739 3,3,3,3,3,3,255,5,5,5,5,255,13,13,13,13,
740 3,3,3,3,3,3,3,255,5,5,5,255,13,13,13,13,
741 3,3,3,3,3,3,3,3,255,255,255,255,15,15,15,15,
742 3,3,3,3,3,3,3,3,255,255,15,15,15,15,15,15,
743 3,3,3,3,3,3,3,3,255,15,255,255,255,255,255,15,
744 255,255,255,255,255,255,255,255,255,15,255,8,8,8,255,15,
745 11,11,11,11,11,11,11,11,15,15,255,8,8,8,255,15,
746 11,11,11,11,11,11,11,11,15,15,255,8,8,255,255,15,
747 11,11,11,11,11,11,11,11,15,15,255,255,255,255,15,15,
748 11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
749 9,9,9,9,9,255,5,5,5,5,255,13,13,13,13,13,
750 9,9,9,9,9,255,5,5,5,5,255,13,13,13,13,13,
751 9,9,9,9,9,255,5,5,5,5,255,13,13,13,13,13,
752 9,9,9,9,9,255,5,5,5,5,255,13,13,13,13,13,
753 9,9,9,9,9,255,5,5,5,5,255,13,13,13,13,13,
754 255,255,255,255,255,255,5,5,5,5,255,13,13,13,13,13,
755 3,3,3,3,3,3,255,5,5,5,255,13,13,13,13,13,
756 3,3,3,3,3,3,3,255,5,5,255,13,13,13,13,13,
757 3,3,3,3,3,3,3,3,255,255,255,15,15,15,15,15,
758 3,3,3,3,3,3,3,3,255,15,15,15,15,15,15,15,
759 255,255,255,255,255,255,255,255,255,15,255,255,255,255,15,15,
760 11,11,11,11,11,11,11,11,15,15,255,255,8,255,255,15,
761 11,11,11,11,11,11,11,11,15,15,255,8,8,255,255,15,
762 11,11,11,11,11,11,11,11,15,15,255,255,255,255,255,15,
763 11,11,11,11,11,11,11,11,15,15,15,255,255,255,15,15,
764 11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
765 9,9,9,9,9,9,255,5,5,255,13,13,13,13,13,13,
766 9,9,9,9,9,9,255,5,5,255,13,13,13,13,13,13,
767 9,9,9,9,9,9,255,5,5,255,13,13,13,13,13,13,
768 9,9,9,9,9,9,255,5,5,255,13,13,13,13,13,13,
769 9,9,9,9,9,9,255,5,5,255,13,13,13,13,13,13,
770 9,9,9,9,9,9,255,5,5,255,13,13,13,13,13,13,
771 255,255,255,255,255,255,255,5,5,255,13,13,13,13,13,13,
772 3,3,3,3,3,3,3,255,5,255,13,13,13,13,13,13,
773 3,3,3,3,3,3,3,3,255,255,15,15,15,15,15,15,
774 255,255,255,255,255,255,255,255,255,15,15,15,15,15,15,15,
775 11,11,11,11,11,11,11,11,15,15,15,255,255,15,15,15,
776 11,11,11,11,11,11,11,11,15,15,255,255,255,255,15,15,
777 11,11,11,11,11,11,11,11,15,15,255,255,255,255,15,15,
778 11,11,11,11,11,11,11,11,15,15,15,255,255,255,15,15,
779 11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
780 11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
781 9,9,9,9,9,9,9,255,255,13,13,13,13,13,13,13,
782 9,9,9,9,9,9,9,255,255,13,13,13,13,13,13,13,
783 9,9,9,9,9,9,9,255,255,13,13,13,13,13,13,13,
784 9,9,9,9,9,9,9,255,255,13,13,13,13,13,13,13,
785 9,9,9,9,9,9,9,255,255,13,13,13,13,13,13,13,
786 9,9,9,9,9,9,9,255,255,13,13,13,13,13,13,13,
787 9,9,9,9,9,9,9,255,255,13,13,13,13,13,13,13,
788 255,255,255,255,255,255,255,255,255,13,13,13,13,13,13,13,
789 255,255,255,255,255,255,255,255,255,15,15,15,15,15,15,15,
790 11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
791 11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
792 11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
793 11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
794 11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
795 11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
796 11,11,11,11,11,11,11,11,15,15,15,15,15,15,15,15,
797 };
798/*...e*/
799
800static byte nearest_colour(byte r, byte g, byte b)
801 {
802 byte i;
803
804 if ( (i = quick_tab[r >> 4][g >> 4][b >> 4]) != (byte) 0xff )
805 return i;
806
807 return calc_nearest(r, g, b);
808 }
809/*...e*/
810
811void gbm_errdiff_line_VGA(byte *src, byte *dest, short *errs, int cx)
812 {
813 BOOLEAN left = TRUE;
814 int x, ptr = 0;
815
816 init();
817
818 /* Step 1: Add error terms to newly supplied line */
819
820 for ( x = 0; x < cx * 3; x++ )
821 src[x] = U_SAT_ADD((int) src[x], (int) errs[x]);
822
823 /* Step 2: Zero out error terms */
824
825 memset(errs, 0, (cx + 1) * 3 * sizeof(errs[0]));
826
827 /* Step 3: Go along data, finding nearest colour and propagating error */
828
829 randinx = rand();
830
831 for ( x = 0; x < cx; x++ )
832 {
833 byte b = *src++;
834 byte g = *src++;
835 byte r = *src++;
836 byte bi = nearest_colour(r, g, b);
837 int be = (int) b - (int) gbmrgb_vga[bi].b;
838 int ge = (int) g - (int) gbmrgb_vga[bi].g;
839 int re = (int) r - (int) gbmrgb_vga[bi].r;
840 word rn = randtab[(byte) (randinx++)];
841 int right = (rn >> 8);
842 int down = ((rn & 0xff) % (63 - right));
843 int be1 = ((be * right) >> 6);
844 int ge1 = ((ge * right) >> 6);
845 int re1 = ((re * right) >> 6);
846 int be2 = ((be * down ) >> 6);
847 int ge2 = ((ge * down ) >> 6);
848 int re2 = ((re * down ) >> 6);
849 int be3 = be - be1 - be2;
850 int ge3 = ge - ge1 - ge2;
851 int re3 = re - re1 - re2;
852
853 if ( left )
854 *dest = (byte) (bi << 4);
855 else
856 *dest++ |= bi;
857
858 left = !left;
859
860 src[0] = U_SAT_ADD((int) src[0], be1);
861 src[1] = U_SAT_ADD((int) src[1], ge1);
862 src[2] = U_SAT_ADD((int) src[2], re1);
863
864 errs[ptr ] = S_SAT_ADD((int) errs[ptr ], be2);
865 errs[ptr + 1] = S_SAT_ADD((int) errs[ptr + 1], ge2);
866 errs[ptr + 2] = S_SAT_ADD((int) errs[ptr + 2], re2);
867
868 ptr += 3;
869
870 errs[ptr ] = S_SAT_ADD((int) errs[ptr ], be3);
871 errs[ptr + 1] = S_SAT_ADD((int) errs[ptr + 1], ge3);
872 errs[ptr + 2] = S_SAT_ADD((int) errs[ptr + 2], re3);
873 }
874 }
875/*...e*/
876/*...sgbm_errdiff_VGA \45\ error diffuse to default VGA palette:0:*/
877BOOLEAN gbm_errdiff_VGA(const GBM *gbm, const byte *data24, byte *data4)
878 {
879 return errdiff(gbm, data24, data4, 4, gbm_errdiff_line_VGA);
880 }
881/*...e*/
882
883/*...sgbm_errdiff_pal_8 \45\ return default 8 colour palette:0:*/
884/*
885This function makes the palette for the 16 colour 8 colour palette.
886*/
887
888static GBMRGB gbmrgb_8[] =
889 {
890 0, 0, 0,
891 0, 0,255,
892 0,255, 0,
893 0,255,255,
894 255, 0, 0,
895 255, 0,255,
896 255,255, 0,
897 255,255,255,
898 0, 0, 0,
899 0, 0, 0,
900 0, 0, 0,
901 0, 0, 0,
902 0, 0, 0,
903 0, 0, 0,
904 0, 0, 0,
905 0, 0, 0,
906 };
907
908void gbm_errdiff_pal_8(GBMRGB *gbmrgb)
909 {
910 init();
911 memcpy((char *) gbmrgb, (char *) gbmrgb_8, sizeof(gbmrgb_8));
912 }
913/*...e*/
914/*...sgbm_errdiff_line_8 \45\ error diffuse to default 8 colour palette one line:0:*/
915/*
916This function takes a line of RGB data, a destination buffer and a buffer of
917error terms and performs one lines worth (a given # of pixels) of error
918diffusion.
919*/
920
921void gbm_errdiff_line_8(byte *src, byte *dest, short *errs, int cx)
922 {
923 BOOLEAN left = TRUE;
924 int x, ptr = 0;
925
926 init();
927
928 /* Step 1: Add error terms to newly supplied line */
929
930 for ( x = 0; x < cx * 3; x++ )
931 src[x] = U_SAT_ADD((int) src[x], (int) errs[x]);
932
933 /* Step 2: Zero out error terms */
934
935 memset(errs, 0, (cx + 1) * 3 * sizeof(errs[0]));
936
937 /* Step 3: Go along data, finding nearest colour and propagating error */
938
939 randinx = rand();
940
941 for ( x = 0; x < cx; x++ )
942 {
943 byte b = *src++;
944 byte g = *src++;
945 byte r = *src++;
946 byte bi = ((r&0x80U)>>5) | ((g&0x80U)>>6) | ((b&0x80U)>>7);
947 int be = (int) b - (int) gbmrgb_8[bi].b;
948 int ge = (int) g - (int) gbmrgb_8[bi].g;
949 int re = (int) r - (int) gbmrgb_8[bi].r;
950 word rn = randtab[(byte) (randinx++)];
951 int right = (rn >> 8);
952 int down = ((rn & 0xff) % (63 - right));
953 int be1 = ((be * right) >> 6);
954 int ge1 = ((ge * right) >> 6);
955 int re1 = ((re * right) >> 6);
956 int be2 = ((be * down ) >> 6);
957 int ge2 = ((ge * down ) >> 6);
958 int re2 = ((re * down ) >> 6);
959 int be3 = be - be1 - be2;
960 int ge3 = ge - ge1 - ge2;
961 int re3 = re - re1 - re2;
962
963 if ( left )
964 *dest = (byte) (bi << 4);
965 else
966 *dest++ |= bi;
967
968 left = !left;
969
970 src[0] = U_SAT_ADD((int) src[0], be1);
971 src[1] = U_SAT_ADD((int) src[1], ge1);
972 src[2] = U_SAT_ADD((int) src[2], re1);
973
974 errs[ptr ] = S_SAT_ADD((int) errs[ptr ], be2);
975 errs[ptr + 1] = S_SAT_ADD((int) errs[ptr + 1], ge2);
976 errs[ptr + 2] = S_SAT_ADD((int) errs[ptr + 2], re2);
977
978 ptr += 3;
979
980 errs[ptr ] = S_SAT_ADD((int) errs[ptr ], be3);
981 errs[ptr + 1] = S_SAT_ADD((int) errs[ptr + 1], ge3);
982 errs[ptr + 2] = S_SAT_ADD((int) errs[ptr + 2], re3);
983 }
984 }
985/*...e*/
986/*...sgbm_errdiff_8 \45\ error diffuse to default 8 colour palette:0:*/
987BOOLEAN gbm_errdiff_8(const GBM *gbm, const byte *data24, byte *data4)
988 {
989 return errdiff(gbm, data24, data4, 4, gbm_errdiff_line_8);
990 }
991/*...e*/
992
993/*...sgbm_errdiff_pal_4G \45\ return 4 bit greyscale palette:0:*/
994/*
995This function makes the palette for the 16 colour VGA palette.
996*/
997
998void gbm_errdiff_pal_4G(GBMRGB *gbmrgb)
999 {
1000 int i;
1001
1002 init();
1003 for ( i = 0; i < 0x10; i++ )
1004 {
1005 gbmrgb[i].r = scale16[i];
1006 gbmrgb[i].g = scale16[i];
1007 gbmrgb[i].b = scale16[i];
1008 }
1009 }
1010/*...e*/
1011/*...sgbm_errdiff_line_4G \45\ error diffuse to 4 bit greyscale palette one line:0:*/
1012/*
1013This function takes a line of RGB data, a destination buffer and a buffer of
1014error terms and performs one lines worth (a given # of pixels) of error
1015diffusion.
1016*/
1017
1018void gbm_errdiff_line_4G(byte *src, byte *dest, short *errs, int cx)
1019 {
1020 BOOLEAN left = TRUE;
1021 int x, ptr = 0;
1022 byte *pb;
1023
1024 init();
1025
1026 /* Step 1: Add error terms to newly supplied line */
1027
1028 for ( x = 0, pb = src; x < cx; x++ )
1029 {
1030 byte b = *pb++;
1031 byte g = *pb++;
1032 byte r = *pb++;
1033
1034 src[x] = (byte) (((word) r * 77U + (word) g * 150U + (word) b * 29U) >> 8);
1035 src[x] = U_SAT_ADD((int) src[x], (int) errs[x]);
1036 }
1037
1038 /* Step 2: Zero out error terms */
1039
1040 memset(errs, 0, (cx + 1) * sizeof(errs[0]));
1041
1042 /* Step 3: Go along data, finding nearest colour and propagating error */
1043
1044 randinx = rand();
1045
1046 for ( x = 0; x < cx; x++ )
1047 {
1048 byte grey = *src++;
1049 byte inx = index16[grey];
1050 int err = (int) grey - (int) scale16[inx];
1051 word rn = randtab[(byte) (randinx++)];
1052 int right = (rn >> 8);
1053 int down = ((rn & 0xff) % (63 - right));
1054 int err1 = ((err * right) >> 6);
1055 int err2 = ((err * down ) >> 6);
1056 int err3 = err - err1 - err2;
1057
1058 if ( left )
1059 *dest = (byte) (inx << 4);
1060 else
1061 *dest++ |= inx;
1062
1063 left = !left;
1064
1065 src[0] = U_SAT_ADD((int) src[0], err1);
1066
1067 errs[ptr] = S_SAT_ADD((int) errs[ptr], err2);
1068
1069 ptr++;
1070
1071 errs[ptr] = S_SAT_ADD((int) errs[ptr], err3);
1072 }
1073 }
1074/*...e*/
1075/*...sgbm_errdiff_4G \45\ error diffuse to 4 bit greyscale palette:0:*/
1076BOOLEAN gbm_errdiff_4G(const GBM *gbm, const byte *data24, byte *data4)
1077 {
1078 return errdiff(gbm, data24, data4, 4, gbm_errdiff_line_4G);
1079 }
1080/*...e*/
1081
1082/*...sgbm_errdiff_pal_BW \45\ return black and white palette:0:*/
1083/*
1084This function returns the b/w palette.
1085(We consider the image to be likely black on white,
1086hence the ordering of the palette entries).
1087*/
1088
1089static GBMRGB gbmrgb_bw[] =
1090 {
1091 255,255,255,
1092 0,0,0,
1093 };
1094
1095void gbm_errdiff_pal_BW(GBMRGB *gbmrgb)
1096 {
1097 init();
1098 memcpy((char *) gbmrgb, (char *) gbmrgb_bw, sizeof(gbmrgb_bw));
1099 }
1100/*...e*/
1101/*...sgbm_errdiff_line_BW \45\ error diffuse to black and white one line:0:*/
1102/*
1103This function takes a line of RGB data, a destination buffer and a buffer of
1104error terms and performs one lines worth (a given # of pixels) of error
1105diffusion.
1106*/
1107
1108void gbm_errdiff_line_BW(byte *src, byte *dest, short *errs, int cx)
1109 {
1110 int x, bit = 0, ptr = 0;
1111 byte *pb;
1112
1113 init();
1114
1115 /* Step 1: Add error terms to newly supplied line */
1116
1117 for ( x = 0, pb = src; x < cx; x++ )
1118 {
1119 byte b = *pb++;
1120 byte g = *pb++;
1121 byte r = *pb++;
1122
1123 src[x] = (byte) (((word) r * 77U + (word) g * 150U + (word) b * 29U) >> 8);
1124 src[x] = U_SAT_ADD((int) src[x], (int) errs[x]);
1125 }
1126
1127 /* Step 2: Zero out error terms */
1128
1129 memset(errs, 0, (cx + 1) * sizeof(errs[0]));
1130
1131 /* Step 3: Go along data, finding nearest colour and propagating error */
1132
1133 memset(dest, 0, (unsigned) (cx + 7) >> 3);
1134
1135 randinx = rand();
1136
1137 for ( x = 0; x < cx; x++ )
1138 {
1139 byte grey = *src++;
1140 byte inx = (byte) (grey < 0x80);
1141 int err = (int) grey - (int) gbmrgb_bw[inx].b;
1142 word rn = randtab[(byte) (randinx++)];
1143 int right = (rn >> 8);
1144 int down = ((rn & 0xff) % (63 - right));
1145 int err1 = ((err * right) >> 6);
1146 int err2 = ((err * down ) >> 6);
1147 int err3 = err - err1 - err2;
1148
1149 if ( inx )
1150 *dest |= (0x80U >> bit);
1151
1152 if ( ++bit == 8 )
1153 {
1154 bit = 0;
1155 dest++;
1156 }
1157
1158 src[0] = U_SAT_ADD((int) src[0], err1);
1159
1160 errs[ptr] = S_SAT_ADD((int) errs[ptr], err2);
1161
1162 ptr++;
1163
1164 errs[ptr] = S_SAT_ADD((int) errs[ptr], err3);
1165 }
1166 }
1167/*...e*/
1168/*...sgbm_errdiff_BW \45\ error diffuse to black and white:0:*/
1169BOOLEAN gbm_errdiff_BW(const GBM *gbm, const byte *data24, byte *data1)
1170 {
1171 return errdiff(gbm, data24, data1, 1, gbm_errdiff_line_BW);
1172 }
1173/*...e*/
Note: See TracBrowser for help on using the repository browser.