/************************************************\ File : CCITT4.C Usage : FAX CCITT Group 4 TIFF Format Author: Peter H. Michalicka \************************************************/ #include #include #include "tiff.h" #include "vma.h" #undef DEBUG #undef RUNDEB #undef BWDEB #define DEBUG_ON 0 #define DEBUG_OF 0 #define EOL -128 #define IsBit(c) (c & (1 << offset)) #define NotBit(c) ((c & (1 << offset)) == 0) #define IndOfs(p) p++, c = iob[(p >> 3)], offset = 7 - (p & 7) extern WorkFile t; extern IMAGE im; extern WORD rb[32767]; extern BYTE *iob; BYTE c; int ip; int offset; long cnt_lines; /* static vars */ static vma *vptr; static WORD BlackEnd; /* Width+1 */ static WORD MaxCol; /* Width+12 */ static WORD rb4[32767]; static WORD *rbcod, *rbref; static int maxref, ncod; static int refrun, bref, wref, is_start; static int a0, b1, b2, w1, w2; static char *msg_gr4 = "Can\'t read Group 4 format"; static char *msg_img = "Invalid Group 4 Image"; static char *br_fmt = "black run: %s"; static char *br_msg = "no start"; #ifdef ANSI int fillstrip(void); int put_buf(vma *v, int n, WORD *wp); #endif /* Code */ static int do_uncomp() /* got: 0000001xxx */ { /* check 111 */ fatal("Uncompressed not supported", NULL); } static void rlc_bw() { int i, n; for (i = *rbref, n = 2; i; i--) { rbref[n]++; /* change rlc black end to white */ n += 2; } } int ref_cod() { int i, j; WORD tmp, *tmp_rb;; #ifdef DEBUG if (is_start) fatal("Start Condition at: %s", "End Of Line"); #endif if (--ncod) /* subtract num_run_entry */ ncod >>= 1; /* determine run count */ #ifdef DEBUG if (cnt_lines >= DEBUG_ON && cnt_lines <= DEBUG_OF) printf("\nLine %d(%d): ", cnt_lines+1, ncod); #endif #ifdef RUNDEB if (cnt_lines >= DEBUG_ON && cnt_lines <= DEBUG_OF) { if (ncod) { j = ncod << 1; j++; for (i = 1; i < j; ) printf("%d,%d ", (int)rbcod[i++], (int)rbcod[i++]); } #ifdef BWDEB printf("\n"); #endif } #endif if (*rbref) { rlc_bw(); maxref = *rbref; maxref <<= 1; maxref++; put_buf(vptr, maxref, rbref); } else if (cnt_lines) put_buf(vptr, 1, rbref); tmp_rb = rbcod, rbcod = rbref, rbref = tmp_rb; if (ncod) { b1 = rbref[1]; b2 = rbref[2]; /* points allways to refrun+1 */ w1 = ++b2; wref = bref = 3; refrun = 1; *rbref = maxref = ncod; maxref <<= 1; maxref++; if (wref < maxref) w2 = rbref[wref++]; else w2 = BlackEnd; } else { w1 = w2 = b1 = b2 = BlackEnd; /* imaginary BlackEnd */ wref = bref = maxref = refrun = *rbref = 0; } is_start = FALSE; ncod = 1; a0 = 0; cnt_lines++; if (cnt_lines >= im.ImageLength) return 0; if (! (cnt_lines % im.RowsPerStrip)) { #ifdef DEBUG extern int max_strip; printf("\n bytes=%d (max=%d)fillstrip %d: ", ip >> 3, max_strip, cnt_lines); #endif fillstrip(); offset = 7; ip = 0; c = iob[0]; if ((c & 0x20)) { /* start line Horizontal Coded */ w1 = w2 = b1 = b2 = BlackEnd; /* imaginary BlackEnd */ wref = bref = maxref = refrun = 0; } } #ifdef DEBUG if (cnt_lines == 0) printf("Error "); #endif return 1; } static int do_white(allow) int allow; { int i = white_cw(); /* White follows Black */ IndOfs(ip); if (! a0) a0++; /* EIA 2.2.5 a) */ if (i > 63) { if (i >= 1792) { /* Additional make_up */ do { a0 += i; i = white_cw(); /* Add. White MakeUp */ IndOfs(ip); } while (i >= 1792); if (i > 63) { /* make_up -> Terminator follows */ i += white_cw(); /* White Terminator */ IndOfs(ip); } } else { /* Terminator follows */ i += white_cw(); /* White Terminator */ IndOfs(ip); } } #ifdef BWDEB if (cnt_lines >= DEBUG_ON && cnt_lines <= DEBUG_OF) printf("w(%d) ", i); #endif a0 += i; if (! is_start) { if (allow && a0 > im.ImageWidth) return ref_cod(); rbcod[ncod++] = a0; is_start = TRUE; } else fatal("white run: %s", "is start"); /* no align to BYTE boundary */ return 1; } static int do_black(allow) int allow; { int n; int i = black_cw(); /* Black follows White */ IndOfs(ip); if (i > 63) { if (i >= 1792) { /* Additional make_up */ n = 0; do { n += i; i = black_cw(); /* Add. Black MakeUp */ IndOfs(ip); } while (i >= 1792); if (i > 63) { /* make_up -> Terminator follows */ i += black_cw(); IndOfs(ip); } i += n; } else { /* Terminator follows */ i += black_cw(); /* Black Terminator */ IndOfs(ip); } } a0 += i; #ifdef BWDEB if (cnt_lines >= DEBUG_ON && cnt_lines <= DEBUG_OF) printf("b(%d) ", i); #endif if (is_start) { if (! i) ncod--; else rbcod[ncod++] = a0 - 1; /* CIS */ is_start = FALSE; if (allow && a0 > im.ImageWidth) return ref_cod(); } else { fatal(br_fmt, br_msg); } return 1; } static int vmode(dif) int dif; { #ifdef BWDEB if (cnt_lines >= DEBUG_ON && cnt_lines <= DEBUG_OF) printf("v(%d) ", dif); #endif if (is_start) { while (a0 >= w1) { if (wref >= maxref) { w1 = w2 = BlackEnd; break; } w1 = (int)rbref[wref++]; w1++; if (wref >= maxref) w2 = BlackEnd; else w2 = (int)rbref[wref++]; } is_start = FALSE; a0 = w1 + dif; rbcod[ncod++] = a0 - 1; /* CIS */ if (a0 > im.ImageWidth) return ref_cod(); } else { while (a0 >= b1) { if (bref >= maxref) { b1 = b2 = BlackEnd; break; } else { b1 = (int)rbref[bref++]; b2 = (int)rbref[bref++]; b2++; } } a0 = b1 + dif; if (a0 > im.ImageWidth) return ref_cod(); else { is_start = TRUE; rbcod[ncod++] = a0; } } return 1; } void dcgr4(v) vma *v; { int n; vptr = v; if (! fillstrip()) return; MaxCol = im.ImageWidth + 1; BlackEnd = im.ImageWidth + 1; /* Start DeCompression */ offset = 7; ip = 0; c = iob[ip]; /* ip default 0 */ rbcod = rb; rbref = rb4; w1 = w2 = b1 = b2 = BlackEnd; /* imaginary black end */ refrun = ncod = 1; a0 = 0; cnt_lines = is_start = *rbref = bref = wref = maxref = 0; /* defaults */ for(;;) { if (IsBit(c)) { IndOfs(ip); if (! vmode(0)) /* 1 .. a1 just under b1 */ break; } else { /* 0x */ IndOfs(ip); if (IsBit(c)) { /* 01x */ IndOfs(ip); if (IsBit(c)) { IndOfs(ip); n = vmode(1); /* 011 .. a1 = b1 + 1 */ } else { IndOfs(ip); n = vmode(-1); /* 010 .. a1 = b1 - 1 */ } if (! n) break; } else { /* 00x */ IndOfs(ip); if (IsBit(c)) { /* 001 .. Horz.CodeWORD */ IndOfs(ip); if (is_start) { /* Black */ if (! do_black(FALSE)) return; if (! do_white(TRUE)) return; } else { /* White */ if (! do_white(FALSE)) return; if (! do_black(TRUE)) return; } } else { /* 000x */ IndOfs(ip); if (IsBit(c)) { /* 0001 .. Pass CodeWORD */ #ifdef BWDEB if (cnt_lines >= DEBUG_ON && cnt_lines <= DEBUG_OF) printf("p "); #endif IndOfs(ip); if (! is_start) { while (a0 >= b1) { if (bref >= maxref) { b1 = b2 = BlackEnd; break; } else { b1 = (int)rbref[bref++]; b2 = (int)rbref[bref++]; b2++; } } a0 = b2; /* rule: b2 < a1 */ if (bref < maxref) { b1 = rbref[bref++]; b2 = rbref[bref++]; b2++; } else b1 = b2 = BlackEnd; } else { while (a0 >= w1) { if (wref >= maxref) { w1 = w2 = BlackEnd; break; } w1 = (int)rbref[wref++]; w1++; if (wref >= maxref) { w2 = BlackEnd; break; } else w2 = (int)rbref[wref++]; } a0 = w2; /* rule: b2 < a1 */ if (wref < maxref) { w1 = rbref[wref++]; w1++; } else w1 = BlackEnd; if (wref < maxref) w2 = rbref[wref++]; else w2 = BlackEnd; } if (a0 > im.ImageWidth) { is_start = FALSE; rbcod[ncod++] = im.ImageWidth; if (! ref_cod()) return; } } else { /* 0000x */ IndOfs(ip); if (IsBit(c)) { /* 00001x */ IndOfs(ip); if (IsBit(c)) { /* 000011 */ IndOfs(ip); n = vmode(2); /* a1 = b1 + 2 */ } else { /* 000010 */ IndOfs(ip); n = vmode(-2); /* a1 = b1 - 2 */ } if (! n) break; } else { /* 00000x */ IndOfs(ip); if (IsBit(c)) { /* 000001x */ IndOfs(ip); if (IsBit(c)) { /* 0000011 */ IndOfs(ip); n = vmode(3); /* a1 = b1 + 3 */ } else { /* 0000010 */ IndOfs(ip); n = vmode(-3); /* a1 = b1 - 3 */ } if (! n) break; } else { /* 000000x */ IndOfs(ip); if (IsBit(c)) do_uncomp(); /* 0000001xxx */ else { fatal(msg_gr4, NULL); } } } } } } } } }