plptools
Loading...
Searching...
No Matches
psibitmap.cpp
Go to the documentation of this file.
1/*
2 * This file is part of plptools.
3 *
4 * Copyright (C) 1999-2001 Fritz Elfert <felfert@to.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * along with this program; if not, see <https://www.gnu.org/licenses/>.
18 *
19 */
20#include "config.h"
21
22#include <stdint.h>
23#include "psibitmap.h"
24
25void
26encodeBitmap(int width, int height, getPixelFunction_t getPixel, bool /*rle*/,
27 bufferStore &out) {
28 bufferStore ib;
29
30 ib.addDWord(0x00000028); // hdrlen
31 ib.addDWord(width); // xPixels
32 ib.addDWord(height); // yPixels
33 ib.addDWord(0); // xTwips (unspecified)
34 ib.addDWord(0); // yTwips (unspecified)
35 ib.addDWord(2); // bitsPerPixel
36 ib.addDWord(0); // unknown1
37 ib.addDWord(0); // unknown2
38 ib.addDWord(0); // RLEflag
39
40 bufferStore rawBuf;
41 for (int y = 0; y < height; y++) {
42 int ov = 0;
43 int shift = 0;
44 int bc = 0;
45
46 for (int x = 0; x < width; x++) {
47 int v = getPixel(x, y) / 85;
48 ov |= (v << shift);
49 if (shift == 6) {
50 rawBuf.addByte(ov);
51 bc++;
52 shift = 0;
53 ov = 0;
54 } else
55 shift += 2;
56 }
57 if (shift != 0) {
58 rawBuf.addByte(ov);
59 shift = 0;
60 ov = 0;
61 bc++;
62 }
63 while (bc % 4) {
64 rawBuf.addByte(0);
65 bc++;
66 }
67 }
68
69#if 1
70 ib.addBuff(rawBuf);
71#else
72 //TODO: RLE encoding
73
74 int rawLen = rawBuf.getLen();
75 int eqCount = 1;
76 int lastByte = rawBuf.getByte(0);
77 bufferStore diBuf;
78
79 for (int i = 1; i <= rawLen; i++) {
80 int v;
81 if (i < rawLen)
82 v = rawBuf.getByte(i);
83 else
84 v = lastByte + 1;
85 if (v == lastByte) {
86 if (diBuf.getLen()) {
87 ib.addByte(0x100 - diBuf.getLen());
88 ib.addBuff(diBuf);
89 diBuf.init();
90 }
91 eqCount++;
92 if (eqCount > 0x7f) {
93 ib.addByte(0x7f);
94 ib.addByte(v);
95 eqCount = 1;
96 }
97 } else {
98 if (eqCount > 1) {
99 ib.addByte(eqCount);
100 ib.addByte(lastByte);
101 eqCount = 1;
102 } else {
103 diBuf.addByte(lastByte);
104 if ((diBuf.getLen() > 0x7f) || (i == rawLen)) {
105 ib.addByte(0x100 - diBuf.getLen());
106 ib.addBuff(diBuf);
107 diBuf.init();
108 }
109 }
110 }
111 lastByte = v;
112 }
113#endif
114
115 out.addDWord(ib.getLen() + 4);
116 out.addBuff(ib);
117}
118
119#define splitByte(v) \
120do { \
121 int j; \
122 \
123 if (x < bytesPerLine) \
124 for (j = 0; j < pixelsPerByte; j++) { \
125 if (j && ((oidx % xPixels) == 0)) \
126 break; \
127 else \
128 if (oidx >= picsize) \
129 return false; \
130 else { \
131 out.addByte((v & mask) * grayVal); \
132 v >>= bitsPerPixel; \
133 oidx++; \
134 } \
135 } \
136 if (++x >= linelen) \
137 x = 0; \
138} while (0)
139
140bool
141decodeBitmap(const unsigned char *p, int &width, int &height, bufferStore &out)
142{
143 uint32_t totlen = *((const uint32_t*)p); p += 4;
144 uint32_t hdrlen = *((const uint32_t*)p); p += 4;
145 uint32_t datlen = totlen - hdrlen;
146 uint32_t xPixels = *((const uint32_t*)p); p += 4;
147 uint32_t yPixels = *((const uint32_t*)p); p += 4;
148 uint32_t xTwips = *((const uint32_t*)p); p += 4;
149 uint32_t yTwips = *((const uint32_t*)p); p += 4;
150 uint32_t bitsPerPixel = *((const uint32_t*)p); p += 4;
151 uint32_t unknown1 = *((const uint32_t*)p); p += 4;
152 uint32_t unknown2 = *((const uint32_t*)p); p += 4;
153 uint32_t RLEflag = *((const uint32_t*)p); p += 4;
154
155 width = xPixels;
156 height = yPixels;
157
158 uint32_t picsize = xPixels * yPixels;
159 uint32_t linelen;
160 int pixelsPerByte = (8 / bitsPerPixel);
161 int nColors = 1 << bitsPerPixel;
162 int grayVal = 255 / (nColors - 1);
163 int bytesPerLine = (xPixels + pixelsPerByte - 1) / pixelsPerByte;
164 int mask = (bitsPerPixel << 1) - 1;
165
166 int oidx = 0;
167 int x = 0;
168 int y = 0;
169 int offset = 0;
170
171 if (RLEflag) {
172 int i = 0;
173 while (offset < datlen) {
174 unsigned char b = *(p + offset);
175 if (b >= 0x80) {
176 offset += 0x100 - b + 1;
177 i += 0x100 - b;
178 } else {
179 offset += 2;
180 i += b + 1;
181 }
182 }
183 linelen = i / yPixels;
184 offset = 0;
185 while (offset < datlen) {
186 unsigned char b = *(p + offset++);
187 if (b >= 0x80) {
188 for (i = 0; i < 0x100 - b; i++, offset++) {
189 if (offset >= datlen)
190 return false; // data corrupted
191 unsigned char b2 = *(p + offset);
192 splitByte(b2);
193 }
194 } else {
195 if (offset >= datlen)
196 return false;
197 else {
198 unsigned char b2 = *(p + offset);
199 unsigned char bs = b2;
200 for (i = 0; i <= b; i++) {
201 splitByte(b2);
202 b2 = bs;
203 }
204 }
205 offset++;
206 }
207 }
208 } else {
209 linelen = datlen / yPixels;
210 while (offset < datlen) {
211 unsigned char b = *(p + offset++);
212 splitByte(b);
213 }
214 }
215 return true;
216}
A generic container for an array of bytes.
Definition: bufferstore.h:37
void init()
Initializes the bufferStore.
Definition: bufferstore.cc:77
void addBuff(const bufferStore &b, long maxLen=-1)
Appends data to the content of this instance.
Definition: bufferstore.cc:182
void addByte(unsigned char c)
Appends a byte to the content of this instance.
Definition: bufferstore.cc:159
void addDWord(long dw)
Appends a dword to the content of this instance.
Definition: bufferstore.cc:199
unsigned long getLen() const
Retrieves the length of a bufferStore.
Definition: bufferstore.cc:94
unsigned char getByte(long pos=0) const
Retrieves the byte at index pos.
Definition: bufferstore.cc:98
void encodeBitmap(int width, int height, getPixelFunction_t getPixel, bool, bufferStore &out)
Convert an image into a bitmap in Psion format.
Definition: psibitmap.cpp:26
#define splitByte(v)
Definition: psibitmap.cpp:119
bool decodeBitmap(const unsigned char *p, int &width, int &height, bufferStore &out)
Convert a Psion bitmap to a 8bit/pixel grayscale image.
Definition: psibitmap.cpp:141
int(* getPixelFunction_t)(int x, int y)
This function is used by encodeBitmap for retrieving image data.
Definition: psibitmap.h:34