|
|
1.1 root 1: /* decode.c - the generic decoder */
2:
3: #ifndef lint
4: static char *rcsid = "$Header: /f/osi/others/quipu/photo/RCS/decode.c,v 7.1 90/07/09 14:40:20 mrose Exp $";
5: #endif
6:
7: /*
8: * $Header: /f/osi/others/quipu/photo/RCS/decode.c,v 7.1 90/07/09 14:40:20 mrose Exp $
9: *
10: *
11: * $Log: decode.c,v $
12: * Revision 7.1 90/07/09 14:40:20 mrose
13: * sync
14: *
15: * Revision 7.0 89/11/23 22:01:37 mrose
16: * Release 6.0
17: *
18: */
19:
20: /*
21: * NOTICE
22: *
23: * Acquisition, use, and distribution of this module and related
24: * materials are subject to the restrictions of a license agreement.
25: * Consult the Preface in the User's Manual for the full terms of
26: * this agreement.
27: *
28: */
29:
30:
31:
32: #include <stdio.h>
33: #include <sgtty.h>
34: #include <signal.h>
35: #include "quipu/photo.h"
36:
37: #define ERR_RUN 0x0f
38:
39: #ifdef lint
40: #define FAXDIR "/tmp"
41: #endif
42:
43: /* this file contains the main routines for decoding X400 */
44:
45: extern int PIC_LINESIZE,STOP,NUMLINES;
46:
47: /* variables for top of the code word trees */
48: node * bl_tree_top;
49: node * wt_tree_top;
50: node * two_tree_top;
51:
52: unsigned int position;
53:
54: static char ref_colour;
55: static char colour;
56: char * malloc ();
57: char *bitmap;
58:
59: /* ROUTINE: Decode_t4
60: /*
61: /* SYNOPSIS: Decodes a bit map stored in format T4 as recommended
62: /* by CCITT.
63: /*
64: /* DESCRIPTION: After setting up the buffers, a line at a time is dealt with.
65: /* Each line is recognised as being one or two dimensionally coded, depending
66: /* upon the tag bit.
67: /* The run change buffers for each line are kept incase the next line is two
68: /* dimensionally, when it will be used as a reference.
69: /*
70: */
71:
72: int decode_t4 (inbuf, winname, length)
73: char *inbuf, *winname;
74: int length;
75: {
76: bit_string code_line, /* output line */
77: ref_line, /* reference line */
78: t4_line; /* input line */
79:
80: int done = 0;
81: run_type run;
82:
83: int *buffer1, *buffer2;
84: int *run_buf1, *run_buf2;
85: char tag,nextbit;
86:
87: if (photo_start (winname) == -1)
88: return (-1);
89:
90: if (build_trees (FAXDIR) == -1)
91: return (-1);
92:
93: buffer1 = (int *) malloc (LINEBUF * sizeof(int));
94: buffer2 = (int *) malloc (LINEBUF * sizeof(int));
95: buffer1[0] = 0; /* to halt backtracting if needed at start of line */
96: buffer2[0] = 0;
97: run_buf1 = buffer1;
98: run_buf2 = buffer2;
99: ref_line.run_top = ++run_buf1;
100: code_line.run_top = ++run_buf2;
101:
102: code_line.dbuf_top = malloc (BUFSIZ);
103: t4_line.dbuf_top = inbuf;
104:
105: if (set_dinput (&t4_line, length) == -1)
106: return (-1);
107: set_doutput (&code_line);
108:
109: /* t4 starts with an initial end of line */
110: run = next_run(&t4_line,WHITE);
111: if (run.r_type == ERR_RUN)
112: return (-1);
113: if (run.r_type != EOLN) {
114: (void) fprintf (stderr,"PHOTO: Initial end of line missing");
115: return (-1);
116: }
117: if ( get_bit(&t4_line) != 1){
118: (void) fprintf (stderr,"PHOTO: Initial end of line (2) missing");
119: return (-1);
120: }
121:
122: NUMLINES = -1;
123:
124: tag = nextbit = get_bit(&t4_line);
125:
126: do {
127: NUMLINES++;
128:
129: position = 1;
130: if (nextbit != tag )
131: { if (code_line.run_top == run_buf1)
132: { ref_line.run_top = run_buf1;
133: code_line.run_top = run_buf2;
134: }
135: else
136: { ref_line.run_top = run_buf2;
137: code_line.run_top = run_buf1;
138: }
139: done = decode_two (&ref_line,&code_line,&t4_line);
140: }
141: else
142: { code_line.run_pos = code_line.run_top;
143: done = decode_one (&code_line,&t4_line);
144: }
145:
146: if (done == -1)
147: return (-1);
148:
149: flush_doutput (&code_line);
150: set_doutput (&code_line);
151:
152: photo_line_end (&code_line);
153:
154: if (!done)
155: nextbit = get_bit(&t4_line);
156:
157: } while (! done);
158:
159: flush_doutput (&code_line);
160: bitmap = code_line.dbuf_top;
161:
162: (void) free ( (char *)buffer1);
163: (void) free ( (char *)buffer2);
164:
165: return (photo_end (winname));
166:
167: }
168:
169:
170:
171: /* ROUTINE: next_run
172: *
173: * SYNOPSIS: Reads the next run length from the input file.
174: *
175: * DESCRIPTION: As each bit is read, it is used to move down the decode tree,
176: * when a node is found that contains a value, the value is returned.
177: * The code is assumed to be one dimensional.
178: */
179:
180: run_type
181: next_run (lineptr,xcolour)
182: bit_string * lineptr;
183: char xcolour;
184: {
185:
186: node * ptr;
187: run_type result ;
188: result.run_length = 0;
189:
190: if (xcolour == BLACK) {
191: ptr = bl_tree_top;
192: } else {
193: ptr = wt_tree_top;
194: }
195:
196: if (ptr == NULL) {
197: (void) fprintf (stderr,"PHOTO: tree error");
198: result.r_type = ERR_RUN;
199: return (result);
200: }
201:
202: do {
203:
204: if (get_bit (lineptr) == 0)
205: ptr = ptr->zero;
206: else
207: ptr = ptr->one;
208:
209: if (ptr == NULL) {
210: /* it may be possible to recover from this in the future */
211: (void) fprintf (stderr,"PHOTO: Sequencing error (1)");
212: result.r_type = ERR_RUN;
213: return (result);
214: }
215:
216: } while (ptr->n_type == INTERNAL);
217:
218: /* if the above value was a make up code, now read the terminal code */
219: if (ptr->n_type == MAKE) {
220: result.run_length = ptr->value;
221: if (xcolour == BLACK) {
222: ptr = bl_tree_top;
223: } else {
224: ptr = wt_tree_top;
225: }
226:
227: if (ptr == NULL) {
228: (void) fprintf (stderr,"PHOTO: tree error");
229: result.r_type = ERR_RUN;
230: return (result);
231: }
232:
233: do {
234:
235: if (get_bit (lineptr) == 0) {
236: ptr = ptr->zero;
237: } else {
238: ptr = ptr->one;
239: }
240:
241: if (ptr == NULL) {
242: /* it may be possible to recover from this ! */
243: (void) fprintf (stderr,"PHOTO: Sequencing error (2)");
244: result.r_type = ERR_RUN;
245: return (result);
246: }
247: } while (ptr->n_type == INTERNAL);
248:
249: }
250:
251: result.run_length += ptr->value;
252: result.r_type = ptr->n_type;
253: return (result);
254:
255: }
256:
257:
258:
259: /* ROUTINE: decode_one
260: /*
261: /* SYNOPSIS: decodes one line of t4.
262: /*
263: /* DESCRIPTION: reads a run, then writes that many bit of the appropiate
264: /* colour to the output.
265: */
266:
267: decode_one (lineptr, t4_lineptr)
268: bit_string * lineptr;
269: bit_string * t4_lineptr;
270:
271: {
272: run_type run;
273: char xcolour = WHITE;
274: int done;
275: int savelinesize;
276:
277: savelinesize = PIC_LINESIZE;
278: PIC_LINESIZE = 0;
279: run = next_run (t4_lineptr,xcolour);
280: if (run.r_type == ERR_RUN)
281: return (-1);
282:
283: while (run.r_type != EOLN) {
284: PIC_LINESIZE += run.run_length;
285: put_run (lineptr,run.run_length,xcolour);
286: xcolour = 1 - xcolour;
287: run = next_run (t4_lineptr,xcolour);
288: if (run.r_type == ERR_RUN)
289: return (-1);
290: }
291: while (get_bit(t4_lineptr) != 01)
292: ; /* skip fill characters */
293:
294: if (lineptr->run_pos == lineptr->run_top){
295: done = 1;
296: PIC_LINESIZE = savelinesize;
297: } else
298: done = 0;
299:
300: STOP = PIC_LINESIZE + 1;
301: *(lineptr->run_pos++) = STOP;
302: *(lineptr->run_pos) = STOP;
303:
304: return (done);
305: }
306:
307:
308:
309: /* ROUTINE: decode_two
310: /*
311: /* SYNOPSIS: decodes a two dim line.
312: /*
313: /* DESCRIPTION: The binary codes read in are looked up in the decode tree,
314: /* and the appropiate routine called to decode that mode.
315: */
316:
317: decode_two (ref_lineptr,code_lineptr,t4_lineptr)
318:
319: bit_string * ref_lineptr;
320: bit_string * code_lineptr;
321: bit_string * t4_lineptr;
322:
323: {
324: node * ptr;
325: int done;
326:
327: ref_lineptr->run_pos = ref_lineptr->run_top;
328: code_lineptr->run_pos = code_lineptr->run_top;
329: colour = WHITE;
330: ref_colour = BLACK;
331: do {
332: ptr = two_tree_top;
333: do {
334: if (ptr == NULL) {
335: (void) fprintf (stderr,"PHOTO: 2-d line failure");
336: return (-1);
337: }
338:
339: if (get_bit (t4_lineptr) == 0)
340: ptr = ptr->zero;
341: else
342: ptr = ptr->one;
343: } while (ptr->n_type == INTERNAL);
344:
345: switch (ptr->value) {
346:
347: case P: undo_pass_mode (ref_lineptr,code_lineptr);
348: break;
349:
350: case H: if (undo_horiz_mode (t4_lineptr,code_lineptr) == -1)
351: return (-1);
352: break;
353:
354: case EOLN: break;
355:
356: default: undo_vert_mode (ref_lineptr,code_lineptr,ptr->value);
357:
358: }
359:
360: } while (ptr->n_type != EOLN );
361:
362: /* fill to end of line with current colour */
363: put_run (code_lineptr,(int)( PIC_LINESIZE - position + 1 ), colour);
364:
365: if (code_lineptr->run_pos == code_lineptr->run_top) /* no runs found */
366: done = 1;
367: else
368: done = 0;
369:
370: while (get_bit (t4_lineptr) != 1)
371: ; /* skip fill characters */
372:
373: *(code_lineptr->run_pos++) = STOP;
374: *(code_lineptr->run_pos) = STOP;
375:
376: return (done);
377: }
378:
379:
380: /* ROUTINE: undo_pass_mode
381: /*
382: /* SYNOPSIS: decodes a section recognised as pass mode.
383: /*
384: /* DESCRIPTION: find b2, then write to output the same colour as before
385: /* up until position b2.
386: */
387:
388: undo_pass_mode (ref_lineptr,code_lineptr)
389: bit_string * ref_lineptr;
390: bit_string * code_lineptr;
391:
392: {
393: goto_b1 (ref_lineptr);
394:
395: ref_lineptr->run_pos++;
396: ref_colour = 1 - ref_colour;
397:
398: put_run (code_lineptr,(int) (*(ref_lineptr->run_pos) - position), colour);
399: code_lineptr->run_pos--; /* don't count this as a change */
400: }
401:
402:
403:
404:
405: /* ROUTINE: undo_horiz_mode
406: /*
407: /* SYNOPSIS: decodes a section recognised as horizontal mode.
408: /*
409: /* DESCRIPTION: Read two run lengths for the input, and write the appropiate
410: /* number of 1's or 0's to the output.
411: */
412:
413: undo_horiz_mode (t4_lineptr,code_lineptr)
414:
415: bit_string * t4_lineptr;
416: bit_string * code_lineptr;
417:
418: {
419: run_type run;
420:
421: run = next_run (t4_lineptr,colour);
422: if (run.r_type == ERR_RUN)
423: return (-1);
424: put_run (code_lineptr,run.run_length,colour);
425:
426: run = next_run (t4_lineptr,1-colour);
427: if (run.r_type == ERR_RUN)
428: return (-1);
429: put_run (code_lineptr,run.run_length,1-colour);
430:
431: return (0);
432: }
433:
434:
435: /* ROUTINE: undo_vert_mode
436: /*
437: /* SYNOPSIS: decodes vertical mode
438: /*
439: /* DESCRIPTION: Find b1, the write 1's or 0's upto it allowing for the offset.
440: */
441:
442: undo_vert_mode (ref_lineptr,code_lineptr,offset)
443:
444: bit_string * ref_lineptr;
445: bit_string * code_lineptr;
446: char offset;
447:
448: {
449: int length;
450:
451: /* find b1 */
452: goto_b1 (ref_lineptr);
453:
454: length = (*ref_lineptr->run_pos - position) + offset - FIXED_OFFSET;
455: put_run ( code_lineptr, length , colour);
456: colour = 1 - colour;
457: }
458:
459: /* ROUTINE: goto_b1
460: *
461: * SYNOPSIS: move the pointer in the reference line to b1
462: *
463: * DESCRIPTION: b1 is the first changing bit in the reference line
464: * of a different colour to a0. May need to move backwards or forwards
465: *
466: */
467:
468: goto_b1 (lineptr)
469: bit_string * lineptr;
470:
471: {
472:
473: if ( *lineptr->run_pos > position )
474: do
475: ref_colour = 1 - ref_colour;
476: while ( *--lineptr->run_pos > position ) ;
477:
478: if ( *lineptr->run_pos < position )
479: do
480: ref_colour = 1 - ref_colour;
481: while ( *++lineptr->run_pos < position ) ;
482:
483: if (ref_colour == colour) {
484: lineptr->run_pos++;
485: ref_colour = 1 - ref_colour;
486:
487: } else
488: /* special case when b1 = a0, and the colours are different,
489: move b1 to the next change of same colour,
490: this must be allowed at the beginning of a line to get a run of
491: zero, as every line must start with a white element */
492: if ((*lineptr->run_pos == position) && (*lineptr->run_pos >1 )) {
493: lineptr->run_pos++;
494: lineptr->run_pos++;
495: }
496:
497: }
498:
499:
500: /* ROUTINE: put_run */
501: /* */
502: /* SYNOPSIS: writes a run_length to the indiacated bit_string, */
503: /* */
504:
505: put_run (lineptr, length, xcolour)
506: bit_string * lineptr;
507: int length;
508: char xcolour;
509: {
510: register i;
511:
512: if ( xcolour == WHITE)
513: photo_white (length);
514: else
515: photo_black (length);
516:
517: /* now fill line buffer for purpose of decoding 2-d lines */
518:
519: if (length > 16)
520: { position += length;
521: *lineptr->run_pos++ = position;
522:
523: if (lineptr->mask != BIT_MASK) { /* fill current byte */
524: if (xcolour == WHITE)
525: do {
526: clr_bit (lineptr);
527: length--;
528: } while (lineptr->mask != BIT_MASK);
529:
530: else
531: do {
532: set_bit (lineptr);
533: length--;
534: } while (lineptr->mask != BIT_MASK);
535: }
536:
537: /* write out the bytes */
538: if (xcolour == WHITE)
539: for (i=0; i<length/8; i++)
540: *lineptr->dbuf++ = 0;
541: else
542: for (i=0; i<length/8; i++)
543: *lineptr->dbuf++ = 0xff;
544:
545:
546: /* put the last few bits into the next byte */
547: if (xcolour == WHITE)
548: for (i=0; i<length%8; i++)
549: clr_bit (lineptr);
550: else
551: for (i=0; i<length%8; i++)
552: set_bit (lineptr);
553: }
554: else
555: { /* length < 16 - can't optimise, so deal with bits */
556:
557: if (xcolour == WHITE) {
558: for (i=0; i<length; i++) clr_bit (lineptr);
559: position += length;
560: *lineptr->run_pos++ = position;
561: } else {
562: for (i=0; i<length; i++)
563: set_bit (lineptr);
564: position += length;
565: *lineptr->run_pos++ = position;
566: }
567:
568: }
569:
570: }
571:
572: /* ROUTINE: set_doutput;
573: /*
574: /* SYNOPSIS: Initialises the output buffers
575: */
576:
577: set_doutput (lineptr)
578: bit_string * lineptr;
579: {
580: lineptr->dbuf = lineptr->dbuf_top;
581: lineptr->mask = BIT_MASK;
582: }
583:
584:
585:
586:
587: /* ROUTINE: flush_doutput;
588: /*
589: /* SYNOPSIS: flush the output buffer;
590: */
591:
592: flush_doutput (lineptr)
593: bit_string * lineptr;
594: {
595: int count = 0;
596:
597: while ( lineptr->mask != BIT_MASK ) {
598: clr_bit (lineptr);
599: count++;
600: }
601: photo_white (count);
602: }
603:
604:
605:
606: /* ROUTINE: set_dinput;
607: /*
608: /* SYNOPSIS: Initialises the input buffers
609: */
610:
611: set_dinput (lineptr, length)
612: bit_string * lineptr;
613: int length;
614: {
615: bit_string temp;
616: int i;
617:
618: lineptr->dbuf = lineptr->dbuf_top;
619:
620: if (length == 0) {
621: /* check id + skip length */
622: if ( *lineptr->dbuf++ != 0x03 ) {
623: (void) fprintf (stderr,"PHOTO: Not a g3fax bit map");
624: return (-1);
625: }
626:
627: if ((length = piclen (lineptr->dbuf_top)) == -1)
628: return (-1);
629: }
630:
631: while ((lineptr->pos = *lineptr->dbuf++) != 0x00)
632: ; /* no op */
633:
634: lineptr->mask = BIT_MASK;
635:
636: return (0);
637: }
638:
639: piclen (s1)
640: char * s1;
641: {
642: int length=0,cnt,i;
643: char * temp;
644:
645: if (*s1 == 0x03) {
646: /* we have a coded picture */
647:
648: temp = s1;
649: temp++;
650: cnt = *temp++ & 0x7f; /*assume len > 127 for now */
651: for (i=0; i<cnt; i++)
652: length = (length << 8) | (*temp++ & 0xff) ;
653:
654: length += 2 + cnt;
655: return (length);
656:
657: } else {
658: (void) fprintf (stderr,"PHOTO: length error");
659: return (-1);
660: }
661:
662: }
663:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.