📄 faxexpand.cpp
字号:
/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */#include <config.h>#include <stdlib.h>#include <stdio.h>#include <sys/types.h>#include "faxexpand.h"#include "kdebug.h"//Uncomment this for verbose debug output//#define DEBUG_FAX#define verbose falsepagenode::pagenode(){}/* 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 { \ BitAcc >>= (n); \ BitsAvail -= (n); \} while (0)#ifdef DEBUG_FAX#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)const 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 = a0 >= lastx; \ 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) \ kDebug() << "Line " << LineNum << ": extension code\n";\ SKIP_EOL; \ break; \ case S_EOL: \ *pa++ = lastx - a0; \ NeedBits(4); \ if (GetBits(4) && verbose) /* already seen 7 zeros */ \ kDebug() << "Line " << LineNum << ": Bad EOL\n"; \ 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(const char *what, int LineNum){ if (verbose) kError() << "Line " << LineNum << ": Unexpected state in " << what << endl;}/* Expand tiff modified huffman data (g3-1d without EOLs) */voidMHexpand(struct pagenode *pn, drawfunc df){ int a0; /* reference element */ int lastx; /* 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->size.width(); runs = (pixnum *) malloc(lastx * sizeof(pixnum)); for (LineNum = 0; LineNum < pn->rowsperstrip; ) {#ifdef DEBUG_FAX printf("\nBitAcc=%08lX, BitsAvail = %d\n", BitAcc, BitsAvail); printf("-------------------- %d\n", LineNum); fflush(stdout);#endif RunLength = 0; pa = runs;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -