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