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/Makefile.am | 7 +- lib/psibitmap.cpp | 223 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/psibitmap.h | 75 ++++++++++++++++++ lib/wprt.cc | 23 +++++- lib/wprt.h | 17 ++++- 5 files changed, 338 insertions(+), 7 deletions(-) create mode 100644 lib/psibitmap.cpp create mode 100644 lib/psibitmap.h (limited to 'lib') diff --git a/lib/Makefile.am b/lib/Makefile.am index 0451077..3e39af2 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,6 +1,8 @@ # $Id$ # INCLUDES += -I$(top_srcdir)/intl +CFLAGS += -D_REENTRANT +CXXFLAGS += -D_REENTRANT lib_LTLIBRARIES = libplp.la @@ -10,12 +12,13 @@ libplp_la_SOURCES = bufferarray.cc bufferstore.cc iowatch.cc ppsocket.cc \ rfsv16.cc rfsv32.cc rfsvfactory.cc log.cc rfsv.cc rpcs32.cc rpcs16.cc \ rpcs.cc rpcsfactory.cc psitime.cc Enum.cc plpdirent.cc wprt.cc \ rclip.cc siscomponentrecord.cpp sisfile.cpp sisfileheader.cpp \ - sisfilerecord.cpp sislangrecord.cpp sisreqrecord.cpp sistypes.cpp + sisfilerecord.cpp sislangrecord.cpp sisreqrecord.cpp sistypes.cpp \ + psibitmap.cpp pkginclude_HEADERS = bufferarray.h bufferstore.h iowatch.h ppsocket.h \ rfsv.h rfsv16.h rfsv32.h rfsvfactory.h log.h rpcs32.h rpcs16.h rpcs.h \ rpcsfactory.h psitime.h Enum.h plpdirent.h wprt.h plpintl.h rclip.h \ siscomponentrecord.h sisfile.h sisfileheader.h sisfilerecord.h \ - sislangrecord.h sisreqrecord.h sistypes.h + sislangrecord.h sisreqrecord.h sistypes.h psibitmap.h maintainer-clean-local: rm -f Makefile.in 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: + */ diff --git a/lib/psibitmap.h b/lib/psibitmap.h new file mode 100644 index 0000000..14383f8 --- /dev/null +++ b/lib/psibitmap.h @@ -0,0 +1,75 @@ +/*-*-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 + * + */ + +#ifndef _PSIBITMAP_H_ +#define _PSIBITMAP_H_ + +#include + +/** + * This function is used by encodeBitmap for retrieving image data. + * It must return a gray value between 0 and 255 where 0 is black and + * 255 is white. + * + * @param x The x coordinate of the pixel to get (0 = left) + * @param y The y coordinate of the pixel to get (0 = top) + */ +typedef int (*getPixelFunction_t)(int x, int y); + +/** + * Convert an image into a bitmap in Psion format. + * + * @param width The width of the image to convert. + * @param height The height of the image to convert. + * @param getPixel Pointer to a function for retrieving pixel values. + * @param rle Flag: Perform RLE compression (currently ignored). + * @param out Output buffer; gets filled with the Psion representation + * of the converted image. + */ +extern void +encodeBitmap(int width, int height, getPixelFunction_t getPixel, + bool rle, bufferStore &out); + +/** + * Convert a Psion bitmap to a 8bit/pixel grayscale image. + * + * @param p Pointer to an input buffer which contains the Psion-formatted + * bitmap to convert. Must start with a Psion bitmap header. + * @param width On return, the image width in pixels is returned here. + * @param height On return, the image height in pixels is returned here. + * @param out Buffer which gets filled with the raw image data. Each pixel + * is represented by a byte. The image data is organized in + * height scanlines of width bytes, starting with the topmost + * scanline. + * + * @returns true on success, false if input data is inconsistent. + */ +extern bool +decodeBitmap(const unsigned char *p, int &width, int &height, bufferStore &out); + +#endif // !_PSIBITMAP_H_ +/* + * Local variables: + * c-basic-offset: 4 + * End: + */ diff --git a/lib/wprt.cc b/lib/wprt.cc index bd87b8a..42d0308 100644 --- a/lib/wprt.cc +++ b/lib/wprt.cc @@ -98,7 +98,7 @@ sendCommand(enum commands cc, bufferStore & data) } bool result; bufferStore a; - a.addWord(cc); + a.addByte(cc); a.addBuff(data); result = skt->sendBufferStore(a); if (!result) { @@ -115,7 +115,8 @@ initPrinter() { Enum ret; bufferStore a; - a.addWord(0); + a.addByte(2); // Major printer version + a.addByte(0); // Minor printer version sendCommand(WPRT_INIT, a); if ((ret = getResponse(a)) != rfsv::E_PSI_GEN_NONE) cerr << "WPRT ERR:" << a << endl; @@ -131,14 +132,30 @@ initPrinter() { Enum wprt:: getData(bufferStore &buf) { Enum ret; - bufferStore a; sendCommand(WPRT_GET, buf); if ((ret = getResponse(buf)) != rfsv::E_PSI_GEN_NONE) + cerr << "WPRT ERR:" << buf << endl; + return ret; +} + +Enum wprt:: +cancelJob() { + Enum ret; + bufferStore a; + + sendCommand(WPRT_CANCEL, a); + if ((ret = getResponse(a)) != rfsv::E_PSI_GEN_NONE) cerr << "WPRT ERR:" << a << endl; return ret; } +bool wprt:: +stop() { + bufferStore a; + return sendCommand(WPRT_STOP, a); +} + Enum wprt:: getResponse(bufferStore & data) { diff --git a/lib/wprt.h b/lib/wprt.h index 54ca84b..755c2b9 100644 --- a/lib/wprt.h +++ b/lib/wprt.h @@ -75,13 +75,25 @@ public: */ Enum initPrinter(); + /** + * Cancels a running job. + */ + Enum cancelJob(); + + /** + * Stops the WPRT server. + */ + bool stop(); + protected: /** * The possible commands. */ enum commands { - WPRT_INIT = 0x0100, - WPRT_GET = 0xf0f0, + WPRT_INIT = 0x00, + WPRT_GET = 0xf0, + WPRT_CANCEL = 0xf1, + WPRT_STOP = 0xff, }; /** @@ -110,6 +122,7 @@ protected: * @returns true on success, false on failure. */ bool sendCommand(enum commands cc, bufferStore &data); + Enum getResponse(bufferStore &data); const char *getConnectName(); -- cgit v1.2.3