source: main/tags/2.80/indexers/mg/src/images/mgtic.c@ 24539

Last change on this file since 24539 was 3745, checked in by mdewsnip, 21 years ago

Addition of MG package for search and retrieval

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 14.7 KB
Line 
1/**************************************************************************
2 *
3 * mgtic.c -- Program to compress/decompress textual images
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: mgtic.c 3745 2003-02-20 21:20:24Z mdewsnip $
21 *
22 **************************************************************************
23 *
24 * This file is the basis of mgtic, which compresses the components of an
25 * image.
26 * The compressed file contains the following sections:
27 * mgtic magic_no
28 * mgtic version
29 * lossy/lossless flag
30 * internal/external library flag
31 * cols, rows, number of marks, library size
32 * [library sequence]
33 * symbol sequence
34 * offset sequence
35 * [residue bitmap]
36 *
37 **************************************************************************/
38
39#include "sysfuncs.h"
40
41#include "marklist.h"
42#include "pbmtools.h"
43#include "extractor.h"
44#include "utils.h"
45#include "match.h"
46#include "sortmarks.h"
47#include "codesyms.h"
48#include "arithcode.h"
49#include "codeoffsets.h"
50#include "bilevel.h"
51
52static char library_template[] =
53{
54 ".ppppp.;"
55 "pp222pp;"
56 "p22222p;"
57 "p22*...;"
58};
59
60void
61usage ()
62{
63 fprintf (stderr, "usage: \n"
64 "\tmgtic -e [-L] [-Q] [-X] libraryfile infile [>compressed]\n"
65 "or\n"
66 "\tmgtic -d [-L] [-X libraryfile] compressed [>outfile]\n");
67 exit (1);
68}
69
70
71/* encode the list of marks 'list', w.r.t. the library 'library' */
72void
73match_sequence (marklistptr list, marklistptr library, marklistptr * symbol_list, Pixel ** recon, int quick)
74{
75 int carryx, carryy, gap;
76 int lastx = 0, lasty = 0;
77 int i, j;
78 marktype d, d2;
79 marklistptr liststep, librarystep;
80 int score, found;
81 int r, c;
82 int p;
83
84 carryx = carryy = 0;
85 gap = max (1, marklist_length (list) / 10);
86
87 for (liststep = list, i = 0; liststep; liststep = liststep->next, i++)
88 {
89 if (V)
90 if (!(i % gap))
91 fprintf (stderr, ".");
92 d = liststep->data;
93
94 found = -1;
95 score = INT_MAX;
96 for (librarystep = library, j = 0; librarystep; librarystep = librarystep->next, j++)
97 {
98 d2 = librarystep->data;
99
100 if (NOT_SCREENED (d2, d))
101 if ((p = MATCH (&d, &d2)) < MATCH_VAL)
102 {
103 if (p < score)
104 {
105 score = p;
106 found = j;
107 if (quick)
108 break;
109 }
110 }
111 }
112 /*
113 if(found<0){
114 for(librarystep=library,j=0; librarystep; librarystep=librarystep->next,j++){
115 d2=librarystep->data;
116
117 if((p=MATCH(&d,&d2))<MATCH_VAL){
118 if(p<score){
119 score=p;found=j; if(quick) break;
120 }
121 }
122 }
123 }
124 */
125 if (found >= 0)
126 {
127 liststep->data.symnum = found;
128 marklist_getat (library, found, &d2);
129 d2.symnum = found;
130
131 d2.xoffset = d.xpos - lastx + carryx; /* propagate changes to next mark */
132 d2.yoffset = d.ypos - lasty + carryy;
133 carryx = (d2.xcen - d.xcen); /* offet centroids because thats where we match them! */
134 carryy = (d2.ycen - d.ycen);
135 d2.xoffset -= carryx; /* make the changes to this mark */
136 d2.yoffset -= carryy;
137 lastx = d.xpos + d2.w;
138 lasty = d.ypos;
139
140 marklist_add (symbol_list, d2);
141
142 /* add to the reconstructed image--this is the lossy version */
143 for (r = 0; r < d2.h; r++)
144 for (c = 0; c < d2.w; c++)
145 if (pbm_getpixel (d2.bitmap, c, r))
146 pbm_putpixel_trunc (recon, d.xpos + c - carryx, d.ypos + r - carryy, 1, d2.w, d2.h);
147 }
148 else
149 {
150 /* didn't match at all..hopefully noise */
151 if ((liststep->data.w >= 10) || (liststep->data.w >= 10))
152 {
153 fprintf (stderr, "mgtic: warning, unable to match a char.\n");
154 write_library_mark (stderr, liststep->data);
155 }
156 if (V)
157 fprintf (stderr, "x");
158 liststep->data.symnum = -1;
159 }
160 }
161 if (V)
162 fprintf (stderr, "\n");
163}
164
165
166
167
168void
169main (int argc, char *args[])
170{
171 int i, n, r, c, ch;
172 FILE *inf;
173 marklistptr library = NULL, list = NULL, step = NULL;
174 marklistptr symbol_list = NULL;
175 marktype d, d2;
176 Pixel **bitmap, **recon, **bitmapcopy;
177 char *splitfilename = NULL;
178 int cols, rows, count, librarysize, lossy = 1;
179 int quick = 0;
180 int ticencode = 0, ticdecode = 0, external = 0;
181 char *libraryname = NULL, *infile = NULL;
182 char *s1 = NULL, *s2 = NULL;
183 char bufferin[BUFSIZ], bufferout[BUFSIZ];
184
185 if (argc < 2)
186 usage ();
187
188 while ((ch = getopt (argc, args, "edlLQhvXR:")) != -1)
189 switch (ch)
190 {
191 case 'e':
192 ticencode = 1;
193 break;
194 case 'd':
195 ticdecode = 1;
196 break;
197 case 'l':
198 lossy = 1;
199 break;
200 case 'L':
201 lossy = 0;
202 break;
203 case 'Q':
204 quick = 1;
205 break;
206 case 'v':
207 V = 1;
208 break;
209 case 'X':
210 external = 1;
211 break;
212 case 'R':
213 splitfilename = optarg;
214 break;
215 case 'h':
216 case '?':
217 usage ();
218 }
219
220 for (i = 1; i < argc; i++)
221 if (args[i][0] != '-')
222 if (strcmp (args[i - 1], "-R"))
223 { /* ignore arg following -R, ie. -R <filename> */
224 if (!s1)
225 s1 = args[i];
226 else if (!s2)
227 s2 = args[i];
228 else
229 error_msg (args[0], "too many filenames", "");
230 }
231
232 if (ticencode == ticdecode)
233 error_msg (args[0], "please specify either encode XOR decode", "");
234
235 if (ticencode)
236 {
237 /*****************
238 ENCODING STAGE
239 *****************/
240 long PrevBits = 0;
241 long BITS_header = 0, BITS_symbols = 0, BITS_offsets = 0, BITS_residue = 0,
242 BITS_footer = 0, BITS_library = 0;
243
244 libraryname = s1;
245 if (!libraryname)
246 error_msg (args[0], "please specify a library file", "");
247 infile = s2;
248 if (!infile)
249 error_msg (args[0], "please specify a file name", "");
250
251 inf = fopen (infile, "rb");
252 if (inf == NULL)
253 error_msg (args[0], "Trouble opening file:", infile);
254 setbuf (inf, bufferin);
255
256 count = librarysize = read_library (libraryname, &library);
257
258 if (V)
259 fprintf (stderr, "%s: processing...\n", args[0]);
260
261 if (pbm_isapbmfile (inf))
262 {
263 if (V)
264 fprintf (stderr, "reading file %s...\n", infile);
265 bitmap = pbm_readfile (inf, &cols, &rows);
266 fclose (inf);
267
268 bitmapcopy = pbm_copy (bitmap, cols, rows);
269
270 if (V)
271 fprintf (stderr, "extracting...");
272 ExtractAllMarks (bitmap, &list, cols, rows);
273 if (V)
274 fprintf (stderr, "(%d marks)\n", marklist_length (list));
275
276 /* sort into reading order */
277 if (V)
278 fprintf (stderr, "sorting...\n");
279 list = sortmarks (list);
280
281 pbm_freearray (&bitmap, rows); /* clear old version */
282 bitmap = bitmapcopy; /* point to the copy */
283 recon = pbm_allocarray (cols, rows);
284
285 if (V)
286 fprintf (stderr, "matching...");
287
288 match_sequence (list, library, &symbol_list, recon, quick);
289
290
291 PrevBits = 0;
292 setbuf (stdout, bufferout);
293 /* start output */
294 magic_write (stdout, MAGIC_TIC);
295 InitArithEncoding ();
296
297 EncodeGammaDist (1); /* version 1 of the program */
298 EncodeGammaDist (lossy); /* lossy=1 = no residue */
299 EncodeGammaDist (external); /* 1== external file */
300
301 count = marklist_length (symbol_list);
302 if (V)
303 fprintf (stderr, "encoding cols, rows, and number of symbols=%d\n", count);
304
305 EncodeGammaDist (cols);
306 EncodeGammaDist (rows);
307 EncodeGammaDist (count);
308 EncodeGammaDist (librarysize);
309
310 BITS_header = CountOfBitsOut - PrevBits;
311 PrevBits = CountOfBitsOut;
312
313
314 /* output the library sequence */
315 if (external == 0)
316 {
317 if (V)
318 fprintf (stderr, "encoding library\n");
319
320 bl_clearmodel ();
321 bl_writetemplate (library_template);
322 for (step = library; step; step = step->next)
323 bl_compress_mark (step->data);
324 bl_freemodel ();
325 BITS_library = CountOfBitsOut - PrevBits;
326 PrevBits = CountOfBitsOut;
327 }
328
329 /* output the symbol sequence */
330 if (V)
331 fprintf (stderr, "encoding symbol sequence\n");
332 InitPPM ();
333 EncodeSymbols (symbol_list, count);
334 BITS_symbols = CountOfBitsOut - PrevBits;
335 PrevBits = CountOfBitsOut;
336
337
338 /* output the offset sequence */
339 if (V)
340 fprintf (stderr, "encoding offset sequence\n");
341 EncodeOffsets (symbol_list, count);
342 BITS_offsets = CountOfBitsOut - PrevBits;
343 PrevBits = CountOfBitsOut;
344
345 EncodeChecksum (); /* code lossy checksum */
346
347 /* calculate the residue...and compress it---if need be! */
348 if (!lossy)
349 {
350 if (V)
351 fprintf (stderr, "encoding residue...\n");
352
353 d.bitmap = bitmap;
354 d.h = rows;
355 d.w = cols;
356 d2.bitmap = recon;
357 d2.h = rows;
358 d2.w = cols;
359
360 if (splitfilename)
361 {
362 FILE *temp;
363
364 CloseDownArithEncoding ();
365 fclose (stdout);
366 /* no residue result */
367 BITS_footer = CountOfBitsOut - PrevBits;
368
369 temp = fopen (splitfilename, "wb");
370 if (temp == NULL)
371 error_msg (args[0], "Trouble creating file:", splitfilename);
372
373 arith_out = temp;
374 InitArithEncoding ();
375 bl_clair_compress (d, d2);
376 CloseDownArithEncoding ();
377 BITS_residue = CountOfBitsOut;
378 fclose (temp);
379 }
380 else
381 {
382 bl_clair_compress (d, d2);
383 BITS_residue = CountOfBitsOut - PrevBits;
384 PrevBits = CountOfBitsOut;
385 EncodeChecksum (); /* code lossless checksum */
386 CloseDownArithEncoding ();
387 BITS_footer = CountOfBitsOut - PrevBits;
388 }
389 }
390 else
391 {
392 if (V)
393 fprintf (stderr, "not encoding residue..lossy mode\n");
394 CloseDownArithEncoding ();
395 BITS_footer = CountOfBitsOut - PrevBits;
396 }
397
398 /* because we edit the values above */
399 CountOfBitsOut = BITS_header + BITS_library + BITS_symbols + BITS_offsets + BITS_residue + BITS_footer;
400
401 fprintf (stderr, "bits: header=%ld, library=%ld, "
402 "symbols=%ld, offsets=%ld, residue=%ld, footer=%ld\n",
403 BITS_header, BITS_library, BITS_symbols,
404 BITS_offsets, BITS_residue, BITS_footer);
405 fprintf (stderr, "total bits: %ld, ", CountOfBitsOut);
406 fprintf (stderr, "Lossy CR: %4.2f", (cols * rows) / (float) (CountOfBitsOut - BITS_residue));
407 if (external)
408 fprintf (stderr, " (excluding external lib)");
409 fprintf (stderr, ", Lossless CR: %4.2f\n", (!lossy) * (cols * rows) / (float) (CountOfBitsOut));
410 }
411 else
412 error_msg (args[0], "unknown format of bitmap--expecting PBM.", "");
413 }
414 else
415 {
416 /*****************
417 DECODING STAGE
418 *****************/
419 int lastx, lasty;
420 librarysize = 0;
421
422 if (external)
423 {
424 libraryname = s1;
425 infile = s2;
426 count = librarysize = read_library (libraryname, &library);
427 }
428 else
429 {
430 infile = s1;
431 if (infile && s2)
432 error_msg (args[0], "too many filenames", "");
433 }
434
435 if (!freopen (infile, "rb", stdin))
436 error_msg (args[0], "Trouble opening file:", infile);
437
438
439 if (V)
440 fprintf (stderr, "decompressing...\n");
441
442 setbuf (stdin, bufferin);
443 magic_check (stdin, MAGIC_TIC);
444
445 InitArithDecoding ();
446
447 {
448 int version = DecodeGammaDist ();
449 if (version != 1)
450 error_msg (args[0], "Need later version of decompressor.", "");
451 }
452
453 {
454 int templossy = DecodeGammaDist ();
455 if (!lossy)
456 lossy = templossy; /* can only choose if encoded file is lossless */
457 if (V)
458 {
459 if (lossy)
460 fprintf (stderr, "lossy mode\n");
461 else
462 fprintf (stderr, "lossless mode\n");
463 }
464 }
465
466 if (DecodeGammaDist ())
467 { /* if compressed file doesn't contain library */
468 if (!external)
469 error_msg (args[0], "compressed file doesn't contain library, specify externally", "");
470 external = 1;
471 }
472 else
473 { /* if compressed file contains library */
474 if (external)
475 fprintf (stderr, "ignoring external library file\n");
476 external = 0;
477 }
478
479 cols = DecodeGammaDist ();
480 rows = DecodeGammaDist ();
481 count = DecodeGammaDist ();
482
483 i = DecodeGammaDist (); /* librarysize */
484 if (external)
485 {
486 if (i > librarysize)
487 error_msg (args[0], "external library file is too small!", "");
488 else if (i < librarysize)
489 fprintf (stderr, "%s: warning, expecting a different (smaller) library.\n", args[0]);
490 }
491 librarysize = i;
492
493 if (V)
494 fprintf (stderr, "cols %d, rows %d, num syms %d, library size %d\n", cols, rows, count, librarysize);
495
496 /* decode library */
497 if (external == 0)
498 {
499 if (V)
500 fprintf (stderr, "reading library\n");
501 bl_clearmodel ();
502 bl_readtemplate ();
503 for (n = 0; n < librarysize; n++)
504 {
505 bl_decompress_mark (&d);
506 d.symnum = n;
507 if (library == NULL)
508 step = marklist_add (&library, d);
509 else
510 step = marklist_add (&step, d);
511 }
512 bl_freemodel ();
513 if (V)
514 fprintf (stderr, "read %d marks from library\n", marklist_length (library));
515 }
516
517 recon = pbm_allocarray (cols, rows);
518
519 /* decode symbols */
520 InitPPM ();
521 if (V)
522 fprintf (stderr, "decompressing %d symbols\n", count);
523 symbol_list = DecodeSymbols (count);
524
525 /* decode offsets */
526 if (V)
527 fprintf (stderr, "reading offsets...\n");
528 DecodeOffsets (symbol_list, count);
529 lastx = lasty = 0;
530 for (step = symbol_list; step; step = step->next)
531 {
532 lastx = lastx + step->data.xoffset;
533 lasty = lasty + step->data.yoffset;
534
535 marklist_getat (library, step->data.symnum, &d2);
536 for (r = 0; r < d2.h; r++)
537 for (c = 0; c < d2.w; c++)
538 if (pbm_getpixel (d2.bitmap, c, r))
539 pbm_putpixel_trunc (recon, lastx + c, lasty + r, 1, cols, rows); /* we don't care, already warned them! */
540 lastx += d2.w;
541 }
542
543 DecodeChecksum (args[0]);
544
545 /* decode the residue */
546 if (!lossy)
547 {
548 if (V)
549 fprintf (stderr, "decoding residue...\n");
550
551 bitmap = pbm_allocarray (cols, rows);
552 d.bitmap = bitmap;
553 d.w = d2.w = cols;
554 d.h = d2.h = rows;
555
556 d2.bitmap = recon;
557
558 /* NOTE: the 2nd argument is clairvoyantly compressed */
559 if (splitfilename)
560 {
561 FILE *temp;
562
563 CloseDownArithDecoding ();
564 fclose (stdin);
565
566 temp = fopen (splitfilename, "rb");
567 if (temp == NULL)
568 error_msg (args[0], "Trouble opening file:", splitfilename);
569
570 arith_in = temp;
571 InitArithDecoding ();
572 bl_clair_decompress (d, d2);
573 CloseDownArithDecoding ();
574 fclose (temp);
575 }
576 else
577 {
578 bl_clair_decompress (d, d2);
579 DecodeChecksum (args[0]);
580 CloseDownArithDecoding ();
581 }
582 pbm_freearray (&recon, rows);
583 recon = bitmap; /* point to the bitmap */
584 }
585 else
586 {
587 CloseDownArithDecoding ();
588 }
589
590 if (V)
591 fprintf (stderr, "writing pbm file...\n");
592 setbuf (stdout, bufferout);
593 pbm_writefile (stdout, recon, cols, rows);
594 pbm_freearray (&recon, rows);
595 } /* end decoding */
596}
Note: See TracBrowser for help on using the repository browser.