1 | /**************************************************************************
|
---|
2 | *
|
---|
3 | * bilevel.c -- Compress a bilevel bitmap
|
---|
4 | * Copyright (C) 1994 Stuart Inglis
|
---|
5 | *
|
---|
6 | * This program is free software; you can redistribute it and/or modify
|
---|
7 | * it under the terms of the GNU General Public License as published by
|
---|
8 | * the Free Software Foundation; either version 2 of the License, or
|
---|
9 | * (at your option) any later version.
|
---|
10 | *
|
---|
11 | * This program is distributed in the hope that it will be useful,
|
---|
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
14 | * GNU General Public License for more details.
|
---|
15 | *
|
---|
16 | * You should have received a copy of the GNU General Public License
|
---|
17 | * along with this program; if not, write to the Free Software
|
---|
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
---|
19 | *
|
---|
20 | * $Id: bilevel.c 3745 2003-02-20 21:20:24Z mdewsnip $
|
---|
21 | *
|
---|
22 | **************************************************************************
|
---|
23 | *
|
---|
24 | *
|
---|
25 | *
|
---|
26 | * This is the code used to compress a bitmap. The template is given in
|
---|
27 | * the following format.
|
---|
28 | * '.' = pixel not used
|
---|
29 | * 'p' = pixel used in 1st order context (the superset)
|
---|
30 | * '2' = pixel used in 2nd order context (the subset)
|
---|
31 | * ';' = marker used to denote the end of a row in the template
|
---|
32 | * '*' = the current context pixel.
|
---|
33 | * for instance, the common 22/10 template would be shown as:
|
---|
34 | * ".ppppp.;"
|
---|
35 | * "pp222pp;"
|
---|
36 | * "p22222p;"
|
---|
37 | * "p22*...;"
|
---|
38 | *
|
---|
39 | **************************************************************************/
|
---|
40 |
|
---|
41 |
|
---|
42 | #include "sysfuncs.h"
|
---|
43 |
|
---|
44 | #include "bilevel.h"
|
---|
45 | #include "extractor.h"
|
---|
46 | #include "pbmtools.h"
|
---|
47 | #include "marklist.h"
|
---|
48 | #include "arithcode.h"
|
---|
49 | #include "utils.h"
|
---|
50 |
|
---|
51 |
|
---|
52 |
|
---|
53 | #define INITVALUE 2
|
---|
54 | #define INCREMENT 4
|
---|
55 |
|
---|
56 | #define MAX_T_W 32
|
---|
57 |
|
---|
58 | /* note memory usage is 2*TEMPLATESIZE*sizeof(prob), which is currently 4.9 Mb */
|
---|
59 | #define TEMPLATESIZE 612317
|
---|
60 |
|
---|
61 |
|
---|
62 | #define HASH(x) ((x)%TEMPLATESIZE)
|
---|
63 |
|
---|
64 |
|
---|
65 | typedef struct
|
---|
66 | {
|
---|
67 | unsigned short s, n;
|
---|
68 | }
|
---|
69 | prob; /* set and notset */
|
---|
70 | typedef struct
|
---|
71 | {
|
---|
72 | short int x, y;
|
---|
73 | }
|
---|
74 | coordinate;
|
---|
75 |
|
---|
76 | coordinate MM[MAX_T_W][MAX_T_W]; /* the actual (x,y) positions */
|
---|
77 | unsigned int MMcount[MAX_T_W]; /* number of bits in this row of the template */
|
---|
78 | unsigned int MMmask[MAX_T_W]; /* the "current" mask value */
|
---|
79 | unsigned int MMbits[MAX_T_W]; /* the bitmask to mask out higher bits */
|
---|
80 | unsigned int MMrows; /* total number of rows */
|
---|
81 | unsigned int MM2level[MAX_T_W]; /* bitmask to calculate the 2nd level mask */
|
---|
82 | int twolevel, curr_row, surr;
|
---|
83 |
|
---|
84 | prob *P = NULL; /* probability array, up to N bits */
|
---|
85 | prob *P2 = NULL;
|
---|
86 |
|
---|
87 | void
|
---|
88 | bl_clearmodel ()
|
---|
89 | {
|
---|
90 | int i;
|
---|
91 |
|
---|
92 | P = (prob *) malloc (TEMPLATESIZE * sizeof (prob));
|
---|
93 | if (!P)
|
---|
94 | error_msg ("bl_clearmodel()", "not enough memory.", "");
|
---|
95 |
|
---|
96 | P2 = (prob *) malloc (TEMPLATESIZE * sizeof (prob));
|
---|
97 | if (!P2)
|
---|
98 | error_msg ("bl_clearmodel()", "not enough memory.", "");
|
---|
99 |
|
---|
100 | for (i = 0; i < TEMPLATESIZE; i++)
|
---|
101 | {
|
---|
102 | P[i].s = P[i].n = INITVALUE;
|
---|
103 | P2[i].s = P2[i].n = INITVALUE;
|
---|
104 | }
|
---|
105 | }
|
---|
106 |
|
---|
107 |
|
---|
108 | void
|
---|
109 | bl_freemodel ()
|
---|
110 | {
|
---|
111 | free (P);
|
---|
112 | free (P2);
|
---|
113 | }
|
---|
114 |
|
---|
115 |
|
---|
116 |
|
---|
117 |
|
---|
118 | #define update_counts(p, pixel) \
|
---|
119 | pixel ? (p->s+=INCREMENT) : (p->n+=INCREMENT); \
|
---|
120 | \
|
---|
121 | if(p->s+p->n >= (unsigned)(maxfrequency)) { \
|
---|
122 | p->s=(p->s+1)/(unsigned)2; \
|
---|
123 | p->n=(p->n+1)/(unsigned)2; \
|
---|
124 | }
|
---|
125 |
|
---|
126 |
|
---|
127 |
|
---|
128 |
|
---|
129 | /* mask is the bigger one, mask2l is smaller one */
|
---|
130 | static void
|
---|
131 | bl_encode_in_context (unsigned long mask, unsigned long mask2l, unsigned long pixel)
|
---|
132 | {
|
---|
133 | register int twol, t;
|
---|
134 | prob *p = &P[mask];
|
---|
135 | prob *p2 = &P2[mask2l];
|
---|
136 |
|
---|
137 | twol = twolevel && (p->s + p->n < (unsigned) (2 * INITVALUE + 5 * INCREMENT));
|
---|
138 |
|
---|
139 | t = twol ? (p2->s + p2->n) : (p->s + p->n);
|
---|
140 |
|
---|
141 | if (twol == 0)
|
---|
142 | {
|
---|
143 | if (pixel)
|
---|
144 | arithmetic_encode (0, p->s, t);
|
---|
145 | else
|
---|
146 | arithmetic_encode (p->s, t, t);
|
---|
147 | update_counts (p, pixel);
|
---|
148 | }
|
---|
149 | else
|
---|
150 | {
|
---|
151 | if (pixel)
|
---|
152 | arithmetic_encode (0, p2->s, t);
|
---|
153 | else
|
---|
154 | arithmetic_encode (p2->s, t, t);
|
---|
155 | update_counts (p2, pixel);
|
---|
156 | update_counts (p, pixel);
|
---|
157 | }
|
---|
158 | }
|
---|
159 |
|
---|
160 |
|
---|
161 | static void
|
---|
162 | bl_decode_in_context (unsigned long mask, unsigned long mask2l, unsigned long *val)
|
---|
163 | {
|
---|
164 | register int twol, pixel, t;
|
---|
165 | prob *p = &P[mask];
|
---|
166 | prob *p2 = &P2[mask2l];
|
---|
167 |
|
---|
168 |
|
---|
169 | if (twolevel && (p->s + p->n < (unsigned) (2 * INITVALUE + 5 * INCREMENT)))
|
---|
170 | {
|
---|
171 | pixel = arithmetic_decode_target (p2->s + p2->n) < p2->s, twol = 1;
|
---|
172 | }
|
---|
173 | else
|
---|
174 | {
|
---|
175 | pixel = arithmetic_decode_target (p->s + p->n) < p->s, twol = 0;
|
---|
176 | }
|
---|
177 |
|
---|
178 | t = twol ? (p2->s + p2->n) : (p->s + p->n);
|
---|
179 |
|
---|
180 | if (twol == 0)
|
---|
181 | {
|
---|
182 | if (pixel)
|
---|
183 | arithmetic_decode (0, p->s, t);
|
---|
184 | else
|
---|
185 | arithmetic_decode (p->s, t, t);
|
---|
186 | update_counts (p, pixel);
|
---|
187 | }
|
---|
188 | else
|
---|
189 | {
|
---|
190 | if (pixel)
|
---|
191 | arithmetic_decode (0, p2->s, t);
|
---|
192 | else
|
---|
193 | arithmetic_decode (p2->s, t, t);
|
---|
194 | update_counts (p2, pixel);
|
---|
195 | update_counts (p, pixel);
|
---|
196 | }
|
---|
197 |
|
---|
198 | *val = pixel;
|
---|
199 | }
|
---|
200 |
|
---|
201 | static void
|
---|
202 | bl_string_to_array (char inputstr[], char parsestr[], int *w, int *h)
|
---|
203 | {
|
---|
204 | int r, c;
|
---|
205 | int i, j, lastc, p, l;
|
---|
206 | int xc, yc;
|
---|
207 | int foundstatus;
|
---|
208 |
|
---|
209 | surr = twolevel = 0;
|
---|
210 | for (i = 0; i < MAX_T_W; i++)
|
---|
211 | MMcount[i] = MM2level[i] = 0;
|
---|
212 | MMrows = 0;
|
---|
213 |
|
---|
214 | for (i = 0; i < (int) strlen (inputstr); i++)
|
---|
215 | {
|
---|
216 | p = inputstr[i];
|
---|
217 | if ((p != '.') && (p != '2') && (p != '*') && (p != 'p') && (p != ';'))
|
---|
218 | {
|
---|
219 | fprintf (stderr, "Template string can only contain [.p2*;], not \"%c\".\n", inputstr[i]);
|
---|
220 | exit (1);
|
---|
221 | }
|
---|
222 | }
|
---|
223 |
|
---|
224 | /* get the width and height, test rectangularity... */
|
---|
225 | parsestr[l = 0] = 0;
|
---|
226 | for (c = 0, r = 0, lastc = -1, p = 0; p < (int) strlen (inputstr); p++)
|
---|
227 | {
|
---|
228 | if ((inputstr[p] == ';'))
|
---|
229 | {
|
---|
230 | r++;
|
---|
231 | if (lastc != -1)
|
---|
232 | { /* this is the 2nd row at least */
|
---|
233 | if (lastc != c)
|
---|
234 | {
|
---|
235 | fprintf (stderr, "The rows have to be the same width. "
|
---|
236 | "Row %d has width %d (previous row has width %d)\n", r, c, lastc);
|
---|
237 | exit (1);
|
---|
238 | }
|
---|
239 | }
|
---|
240 | lastc = c;
|
---|
241 | c = 0;
|
---|
242 | }
|
---|
243 | else
|
---|
244 | {
|
---|
245 | c++;
|
---|
246 | parsestr[l] = inputstr[p];
|
---|
247 | parsestr[++l] = 0;
|
---|
248 | }
|
---|
249 | }
|
---|
250 |
|
---|
251 | if (c != 0)
|
---|
252 | lastc = c;
|
---|
253 | *w = lastc;
|
---|
254 | *h = r;
|
---|
255 | if ((*w) <= 0)
|
---|
256 | {
|
---|
257 | fprintf (stderr, "Must have at least one column!\n");
|
---|
258 | exit (1);
|
---|
259 | }
|
---|
260 | if ((*h) <= 0)
|
---|
261 | {
|
---|
262 | fprintf (stderr, "Must have at least one row! Terminate each row with a ';'\n");
|
---|
263 | exit (1);
|
---|
264 | }
|
---|
265 | if ((*w > MAX_T_W) || (*h > MAX_T_W))
|
---|
266 | {
|
---|
267 | fprintf (stderr, "template size bigger than internal threshold of %d\n", MAX_T_W);
|
---|
268 | exit (1);
|
---|
269 | }
|
---|
270 |
|
---|
271 | /* get the (x,y) position of the current (*) pixel */
|
---|
272 | for (xc = -1, yc = 0, i = 0; i < *w; i++)
|
---|
273 | for (j = 0; j < *h; j++)
|
---|
274 | if (parsestr[j * (*w) + i] == '*')
|
---|
275 | {
|
---|
276 | if (xc >= 0)
|
---|
277 | {
|
---|
278 | fprintf (stderr, "There can only be ONE current ('*') pixel.\n");
|
---|
279 | exit (1);
|
---|
280 | }
|
---|
281 | xc = i;
|
---|
282 | yc = j;
|
---|
283 | curr_row = j + 1;
|
---|
284 | }
|
---|
285 | if (xc < 0)
|
---|
286 | error_msg ("bl_string_to_array", "Error in mask, no current ('*') pixel.", "");
|
---|
287 | /* found the position (xc,yc) */
|
---|
288 |
|
---|
289 |
|
---|
290 | /* convert parsestr[] into a MM[][] structure */
|
---|
291 | for (j = 0; j < *h; j++)
|
---|
292 | {
|
---|
293 | foundstatus = 0;
|
---|
294 | for (i = 0; i < *w; i++)
|
---|
295 | {
|
---|
296 | p = j * (*w) + i;
|
---|
297 | if ((parsestr[p] == 'p') || (parsestr[p] == '2'))
|
---|
298 | {
|
---|
299 | if (!foundstatus)
|
---|
300 | foundstatus = 1;
|
---|
301 | MM2level[j] = MM2level[j] * 2 | (parsestr[p] == '2');
|
---|
302 | if (parsestr[p] == '2')
|
---|
303 | twolevel = 1;
|
---|
304 |
|
---|
305 | MM[j][MMcount[j]].x = i - xc;
|
---|
306 | MM[j][MMcount[j]++].y = j - yc;
|
---|
307 | if (((i - xc) >= 0) && ((j - yc) >= 0))
|
---|
308 | surr = 1;
|
---|
309 | }
|
---|
310 | else
|
---|
311 | {
|
---|
312 | if (foundstatus == 1)
|
---|
313 | foundstatus = 2;
|
---|
314 | }
|
---|
315 |
|
---|
316 | }
|
---|
317 | if (foundstatus)
|
---|
318 | MMrows++;
|
---|
319 | MMbits[j] = (1 << MMcount[j]) - 1;
|
---|
320 | }
|
---|
321 |
|
---|
322 | /* reverse matrix, so [][0] is the closest to the right */
|
---|
323 | {
|
---|
324 | coordinate temp;
|
---|
325 | for (i = 0; i < MMrows; i++)
|
---|
326 | for (j = 0; j < MMcount[i] / (unsigned) 2; j++)
|
---|
327 | {
|
---|
328 | temp = MM[i][MMcount[i] - 1 - j];
|
---|
329 | MM[i][MMcount[i] - 1 - j] = MM[i][j];
|
---|
330 | MM[i][j] = temp;
|
---|
331 | }
|
---|
332 | }
|
---|
333 | }
|
---|
334 |
|
---|
335 |
|
---|
336 |
|
---|
337 |
|
---|
338 |
|
---|
339 |
|
---|
340 |
|
---|
341 |
|
---|
342 | void
|
---|
343 | bl_writetemplate (char inputstr[])
|
---|
344 | {
|
---|
345 | register int i, j;
|
---|
346 | int w, h;
|
---|
347 | char ind[255];
|
---|
348 | char *str;
|
---|
349 |
|
---|
350 | str = (char *) malloc (strlen (inputstr) * sizeof (char) + 2);
|
---|
351 |
|
---|
352 | bl_string_to_array (inputstr, str, &w, &h);
|
---|
353 |
|
---|
354 | EncodeGammaDist (surr);
|
---|
355 | EncodeGammaDist (w);
|
---|
356 | EncodeGammaDist (h);
|
---|
357 | ind['.'] = 0;
|
---|
358 | ind['p'] = 1;
|
---|
359 | ind['2'] = 2;
|
---|
360 | ind['*'] = 3;
|
---|
361 | for (j = 0; j < h; j++)
|
---|
362 | for (i = 0; i < w; i++)
|
---|
363 | EncodeGammaDist (ind[(int) str[j * w + i]]);
|
---|
364 |
|
---|
365 | free (str);
|
---|
366 | }
|
---|
367 |
|
---|
368 |
|
---|
369 | void
|
---|
370 | bl_readtemplate ()
|
---|
371 | {
|
---|
372 | register int i, j;
|
---|
373 | int w, h, p;
|
---|
374 | char ind[4];
|
---|
375 | char *inputstr, *str;
|
---|
376 |
|
---|
377 | surr = DecodeGammaDist (surr);
|
---|
378 | if (surr)
|
---|
379 | {
|
---|
380 | fprintf (stderr, "It's fine compressing an image using a 'surrounding' template, but I can't "
|
---|
381 | "decompress it!\n");
|
---|
382 | exit (1);
|
---|
383 | }
|
---|
384 | w = DecodeGammaDist ();
|
---|
385 | h = DecodeGammaDist ();
|
---|
386 |
|
---|
387 | inputstr = (char *) malloc ((w + 2) * h * sizeof (char) + 2);
|
---|
388 | ind[0] = '.';
|
---|
389 | ind[1] = 'p';
|
---|
390 | ind[2] = '2';
|
---|
391 | ind[3] = '*';
|
---|
392 | for (p = 0, j = 0; j < h; j++)
|
---|
393 | {
|
---|
394 | for (i = 0; i < w; i++)
|
---|
395 | {
|
---|
396 | inputstr[p++] = ind[DecodeGammaDist ()];
|
---|
397 | }
|
---|
398 | inputstr[p++] = ';';
|
---|
399 | inputstr[p] = 0;
|
---|
400 | }
|
---|
401 |
|
---|
402 | str = (char *) malloc (strlen (inputstr) * sizeof (char) + 2);
|
---|
403 | bl_string_to_array (inputstr, str, &w, &h);
|
---|
404 | }
|
---|
405 |
|
---|
406 |
|
---|
407 |
|
---|
408 |
|
---|
409 |
|
---|
410 | /* Currently if there are more than 32 bits, the topmost 32 will be discarded, if the
|
---|
411 | topbits are to be used in compression, define _MORETHAN32 */
|
---|
412 | #undef _MORETHAN32
|
---|
413 |
|
---|
414 | void
|
---|
415 | bl_compress_mark (marktype d)
|
---|
416 | {
|
---|
417 | register int r, c;
|
---|
418 | register int i, j;
|
---|
419 | register unsigned long mask, mask2level;
|
---|
420 | char *array[MAX_T_W];
|
---|
421 |
|
---|
422 |
|
---|
423 | for (i = 0; i < MAX_T_W; i++)
|
---|
424 | {
|
---|
425 | array[i] = (char *) calloc ((size_t) d.w + 2 * MAX_T_W + 1, (size_t) sizeof (char));
|
---|
426 | array[i] = array[i] + MAX_T_W;
|
---|
427 | }
|
---|
428 |
|
---|
429 | EncodeGammaDist (d.w);
|
---|
430 | EncodeGammaDist (d.h);
|
---|
431 |
|
---|
432 | for (r = 0; r < min (curr_row, d.h); r++)
|
---|
433 | for (c = 0; c < d.w; c++)
|
---|
434 | array[r % MAX_T_W][c] = pbm_getpixel (d.bitmap, c, r);
|
---|
435 |
|
---|
436 | for (r = 0; r < d.h; r++)
|
---|
437 | {
|
---|
438 | if (V)
|
---|
439 | if (r && (r % 200 == 0))
|
---|
440 | fprintf (stderr, ".");
|
---|
441 |
|
---|
442 | if (r + curr_row < d.h)
|
---|
443 | for (c = 0; c < d.w; c++)
|
---|
444 | array[(r + curr_row) % MAX_T_W][c] = pbm_getpixel (d.bitmap, c, r + curr_row);
|
---|
445 | else
|
---|
446 | for (c = 0; c < d.w; c++)
|
---|
447 | array[(r + curr_row) % MAX_T_W][c] = 0;
|
---|
448 |
|
---|
449 | for (c = 0; c < d.w; c++)
|
---|
450 | {
|
---|
451 | for (mask = 0, mask2level = 0, i = 0; i < MMrows; i++)
|
---|
452 | {
|
---|
453 | if (c != 0)
|
---|
454 | {
|
---|
455 | MMmask[i] = (MMmask[i] * 2);
|
---|
456 | MMmask[i] |= array[(r + MM[i][0].y + MAX_T_W) % MAX_T_W][c + MM[i][0].x];
|
---|
457 | }
|
---|
458 | else
|
---|
459 | {
|
---|
460 | for (MMmask[i] = 0, j = MMcount[i] - 1; j >= 0; j--)
|
---|
461 | MMmask[i] = 2 * MMmask[i] | array[(r + MM[i][j].y + MAX_T_W) % MAX_T_W][c + MM[i][j].x];
|
---|
462 | }
|
---|
463 | MMmask[i] &= MMbits[i];
|
---|
464 | #ifdef _MORETHAN32
|
---|
465 | mask = ((mask * 8191) << MMcount[i]) | MMmask[i];
|
---|
466 | mask2level = ((mask2level * 499) << MMcount[i]) | (MMmask[i] & MM2level[i]);
|
---|
467 | #else
|
---|
468 | mask = (mask << MMcount[i]) | MMmask[i];
|
---|
469 | mask2level = (mask2level << MMcount[i]) | (MMmask[i] & MM2level[i]);
|
---|
470 | #endif
|
---|
471 | }
|
---|
472 |
|
---|
473 | mask = HASH (mask);
|
---|
474 | mask2level = HASH (mask2level);
|
---|
475 |
|
---|
476 | bl_encode_in_context (mask, mask2level, pbm_getpixel (d.bitmap, c, r));
|
---|
477 | }
|
---|
478 | }
|
---|
479 | for (i = 0; i < MAX_T_W; i++)
|
---|
480 | free (array[i] - MAX_T_W);
|
---|
481 | }
|
---|
482 |
|
---|
483 |
|
---|
484 |
|
---|
485 | void
|
---|
486 | bl_decompress_mark (marktype * d)
|
---|
487 | {
|
---|
488 | register int r, c;
|
---|
489 | register int i, j;
|
---|
490 | unsigned long pix;
|
---|
491 | register unsigned long mask, mask2level;
|
---|
492 | char *array[MAX_T_W];
|
---|
493 |
|
---|
494 |
|
---|
495 | d->w = DecodeGammaDist ();
|
---|
496 | d->h = DecodeGammaDist ();
|
---|
497 |
|
---|
498 | d->bitmap = pbm_allocarray (d->w, d->h);
|
---|
499 | for (i = 0; i < MAX_T_W; i++)
|
---|
500 | {
|
---|
501 | array[i] = (char *) calloc ((size_t) d->w + 2 * MAX_T_W + 1, (size_t) sizeof (char));
|
---|
502 | array[i] = array[i] + MAX_T_W;
|
---|
503 | }
|
---|
504 |
|
---|
505 | for (r = 0; r < d->h; r++)
|
---|
506 | {
|
---|
507 | if (V)
|
---|
508 | if (r && (r % 200 == 0))
|
---|
509 | fprintf (stderr, ".");
|
---|
510 | for (c = 0; c < d->w; c++)
|
---|
511 | array[r % MAX_T_W][c] = pbm_getpixel (d->bitmap, c, r);
|
---|
512 | for (c = 0; c < d->w; c++)
|
---|
513 | {
|
---|
514 | for (mask = 0, mask2level = 0, i = 0; i < MMrows; i++)
|
---|
515 | {
|
---|
516 | if (c != 0)
|
---|
517 | {
|
---|
518 | MMmask[i] = (MMmask[i] * 2);
|
---|
519 | MMmask[i] |= array[(r + MM[i][0].y + MAX_T_W) % MAX_T_W][c + MM[i][0].x];
|
---|
520 | }
|
---|
521 | else
|
---|
522 | {
|
---|
523 | for (MMmask[i] = 0, j = MMcount[i] - 1; j >= 0; j--) /* get all pixels */
|
---|
524 | MMmask[i] = 2 * MMmask[i] | array[(r + MM[i][j].y + MAX_T_W) % MAX_T_W][c + MM[i][j].x];
|
---|
525 | }
|
---|
526 | MMmask[i] &= MMbits[i];
|
---|
527 |
|
---|
528 | #ifdef _MORETHAN32
|
---|
529 | mask = ((mask * 8191) << MMcount[i]) | MMmask[i];
|
---|
530 | mask2level = ((mask2level * 499) << MMcount[i]) | (MMmask[i] & MM2level[i]);
|
---|
531 | #else
|
---|
532 | mask = (mask << MMcount[i]) | MMmask[i];
|
---|
533 | mask2level = (mask2level << MMcount[i]) | (MMmask[i] & MM2level[i]);
|
---|
534 | #endif
|
---|
535 | }
|
---|
536 |
|
---|
537 | mask = HASH (mask);
|
---|
538 | mask2level = HASH (mask2level);
|
---|
539 |
|
---|
540 | bl_decode_in_context (mask, mask2level, &pix);
|
---|
541 | if (pix)
|
---|
542 | {
|
---|
543 | pbm_putpixel (d->bitmap, c, r, pix);
|
---|
544 | array[r % MAX_T_W][c] = pix;
|
---|
545 | }
|
---|
546 | }
|
---|
547 | }
|
---|
548 | for (i = 0; i < MAX_T_W; i++)
|
---|
549 | free (array[i] - MAX_T_W);
|
---|
550 | }
|
---|
551 |
|
---|
552 |
|
---|
553 |
|
---|
554 | void
|
---|
555 | bl_compress (marktype d, char inputstr[])
|
---|
556 | {
|
---|
557 | bl_clearmodel ();
|
---|
558 | bl_writetemplate (inputstr);
|
---|
559 | bl_compress_mark (d);
|
---|
560 | bl_freemodel ();
|
---|
561 | }
|
---|
562 |
|
---|
563 |
|
---|
564 | void
|
---|
565 | bl_decompress (marktype * d)
|
---|
566 | {
|
---|
567 | bl_clearmodel ();
|
---|
568 | bl_readtemplate ();
|
---|
569 | bl_decompress_mark (d);
|
---|
570 | bl_freemodel ();
|
---|
571 | }
|
---|
572 |
|
---|
573 |
|
---|
574 |
|
---|
575 |
|
---|
576 |
|
---|
577 |
|
---|
578 | /*
|
---|
579 | The bitmap in d2, can be examined clairvoyantly. The ordering of the
|
---|
580 | params is therefore non-clairvoyant, and clairvoyant in that order.
|
---|
581 |
|
---|
582 | */
|
---|
583 | /*
|
---|
584 | coordinate M1[6]={ { 0,-2},
|
---|
585 | {-1,-1},{ 0,-1}, {1,-1},
|
---|
586 | {-2,0}, {-1, 0}};
|
---|
587 | };
|
---|
588 | coordinate M2[13]={ { 0,-2},
|
---|
589 | {-1,-1}, { 0,-1}, {1, -1},
|
---|
590 | {-2,0}, {-1, 0}, { 0, 0}, { 1, 0}, {2,0},
|
---|
591 | {-1, 1}, { 0, 1}, { 1, 1},
|
---|
592 | { 0, 2}
|
---|
593 | */
|
---|
594 |
|
---|
595 | coordinate M1[6] =
|
---|
596 | {
|
---|
597 | {0, -2},
|
---|
598 | {-2, 0},
|
---|
599 | {1, -1},
|
---|
600 | {-1, -1},
|
---|
601 | {0, -1},
|
---|
602 | {-1, 0}};
|
---|
603 | coordinate M2[13] =
|
---|
604 | {
|
---|
605 | {0, -2},
|
---|
606 | {1, -1},
|
---|
607 | {-2, 0},
|
---|
608 | {2, 0},
|
---|
609 | {-1, 1},
|
---|
610 | {1, 1},
|
---|
611 | {0, 2},
|
---|
612 | {-1, -1},
|
---|
613 | {0, -1},
|
---|
614 | {1, 0},
|
---|
615 | {-1, 0},
|
---|
616 | {0, 1},
|
---|
617 | {0, 0}
|
---|
618 | };
|
---|
619 | #define M1S 6
|
---|
620 | #define M1S_2level 3
|
---|
621 | #define M2S 13
|
---|
622 | #define M2S_2level 6
|
---|
623 |
|
---|
624 |
|
---|
625 | void
|
---|
626 | bl_clair_compress (marktype d1, marktype d2)
|
---|
627 | {
|
---|
628 | register int r, c;
|
---|
629 | register int i, j, n;
|
---|
630 | register unsigned long mask, mask2level = 0;
|
---|
631 | int cols, rows;
|
---|
632 | int gap;
|
---|
633 | Pixel **b1, **b2;
|
---|
634 |
|
---|
635 |
|
---|
636 | bl_clearmodel ();
|
---|
637 | twolevel = 1;
|
---|
638 |
|
---|
639 | b1 = d1.bitmap;
|
---|
640 | b2 = d2.bitmap;
|
---|
641 | cols = d1.w;
|
---|
642 | rows = d1.h;
|
---|
643 |
|
---|
644 | gap = max (50, rows / 10);
|
---|
645 |
|
---|
646 | EncodeGammaDist (cols);
|
---|
647 | EncodeGammaDist (rows);
|
---|
648 |
|
---|
649 | for (r = 0; r < rows; r++)
|
---|
650 | {
|
---|
651 | if (V)
|
---|
652 | if (!(r % gap))
|
---|
653 | fprintf (stderr, ".");
|
---|
654 | for (c = 0; c < cols; c++)
|
---|
655 | {
|
---|
656 |
|
---|
657 | mask = 0;
|
---|
658 | for (n = 0; n < M1S; n++)
|
---|
659 | {
|
---|
660 | i = c + M1[n].x;
|
---|
661 | j = r + M1[n].y;
|
---|
662 | mask = (2 * mask) | pbm_getpixel_trunc (b1, i, j, cols, rows);
|
---|
663 | }
|
---|
664 |
|
---|
665 | mask2level = mask & ((1 << M1S_2level) - 1);
|
---|
666 |
|
---|
667 | for (n = 0; n < M2S; n++)
|
---|
668 | {
|
---|
669 | i = c + M2[n].x;
|
---|
670 | j = r + M2[n].y;
|
---|
671 | mask = (2 * mask) | pbm_getpixel_trunc (b2, i, j, cols, rows);
|
---|
672 | }
|
---|
673 |
|
---|
674 | mask2level = (mask2level << M2S_2level) | (mask & ((1 << M2S_2level) - 1));
|
---|
675 |
|
---|
676 | bl_encode_in_context (mask, mask2level, pbm_getpixel (b1, c, r));
|
---|
677 |
|
---|
678 | }
|
---|
679 | }
|
---|
680 | if (V)
|
---|
681 | fprintf (stderr, "\n");
|
---|
682 | bl_freemodel ();
|
---|
683 | }
|
---|
684 |
|
---|
685 |
|
---|
686 | void
|
---|
687 | bl_clair_decompress (marktype d1, marktype d2)
|
---|
688 | {
|
---|
689 | register int r, c;
|
---|
690 | register int i, j, n;
|
---|
691 | register unsigned long mask, mask2level = 0;
|
---|
692 | unsigned long p;
|
---|
693 | int cols, rows;
|
---|
694 | int gap;
|
---|
695 | Pixel **b1, **b2;
|
---|
696 |
|
---|
697 | bl_clearmodel ();
|
---|
698 | twolevel = 1;
|
---|
699 |
|
---|
700 | b1 = d1.bitmap;
|
---|
701 | b2 = d2.bitmap;
|
---|
702 | cols = d1.w;
|
---|
703 | rows = d1.h;
|
---|
704 |
|
---|
705 | gap = max (50, rows / 10);
|
---|
706 |
|
---|
707 | i = DecodeGammaDist ();
|
---|
708 | j = DecodeGammaDist ();
|
---|
709 | if ((i != cols) || (j != rows))
|
---|
710 | error_msg ("bl_clair_decompress", "incorrect size of residue image", "");
|
---|
711 |
|
---|
712 | if (V)
|
---|
713 | fprintf (stderr, "cols=%d rows=%d\n", cols, rows);
|
---|
714 |
|
---|
715 | for (r = 0; r < rows; r++)
|
---|
716 | {
|
---|
717 | if (V)
|
---|
718 | if (!(r % gap))
|
---|
719 | fprintf (stderr, ".");
|
---|
720 | for (c = 0; c < cols; c++)
|
---|
721 | {
|
---|
722 | mask = 0;
|
---|
723 | for (n = 0; n < M1S; n++)
|
---|
724 | {
|
---|
725 | i = c + M1[n].x;
|
---|
726 | j = r + M1[n].y;
|
---|
727 | mask = (2 * mask) | pbm_getpixel_trunc (b1, i, j, cols, rows);
|
---|
728 | }
|
---|
729 | mask2level = mask & ((1 << M1S_2level) - 1);
|
---|
730 | for (n = 0; n < M2S; n++)
|
---|
731 | {
|
---|
732 | i = c + M2[n].x;
|
---|
733 | j = r + M2[n].y;
|
---|
734 | mask = (2 * mask) | pbm_getpixel_trunc (b2, i, j, cols, rows);
|
---|
735 | }
|
---|
736 | mask2level = (mask2level << M2S_2level) | (mask & ((1 << M2S_2level) - 1));
|
---|
737 |
|
---|
738 |
|
---|
739 | bl_decode_in_context (mask, mask2level, &p);
|
---|
740 | if (p)
|
---|
741 | pbm_putpixel (b1, c, r, 1);
|
---|
742 | }
|
---|
743 | }
|
---|
744 | if (V)
|
---|
745 | fprintf (stderr, "\n");
|
---|
746 | bl_freemodel ();
|
---|
747 | }
|
---|