faxexpand.c
来自「涉及Fax/Mail/Voice通讯编程的一个程序」· C语言 代码 · 共 730 行 · 第 1/2 页
C
730 行
/* Expand one page of fax data Copyright (C) 1990, 1995 Frank D. Cringle.This file is part of viewfax - g3/g4 fax processing software. viewfax is free software; you can redistribute it and/or modify itunder the terms of the GNU General Public License as published by theFree Software Foundation; either version 2 of the License, or (at youroption) any later version. This program is distributed in the hope that it will be useful, butWITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNUGeneral Public License for more details. You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <stdlib.h>#include <stdio.h>#include <sys/types.h>#include "faxexpand.h"/* Note that NeedBits() only works for n <= 16 */#define NeedBits(n) do { \ if (BitsAvail < (n)) { \ BitAcc |= *sp++ << BitsAvail; \ BitsAvail += 16; \ } \} while (0)#define GetBits(n) (BitAcc & ((1<<(n))-1))#define ClrBits(n) do { \ BitsAvail -= (n); \ BitAcc >>= (n); \} while (0)#ifdef DEBUG#define DEBUG_SHOW putchar(BitAcc & (1 << t) ? '1' : '0')#define LOOKUP(wid,tab) do { \ int t; \ NeedBits(wid); \ TabEnt = tab + GetBits(wid); \ printf("%08lX/%d: %s%5d\t", BitAcc, BitsAvail, \ StateNames[TabEnt->State], TabEnt->Param); \ for (t = 0; t < TabEnt->Width; t++) \ DEBUG_SHOW; \ putchar('\n'); \ fflush(stdout); \ ClrBits(TabEnt->Width); \} while (0)#define SETVAL(x) do { \ *pa++ = RunLength + (x); \ printf("SETVAL: %d\t%d\n", RunLength + (x), a0); \ a0 += x; \ RunLength = 0; \} while (0)char *StateNames[] = { "Null ", "Pass ", "Horiz ", "V0 ", "VR ", "VL ", "Ext ", "TermW ", "TermB ", "MakeUpW", "MakeUpB", "MakeUp ", "EOL ",};#else#define LOOKUP(wid,tab) do { \ NeedBits(wid); \ TabEnt = tab + GetBits(wid); \ ClrBits(TabEnt->Width); \} while (0)#define SETVAL(x) do { \ *pa++ = RunLength + (x); \ a0 += x; \ RunLength = 0; \} while (0)#endif#define dumpruns(runs) do { \ printf("-------------------- %d\n", LineNum); \ for (pa = runs, a0 = 0; a0 < lastx; a0 += *pa++) \ printf("%4d %d\n", a0, *pa); \} while (0)#define EndOfData(pn) (sp >= pn->data + pn->length/sizeof(*pn->data))/* This macro handles coding errors in G3 data. We redefine it below for the G4 case */#define SKIP_EOL do { \ while (!EndOfData(pn)) { \ NeedBits(11); \ if (GetBits(11) == 0) \ break; \ ClrBits(1); \ } \ ClrBits(11); \ goto EOL; \} while (0)#define eol2lab EOL2:/* the line expanders are written as macros so that they can be reused (twice each) but still have direct access to the local variables of the "calling" function */#define expand1d() do { \ while (a0 < lastx) { \ int done = 0; \ while (!done) { /* white first */ \ LOOKUP(12, WhiteTable); \ switch (TabEnt->State) { \ case S_EOL: \ EOLcnt = 1; \ goto EOL; \ case S_TermW: \ SETVAL(TabEnt->Param); \ done = 1; \ break; \ case S_MakeUpW: \ case S_MakeUp: \ a0 += TabEnt->Param; \ RunLength += TabEnt->Param; \ break; \ case S_Ext: \ unexpected("Extension code", LineNum); \ SKIP_EOL; \ break; \ default: \ unexpected("WhiteTable", LineNum); \ SKIP_EOL; \ break; \ } \ } \ done = 0; \ while (!done) { /* then black */ \ LOOKUP(13, BlackTable); \ switch (TabEnt->State) { \ case S_EOL: \ EOLcnt = 1; \ goto EOL; \ case S_TermB: \ SETVAL(TabEnt->Param); \ done = 1; \ break; \ case S_MakeUpB: \ case S_MakeUp: \ a0 += TabEnt->Param; \ RunLength += TabEnt->Param; \ break; \ case S_Ext: \ unexpected("Extension code", LineNum); \ SKIP_EOL; \ break; \ default: \ unexpected("BlackTable", LineNum); \ SKIP_EOL; \ break; \ } \ } \ } \ EOL: ; \} while (0)#define CHECK_b1 do { \ if (pa != thisrun) while (b1 <= a0 && b1 < lastx) { \ b1 += pb[0] + pb[1]; \ pb += 2; \ } \} while (0)#define expand2d(eolab) do { \ while (a0 < lastx) { \ LOOKUP(7, MainTable); \ switch (TabEnt->State) { \ case S_Pass: \ CHECK_b1; \ b1 += *pb++; \ RunLength += b1 - a0; \ a0 = b1; \ b1 += *pb++; \ break; \ case S_Horiz: \ if ((pa-run0)&1) { \ int done = 0; \ while (!done) { /* black first */ \ LOOKUP(13, BlackTable); \ switch (TabEnt->State) { \ case S_TermB: \ SETVAL(TabEnt->Param); \ done = 1; \ break; \ case S_MakeUpB: \ case S_MakeUp: \ a0 += TabEnt->Param; \ RunLength += TabEnt->Param; \ break; \ default: \ unexpected("BlackTable", LineNum); \ SKIP_EOL; \ break; \ } \ } \ done = 0; \ while (!done) { /* then white */ \ LOOKUP(12, WhiteTable); \ switch (TabEnt->State) { \ case S_TermW: \ SETVAL(TabEnt->Param); \ done = 1; \ break; \ case S_MakeUpW: \ case S_MakeUp: \ a0 += TabEnt->Param; \ RunLength += TabEnt->Param; \ break; \ default: \ unexpected("WhiteTable", LineNum); \ SKIP_EOL; \ break; \ } \ } \ } \ else { \ int done = 0; \ while (!done) { /* white first */ \ LOOKUP(12, WhiteTable); \ switch (TabEnt->State) { \ case S_TermW: \ SETVAL(TabEnt->Param); \ done = 1; \ break; \ case S_MakeUpW: \ case S_MakeUp: \ a0 += TabEnt->Param; \ RunLength += TabEnt->Param; \ break; \ default: \ unexpected("WhiteTable", LineNum); \ SKIP_EOL; \ break; \ } \ } \ done = 0; \ while (!done) { /* then black */ \ LOOKUP(13, BlackTable); \ switch (TabEnt->State) { \ case S_TermB: \ SETVAL(TabEnt->Param); \ done = 1; \ break; \ case S_MakeUpB: \ case S_MakeUp: \ a0 += TabEnt->Param; \ RunLength += TabEnt->Param; \ break; \ default: \ unexpected("BlackTable", LineNum); \ SKIP_EOL; \ break; \ } \ } \ } \ CHECK_b1; \ break; \ case S_V0: \ CHECK_b1; \ SETVAL(b1 - a0); \ b1 += *pb++; \ break; \ case S_VR: \ CHECK_b1; \ SETVAL(b1 - a0 + TabEnt->Param); \ b1 += *pb++; \ break; \ case S_VL: \ CHECK_b1; \ SETVAL(b1 - a0 - TabEnt->Param); \ b1 -= *--pb; \ break; \ case S_Ext: \ *pa++ = lastx - a0; \ if (verbose) \ fprintf(stderr, "Line %d: extension code\n", LineNum); \ SKIP_EOL; \ break; \ case S_EOL: \ *pa++ = lastx - a0; \ NeedBits(4); \ if (GetBits(4) && verbose) /* already seen 7 zeros */ \ fprintf(stderr, "Line %d: Bad EOL\n", LineNum); \ ClrBits(4); \ EOLcnt = 1; \ goto eolab; \ break; \ default: \ unexpected("MainTable", LineNum); \ SKIP_EOL; \ break; \ } \ } \ if (RunLength) { \ if (RunLength + a0 < lastx) { \ /* expect a final V0 */ \ NeedBits(1); \ if (!GetBits(1)) { \ unexpected("MainTable", LineNum); \ SKIP_EOL; \ } \ ClrBits(1); \ } \ SETVAL(0); \ } \ eol2lab ; \} while (0)static voidunexpected(char *what, int LineNum){ if (verbose) fprintf(stderr, "Line %d: Unexpected state in %s\n", LineNum, what);}/* Expand tiff modified huffman data (g3-1d without EOLs) */voidMHexpand(struct pagenode *pn, drawfunc df){ int a0; /* reference element */ int lastx = pn->width; /* copy line width to register */ t32bits BitAcc; /* bit accumulator */ int BitsAvail; /* # valid bits in BitAcc */ int RunLength; /* Length of current run */ t16bits *sp; /* pointer into compressed data */ pixnum *pa; /* pointer into new line */ int EOLcnt; /* number of consecutive EOLs */ int LineNum; /* line number */ pixnum *runs; /* list of run lengths */ struct tabent *TabEnt; sp = pn->data; BitAcc = 0; BitsAvail = 0; lastx = pn->width; runs = (pixnum *) xmalloc(lastx * sizeof(pixnum)); for (LineNum = 0; LineNum < pn->rowsperstrip; ) {#ifdef DEBUG printf("\nBitAcc=%08lX, BitsAvail = %d\n", BitAcc, BitsAvail); printf("-------------------- %d\n", LineNum); fflush(stdout);#endif RunLength = 0; pa = runs; a0 = 0; EOLcnt = 0; if (BitsAvail & ~8) /* skip to byte boundary */ ClrBits(BitsAvail & ~8);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?