|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T d
Length: 14067 (0x36f3) Types: TextFile Names: »decode.c«
└─⟦3d0c2be1b⟧ Bits:30001254 ISODE-5.0 Tape └─⟦eba4602b1⟧ »./isode-5.0.tar.Z« └─⟦d3ac74d73⟧ └─⟦this⟧ »isode-5.0/others/quipu/photo/decode.c«
/* decode.c - the generic decoder */ #ifndef lint static char *rcsid = "$Header: /f/osi/others/quipu/photo/RCS/decode.c,v 6.0 89/03/18 23:34:01 mrose Rel $"; #endif /* * $Header: /f/osi/others/quipu/photo/RCS/decode.c,v 6.0 89/03/18 23:34:01 mrose Rel $ * * * $Log: decode.c,v $ * Revision 6.0 89/03/18 23:34:01 mrose * Release 5.0 * */ /* * NOTICE * * Acquisition, use, and distribution of this module and related * materials are subject to the restrictions of a license agreement. * Consult the Preface in the User's Manual for the full terms of * this agreement. * */ #include <stdio.h> #include <sgtty.h> #include <signal.h> #include "quipu/photo.h" #define ERR_RUN 0x0f #ifdef lint #define FAXDIR "/tmp" #endif /* this file contains the main routines for decoding X400 */ extern int PIC_LINESIZE,STOP,NUMLINES; /* variables for top of the code word trees */ node * bl_tree_top; node * wt_tree_top; node * two_tree_top; unsigned int position; static char ref_colour; static char colour; char * malloc (); char *bitmap; /* ROUTINE: Decode_t4 /* /* SYNOPSIS: Decodes a bit map stored in format T4 as recommended /* by CCITT. /* /* DESCRIPTION: After setting up the buffers, a line at a time is dealt with. /* Each line is recognised as being one or two dimensionally coded, depending /* upon the tag bit. /* The run change buffers for each line are kept incase the next line is two /* dimensionally, when it will be used as a reference. /* */ int decode_t4 (inbuf, winname, length) char *inbuf, *winname; int length; { bit_string code_line, /* output line */ ref_line, /* reference line */ t4_line; /* input line */ int done = 0; run_type run; int *buffer1, *buffer2; int *run_buf1, *run_buf2; if (photo_start (winname) == -1) return (-1); if (build_trees (FAXDIR) == -1) return (-1); buffer1 = (int *) malloc (LINEBUF * sizeof(int)); buffer2 = (int *) malloc (LINEBUF * sizeof(int)); buffer1[0] = 0; /* to halt backtracting if needed at start of line */ buffer2[0] = 0; run_buf1 = buffer1; run_buf2 = buffer2; ref_line.run_top = ++run_buf1; code_line.run_top = ++run_buf2; code_line.dbuf_top = malloc (BUFSIZ); t4_line.dbuf_top = inbuf; if (set_dinput (&t4_line, length) == -1) return (-1); set_doutput (&code_line); /* t4 starts with an initial end of line */ run = next_run(&t4_line,WHITE); if (run.r_type == ERR_RUN) return (-1); if (run.r_type != EOLN) { (void) fprintf (stderr,"PHOTO: Initial end of line missing"); return (-1); } if ( get_bit(&t4_line) != 1){ (void) fprintf (stderr,"PHOTO: Initial end of line (2) missing"); return (-1); } NUMLINES = -1; do { NUMLINES++; position = 1; if (get_bit(&t4_line) != 0) { if (code_line.run_top == run_buf1) { ref_line.run_top = run_buf1; code_line.run_top = run_buf2; } else { ref_line.run_top = run_buf2; code_line.run_top = run_buf1; } done = decode_two (&ref_line,&code_line,&t4_line); } else { code_line.run_pos = code_line.run_top; done = decode_one (&code_line,&t4_line); } if (done == -1) return (-1); flush_doutput (&code_line); set_doutput (&code_line); photo_line_end (&code_line); } while (! done); flush_doutput (&code_line); bitmap = code_line.dbuf_top; (void) free ( (char *)buffer1); (void) free ( (char *)buffer2); return (photo_end (winname)); } /* ROUTINE: next_run * * SYNOPSIS: Reads the next run length from the input file. * * DESCRIPTION: As each bit is read, it is used to move down the decode tree, * when a node is found that contains a value, the value is returned. * The code is assumed to be one dimensional. */ run_type next_run (lineptr,xcolour) bit_string * lineptr; char xcolour; { node * ptr; run_type result ; result.run_length = 0; if (xcolour == BLACK) { ptr = bl_tree_top; } else { ptr = wt_tree_top; } if (ptr == NULL) { (void) fprintf (stderr,"PHOTO: tree error"); result.r_type = ERR_RUN; return (result); } do { if (get_bit (lineptr) == 0) ptr = ptr->zero; else ptr = ptr->one; if (ptr == NULL) { /* it may be possible to recover from this in the future */ (void) fprintf (stderr,"PHOTO: Sequencing error (1)"); result.r_type = ERR_RUN; return (result); } } while (ptr->n_type == INTERNAL); /* if the above value was a make up code, now read the terminal code */ if (ptr->n_type == MAKE) { result.run_length = ptr->value; if (xcolour == BLACK) { ptr = bl_tree_top; } else { ptr = wt_tree_top; } if (ptr == NULL) { (void) fprintf (stderr,"PHOTO: tree error"); result.r_type = ERR_RUN; return (result); } do { if (get_bit (lineptr) == 0) { ptr = ptr->zero; } else { ptr = ptr->one; } if (ptr == NULL) { /* it may be possible to recover from this ! */ (void) fprintf (stderr,"PHOTO: Sequencing error (2)"); result.r_type = ERR_RUN; return (result); } } while (ptr->n_type == INTERNAL); } result.run_length += ptr->value; result.r_type = ptr->n_type; return (result); } /* ROUTINE: decode_one /* /* SYNOPSIS: decodes one line of t4. /* /* DESCRIPTION: reads a run, then writes that many bit of the appropiate /* colour to the output. */ decode_one (lineptr, t4_lineptr) bit_string * lineptr; bit_string * t4_lineptr; { run_type run; char xcolour = WHITE; int done; int savelinesize; savelinesize = PIC_LINESIZE; PIC_LINESIZE = 0; run = next_run (t4_lineptr,xcolour); if (run.r_type == ERR_RUN) return (-1); while (run.r_type != EOLN) { PIC_LINESIZE += run.run_length; put_run (lineptr,run.run_length,xcolour); xcolour = 1 - xcolour; run = next_run (t4_lineptr,xcolour); if (run.r_type == ERR_RUN) return (-1); } while (get_bit(t4_lineptr) != 01) ; /* skip fill characters */ if (lineptr->run_pos == lineptr->run_top){ done = 1; PIC_LINESIZE = savelinesize; } else done = 0; STOP = PIC_LINESIZE + 1; *(lineptr->run_pos++) = STOP; *(lineptr->run_pos) = STOP; return (done); } /* ROUTINE: decode_two /* /* SYNOPSIS: decodes a two dim line. /* /* DESCRIPTION: The binary codes read in are looked up in the decode tree, /* and the appropiate routine called to decode that mode. */ decode_two (ref_lineptr,code_lineptr,t4_lineptr) bit_string * ref_lineptr; bit_string * code_lineptr; bit_string * t4_lineptr; { node * ptr; int done; ref_lineptr->run_pos = ref_lineptr->run_top; code_lineptr->run_pos = code_lineptr->run_top; colour = WHITE; ref_colour = BLACK; do { ptr = two_tree_top; do { if (ptr == NULL) { (void) fprintf (stderr,"PHOTO: 2-d line failure"); return (-1); } if (get_bit (t4_lineptr) == 0) ptr = ptr->zero; else ptr = ptr->one; } while (ptr->n_type == INTERNAL); switch (ptr->value) { case P: undo_pass_mode (ref_lineptr,code_lineptr); break; case H: if (undo_horiz_mode (t4_lineptr,code_lineptr) == -1) return (-1); break; case EOLN: break; default: undo_vert_mode (ref_lineptr,code_lineptr,ptr->value); } } while (ptr->n_type != EOLN ); /* fill to end of line with current colour */ put_run (code_lineptr,(int)( PIC_LINESIZE - position + 1 ), colour); if (code_lineptr->run_pos == code_lineptr->run_top) /* no runs found */ done = 1; else done = 0; while (get_bit (t4_lineptr) != 1) ; /* skip fill characters */ *(code_lineptr->run_pos++) = STOP; *(code_lineptr->run_pos) = STOP; return (done); } /* ROUTINE: undo_pass_mode /* /* SYNOPSIS: decodes a section recognised as pass mode. /* /* DESCRIPTION: find b2, then write to output the same colour as before /* up until position b2. */ undo_pass_mode (ref_lineptr,code_lineptr) bit_string * ref_lineptr; bit_string * code_lineptr; { goto_b1 (ref_lineptr); ref_lineptr->run_pos++; ref_colour = 1 - ref_colour; put_run (code_lineptr,(int) (*(ref_lineptr->run_pos) - position), colour); code_lineptr->run_pos--; /* don't count this as a change */ } /* ROUTINE: undo_horiz_mode /* /* SYNOPSIS: decodes a section recognised as horizontal mode. /* /* DESCRIPTION: Read two run lengths for the input, and write the appropiate /* number of 1's or 0's to the output. */ undo_horiz_mode (t4_lineptr,code_lineptr) bit_string * t4_lineptr; bit_string * code_lineptr; { run_type run; run = next_run (t4_lineptr,colour); if (run.r_type == ERR_RUN) return (-1); put_run (code_lineptr,run.run_length,colour); run = next_run (t4_lineptr,1-colour); if (run.r_type == ERR_RUN) return (-1); put_run (code_lineptr,run.run_length,1-colour); return (0); } /* ROUTINE: undo_vert_mode /* /* SYNOPSIS: decodes vertical mode /* /* DESCRIPTION: Find b1, the write 1's or 0's upto it allowing for the offset. */ undo_vert_mode (ref_lineptr,code_lineptr,offset) bit_string * ref_lineptr; bit_string * code_lineptr; char offset; { int length; /* find b1 */ goto_b1 (ref_lineptr); length = (*ref_lineptr->run_pos - position) + offset - FIXED_OFFSET; put_run ( code_lineptr, length , colour); colour = 1 - colour; } /* ROUTINE: goto_b1 * * SYNOPSIS: move the pointer in the reference line to b1 * * DESCRIPTION: b1 is the first changing bit in the reference line * of a different colour to a0. May need to move backwards or forwards * */ goto_b1 (lineptr) bit_string * lineptr; { if ( *lineptr->run_pos > position ) do ref_colour = 1 - ref_colour; while ( *--lineptr->run_pos > position ) ; if ( *lineptr->run_pos < position ) do ref_colour = 1 - ref_colour; while ( *++lineptr->run_pos < position ) ; if (ref_colour == colour) { lineptr->run_pos++; ref_colour = 1 - ref_colour; } else /* special case when b1 = a0, and the colours are different, move b1 to the next change of same colour, this must be allowed at the beginning of a line to get a run of zero, as every line must start with a white element */ if ((*lineptr->run_pos == position) && (*lineptr->run_pos >1 )) { lineptr->run_pos++; lineptr->run_pos++; } } /* ROUTINE: put_run */ /* */ /* SYNOPSIS: writes a run_length to the indiacated bit_string, */ /* */ put_run (lineptr, length, xcolour) bit_string * lineptr; int length; char xcolour; { register i; if ( xcolour == WHITE) photo_white (length); else photo_black (length); /* now fill line buffer for purpose of decoding 2-d lines */ if (length > 16) { position += length; *lineptr->run_pos++ = position; if (lineptr->mask != BIT_MASK) { /* fill current byte */ if (xcolour == WHITE) do { clr_bit (lineptr); length--; } while (lineptr->mask != BIT_MASK); else do { set_bit (lineptr); length--; } while (lineptr->mask != BIT_MASK); } /* write out the bytes */ if (xcolour == WHITE) for (i=0; i<length/8; i++) *lineptr->dbuf++ = 0; else for (i=0; i<length/8; i++) *lineptr->dbuf++ = 0xff; /* put the last few bits into the next byte */ if (xcolour == WHITE) for (i=0; i<length%8; i++) clr_bit (lineptr); else for (i=0; i<length%8; i++) set_bit (lineptr); } else { /* length < 16 - can't optimise, so deal with bits */ if (xcolour == WHITE) { for (i=0; i<length; i++) clr_bit (lineptr); position += length; *lineptr->run_pos++ = position; } else { for (i=0; i<length; i++) set_bit (lineptr); position += length; *lineptr->run_pos++ = position; } } } /* ROUTINE: set_doutput; /* /* SYNOPSIS: Initialises the output buffers */ set_doutput (lineptr) bit_string * lineptr; { lineptr->dbuf = lineptr->dbuf_top; lineptr->mask = BIT_MASK; } /* ROUTINE: flush_doutput; /* /* SYNOPSIS: flush the output buffer; */ flush_doutput (lineptr) bit_string * lineptr; { int count = 0; while ( lineptr->mask != BIT_MASK ) { clr_bit (lineptr); count++; } photo_white (count); } /* ROUTINE: set_dinput; /* /* SYNOPSIS: Initialises the input buffers */ set_dinput (lineptr, length) bit_string * lineptr; int length; { bit_string temp; int i; lineptr->dbuf = lineptr->dbuf_top; if (length == 0) { /* check id + skip length */ if ( *lineptr->dbuf++ != 0x03 ) { (void) fprintf (stderr,"PHOTO: Not a g3fax bit map"); return (-1); } if ((length = piclen (lineptr->dbuf_top)) == -1) return (-1); } while ((lineptr->pos = *lineptr->dbuf++) != 0x00) ; /* no op */ temp.dbuf_top = lineptr->dbuf_top + length - 8; temp.dbuf = temp.dbuf_top; temp.mask = BIT_MASK; temp.pos = *temp.dbuf++; /* look for last eoln */ while (get_bit (&temp) != 1) ; for (i=0;i<12;i++) if (get_bit (&temp) == 1) { (void) fprintf (stderr,"PHOTO: last end of line missing"); return (-1); } if (get_bit (&temp) != 1) { (void) fprintf (stderr,"PHOTO: last end of line (2) missing"); return (-1); } lineptr->mask = BIT_MASK; return (0); } piclen (s1) char * s1; { int length=0,cnt,i; char * temp; if (*s1 == 0x03) { /* we have a coded picture */ temp = s1; temp++; cnt = *temp++ & 0x7f; /*assume len > 127 for now */ for (i=0; i<cnt; i++) length = (length << 8) | (*temp++ & 0xff) ; length += 2 + cnt; return (length); } else { (void) fprintf (stderr,"PHOTO: length error"); return (-1); } }