/* $Xorg: efaxg42d.c,v 1.3 2000/08/17 19:46:41 cpqbld Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler * Copyright (c) 1991, 1992 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* $XFree86: xc/lib/lbxutil/image/efaxg42d.c,v 1.4 2001/01/17 19:43:35 dawes Exp $ */ #include #include #include #include "lbxfax.h" #include #include "lbxbwcodes.h" /* * ------------------------------------------------------------------------- * FAX G42D encoding for 1 bit images * ------------------------------------------------------------------------- */ static short sp_data, sp_bit; static tableentry horizcode = { 3, 0x1 }; /* 001 */ static tableentry passcode = { 4, 0x1 }; /* 0001 */ static tableentry vcodes[7] = { { 7, 0x03 }, /* 0000 011 */ { 6, 0x03 }, /* 0000 11 */ { 3, 0x03 }, /* 011 */ { 1, 0x1 }, /* 1 */ { 3, 0x2 }, /* 010 */ { 6, 0x02 }, /* 0000 10 */ { 7, 0x02 } /* 0000 010 */ }; typedef struct { unsigned char *bufStart; unsigned char *bufPtr; int bufSize; int bytesLeft; } Buffer; /* * Flush bits to output buffer. */ static int flushbits (Buffer *outbuf) { if (outbuf->bytesLeft > 0) { *(outbuf->bufPtr++) = sp_data; outbuf->bytesLeft--; sp_data = 0; sp_bit = 8; return (1); } else return (0); } /* * Write a variable-length bit-value to the output stream. Values are * assumed to be at most 16 bits. */ static int putbits (unsigned int bits, unsigned int length, Buffer *outbuf) { static int mask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; while (length > sp_bit) { sp_data |= bits >> (length - sp_bit); length -= sp_bit; if (!flushbits (outbuf)) return (0); } sp_data |= (bits & mask[length]) << (sp_bit - length); sp_bit -= length; if (sp_bit == 0) { if (!flushbits (outbuf)) return (0); } return (1); } /* * Write a code to the output stream. */ static int putcode (tableentry *te, Buffer *outbuf) { return (putbits (te->code, te->length, outbuf)); } /* * Write the sequence of codes that describes the specified span of * zero's or one's. The appropriate table that holds the make-up and * terminating codes is supplied. */ static int putspan (int span, tableentry *tab, Buffer *outbuf) { while (span >= 2624) { tableentry *te = &tab[63 + (2560 >> 6)]; if (!putcode (te, outbuf)) return (0); span -= te->runlen; } if (span >= 64) { tableentry *te = &tab[63 + (span >> 6)]; if (!putcode (te, outbuf)) return (0); span -= te->runlen; } if (!putcode (&tab[span], outbuf)) return (0); return (1); } #define PIXEL(buf,ix) ((((buf)[(ix)>>3]) >> (7-((ix)&7))) & 1) static int EncodeFaxG42D (unsigned char *inbuf, unsigned char *refline, int bits, Buffer *outbuf) { short white = 1; int a0 = 0; int a1 = (PIXEL (inbuf, 0) != white ? 0 : LbxImageFindDiff (inbuf, 0, bits, white)); int b1 = (PIXEL (refline, 0) != white ? 0 : LbxImageFindDiff (refline, 0, bits, white)); int a2, b2; for (;;) { b2 = LbxImageFindDiff (refline, b1, bits, PIXEL (refline, b1)); if (b2 >= a1) { int d = b1 - a1; if (!(-3 <= d && d <= 3)) { /* horizontal mode */ a2 = LbxImageFindDiff (inbuf, a1, bits, PIXEL (inbuf, a1)); if (!putcode (&horizcode, outbuf)) return (0); if (a0 + a1 == 0 || PIXEL (inbuf, a0) == white) { if (!putspan(a1 - a0, TIFFFaxWhiteCodes, outbuf)) return (0); if (!putspan(a2 - a1, TIFFFaxBlackCodes, outbuf)) return (0); } else { if (!putspan (a1 - a0, TIFFFaxBlackCodes, outbuf)) return (0); if (!putspan (a2 - a1, TIFFFaxWhiteCodes, outbuf)) return (0); } a0 = a2; } else { /* vertical mode */ if (!putcode (&vcodes[d+3], outbuf)) return (0); a0 = a1; } } else { /* pass mode */ if (!putcode (&passcode, outbuf)) return (0); a0 = b2; } if (a0 >= bits) break; a1 = LbxImageFindDiff (inbuf, a0, bits, PIXEL (inbuf, a0)); b1 = LbxImageFindDiff (refline, a0, bits, !PIXEL (inbuf, a0)); b1 = LbxImageFindDiff (refline, b1, bits, PIXEL (inbuf, a0)); } return (1); } int LbxImageEncodeFaxG42D (unsigned char *inbuf, unsigned char *outbuf, int outbufSize, int image_bytes, int pixels_per_line, int padded_bytes_per_scanline, int reverse_bits, int *bytesCompressed) { int bytes_per_scanline = ROUNDUP8 (pixels_per_line); unsigned char *refline, *refptr; unsigned char *save_inbuf = inbuf; int bytes_left = image_bytes; Buffer OutBuf; int status, i; OutBuf.bufStart = OutBuf.bufPtr = outbuf; OutBuf.bufSize = OutBuf.bytesLeft = outbufSize; if (!(refline = (unsigned char *) malloc (bytes_per_scanline + 1))) return (LBX_IMAGE_COMPRESS_BAD_MALLOC); refptr = refline + 1; for (i = 0; i < bytes_per_scanline + 1; i++) refline[i] = 0xff; if (reverse_bits) LbxReverseBits (inbuf, image_bytes); sp_bit = 8; sp_data = 0; while (bytes_left > 0) { if (!(status = EncodeFaxG42D (inbuf, refptr, pixels_per_line, &OutBuf))) { goto bad; } memcpy (refptr, inbuf, bytes_per_scanline); inbuf += padded_bytes_per_scanline; bytes_left -= padded_bytes_per_scanline; } status = putbits (EOL, 12, &OutBuf); if (status) status = putbits (EOL, 12, &OutBuf); if (status && sp_bit != 8) { status = flushbits (&OutBuf); } bad: free ((char *) refline); /* put the bits back the way they were */ if (reverse_bits) LbxReverseBits (save_inbuf, image_bytes); if (status) { *bytesCompressed = OutBuf.bufPtr - OutBuf.bufStart; if (OutBuf.bytesLeft > 0) return (LBX_IMAGE_COMPRESS_SUCCESS); else return (LBX_IMAGE_COMPRESS_NOT_WORTH_IT); } else return (LBX_IMAGE_COMPRESS_NOT_WORTH_IT); }