From f0cd69968e5667b5ab1d00a3a78a54c6f8cffd5d Mon Sep 17 00:00:00 2001 From: Fritz Elfert Date: Sun, 3 Mar 2002 23:49:27 +0000 Subject: - Added bitmap conversion functions. - Updated printer class according to Protocol doc 1.15 --- lib/psibitmap.cpp | 223 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 lib/psibitmap.cpp (limited to 'lib/psibitmap.cpp') diff --git a/lib/psibitmap.cpp b/lib/psibitmap.cpp new file mode 100644 index 0000000..39c2c68 --- /dev/null +++ b/lib/psibitmap.cpp @@ -0,0 +1,223 @@ +/*-*-c++-*- + * $Id$ + * + * This file is part of plptools. + * + * Copyright (C) 1999-2001 Fritz Elfert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "psibitmap.h" + +void +encodeBitmap(int width, int height, getPixelFunction_t getPixel, bool /*rle*/, + bufferStore &out) { + bufferStore ib; + + ib.addDWord(0x00000028); // hdrlen + ib.addDWord(width); // xPixels + ib.addDWord(height); // yPixels + ib.addDWord(0); // xTwips (unspecified) + ib.addDWord(0); // yTwips (unspecified) + ib.addDWord(2); // bitsPerPixel + ib.addDWord(0); // unknown1 + ib.addDWord(0); // unknown2 + ib.addDWord(0); // RLEflag + + bufferStore rawBuf; + for (int y = 0; y < height; y++) { + int ov = 0; + int shift = 0; + int bc = 0; + + for (int x = 0; x < width; x++) { + int v = getPixel(x, y) / 85; + ov |= (v << shift); + if (shift == 6) { + rawBuf.addByte(ov); + bc++; + shift = 0; + ov = 0; + } else + shift += 2; + } + if (shift != 0) { + rawBuf.addByte(ov); + shift = 0; + ov = 0; + bc++; + } + while (bc % 4) { + rawBuf.addByte(0); + bc++; + } + } + +#if 1 + ib.addBuff(rawBuf); +#else + //TODO: RLE encoding + + int rawLen = rawBuf.getLen(); + int eqCount = 1; + int lastByte = rawBuf.getByte(0); + bufferStore diBuf; + + for (int i = 1; i <= rawLen; i++) { + int v; + if (i < rawLen) + v = rawBuf.getByte(i); + else + v = lastByte + 1; + if (v == lastByte) { + if (diBuf.getLen()) { + ib.addByte(0x100 - diBuf.getLen()); + ib.addBuff(diBuf); + diBuf.init(); + } + eqCount++; + if (eqCount > 0x7f) { + ib.addByte(0x7f); + ib.addByte(v); + eqCount = 1; + } + } else { + if (eqCount > 1) { + ib.addByte(eqCount); + ib.addByte(lastByte); + eqCount = 1; + } else { + diBuf.addByte(lastByte); + if ((diBuf.getLen() > 0x7f) || (i == rawLen)) { + ib.addByte(0x100 - diBuf.getLen()); + ib.addBuff(diBuf); + diBuf.init(); + } + } + } + lastByte = v; + } +#endif + + out.addDWord(ib.getLen() + 4); + out.addBuff(ib); +} + +#define splitByte(v) \ +do { \ + int j; \ + \ + if (x < bytesPerLine) \ + for (j = 0; j < pixelsPerByte; j++) { \ + if (j && ((oidx % xPixels) == 0)) \ + break; \ + else \ + if (oidx >= picsize) \ + return false; \ + else { \ + out.addByte((v & mask) * grayVal); \ + v >>= bitsPerPixel; \ + oidx++; \ + } \ + } \ + if (++x >= linelen) \ + x = 0; \ +} while (0) + +bool +decodeBitmap(const unsigned char *p, int &width, int &height, bufferStore &out) +{ + u_int32_t totlen = *((u_int32_t*)p); p += 4; + u_int32_t hdrlen = *((u_int32_t*)p); p += 4; + u_int32_t datlen = totlen - hdrlen; + u_int32_t xPixels = *((u_int32_t*)p); p += 4; + u_int32_t yPixels = *((u_int32_t*)p); p += 4; + u_int32_t xTwips = *((u_int32_t*)p); p += 4; + u_int32_t yTwips = *((u_int32_t*)p); p += 4; + u_int32_t bitsPerPixel = *((u_int32_t*)p); p += 4; + u_int32_t unknown1 = *((u_int32_t*)p); p += 4; + u_int32_t unknown2 = *((u_int32_t*)p); p += 4; + u_int32_t RLEflag = *((u_int32_t*)p); p += 4; + + width = xPixels; + height = yPixels; + + u_int32_t picsize = xPixels * yPixels; + u_int32_t linelen; + int pixelsPerByte = (8 / bitsPerPixel); + int nColors = 1 << bitsPerPixel; + int grayVal = 255 / (nColors - 1); + int bytesPerLine = (xPixels + pixelsPerByte - 1) / pixelsPerByte; + int mask = (bitsPerPixel << 1) - 1; + + int oidx = 0; + int x = 0; + int y = 0; + int offset = 0; + + if (RLEflag) { + int i = 0; + while (offset < datlen) { + unsigned char b = *(p + offset); + if (b >= 0x80) { + offset += 0x100 - b + 1; + i += 0x100 - b; + } else { + offset += 2; + i += b + 1; + } + } + linelen = i / yPixels; + offset = 0; + while (offset < datlen) { + unsigned char b = *(p + offset++); + if (b >= 0x80) { + for (i = 0; i < 0x100 - b; i++, offset++) { + if (offset >= datlen) + return false; // data corrupted + unsigned char b2 = *(p + offset); + splitByte(b2); + } + } else { + if (offset >= datlen) + return false; + else { + unsigned char b2 = *(p + offset); + unsigned char bs = b2; + for (i = 0; i <= b; i++) { + splitByte(b2); + b2 = bs; + } + } + offset++; + } + } + } else { + linelen = datlen / yPixels; + while (offset < datlen) { + unsigned char b = *(p + offset++); + splitByte(b); + } + } + return true; +} + +/* + * Local variables: + * c-basic-offset: 4 + * End: + */ -- cgit v1.2.3