Diffstat (limited to 'noncore/apps/opie-reader/Palm2QImage.cpp') (more/less context) (show whitespace changes)
-rw-r--r-- | noncore/apps/opie-reader/Palm2QImage.cpp | 290 |
1 files changed, 290 insertions, 0 deletions
diff --git a/noncore/apps/opie-reader/Palm2QImage.cpp b/noncore/apps/opie-reader/Palm2QImage.cpp new file mode 100644 index 0000000..ef88cc5 --- a/dev/null +++ b/noncore/apps/opie-reader/Palm2QImage.cpp | |||
@@ -0,0 +1,290 @@ | |||
1 | /* -*- mode: c; indent-tabs-mode: nil; -*- */ | ||
2 | #include <stdio.h> | ||
3 | #include <stdlib.h> | ||
4 | #include <string.h> | ||
5 | #include <unistd.h> /* for link */ | ||
6 | #include <sys/types.h> | ||
7 | #include <sys/stat.h> | ||
8 | #include <stdarg.h> | ||
9 | |||
10 | #include <qimage.h> | ||
11 | |||
12 | /***********************************************************************/ | ||
13 | /***********************************************************************/ | ||
14 | /***** *****/ | ||
15 | /***** Code to decode the Palm image format to JPEG *****/ | ||
16 | /***** *****/ | ||
17 | /***********************************************************************/ | ||
18 | /***********************************************************************/ | ||
19 | |||
20 | #define READ_BIGENDIAN_SHORT(p) (((p)[0] << 8)|((p)[1])) | ||
21 | #define READ_BIGENDIAN_LONG(p) (((p)[0] << 24)|((p)[1] << 16)|((p)[2] << 8)|((p)[3])) | ||
22 | |||
23 | #define PALM_IS_COMPRESSED_FLAG 0x8000 | ||
24 | #define PALM_HAS_COLORMAP_FLAG 0x4000 | ||
25 | #define PALM_HAS_TRANSPARENCY_FLAG 0x2000 | ||
26 | #define PALM_DIRECT_COLOR_FLAG 0x0400 | ||
27 | #define PALM_4_BYTE_FIELD_FLAG 0x0200 | ||
28 | |||
29 | #define PALM_COMPRESSION_SCANLINE 0x00 | ||
30 | #define PALM_COMPRESSION_RLE 0x01 | ||
31 | #define PALM_COMPRESSION_PACKBITS 0x02 | ||
32 | #define PALM_COMPRESSION_NONE 0xFF | ||
33 | |||
34 | #define PALM_COLORMAP_SIZE 232 | ||
35 | |||
36 | typedef struct { | ||
37 | unsigned char red; | ||
38 | unsigned char green; | ||
39 | unsigned char blue; | ||
40 | } ColorMapEntry; | ||
41 | |||
42 | static ColorMapEntry Palm8BitColormap[] = { | ||
43 | { 255, 255, 255 }, { 255, 204, 255 }, { 255, 153, 255 }, { 255, 102, 255 }, | ||
44 | { 255, 51, 255 }, { 255, 0, 255 }, { 255, 255, 204 }, { 255, 204, 204 }, | ||
45 | { 255, 153, 204 }, { 255, 102, 204 }, { 255, 51, 204 }, { 255, 0, 204 }, | ||
46 | { 255, 255, 153 }, { 255, 204, 153 }, { 255, 153, 153 }, { 255, 102, 153 }, | ||
47 | { 255, 51, 153 }, { 255, 0, 153 }, { 204, 255, 255 }, { 204, 204, 255 }, | ||
48 | { 204, 153, 255 }, { 204, 102, 255 }, { 204, 51, 255 }, { 204, 0, 255 }, | ||
49 | { 204, 255, 204 }, { 204, 204, 204 }, { 204, 153, 204 }, { 204, 102, 204 }, | ||
50 | { 204, 51, 204 }, { 204, 0, 204 }, { 204, 255, 153 }, { 204, 204, 153 }, | ||
51 | { 204, 153, 153 }, { 204, 102, 153 }, { 204, 51, 153 }, { 204, 0, 153 }, | ||
52 | { 153, 255, 255 }, { 153, 204, 255 }, { 153, 153, 255 }, { 153, 102, 255 }, | ||
53 | { 153, 51, 255 }, { 153, 0, 255 }, { 153, 255, 204 }, { 153, 204, 204 }, | ||
54 | { 153, 153, 204 }, { 153, 102, 204 }, { 153, 51, 204 }, { 153, 0, 204 }, | ||
55 | { 153, 255, 153 }, { 153, 204, 153 }, { 153, 153, 153 }, { 153, 102, 153 }, | ||
56 | { 153, 51, 153 }, { 153, 0, 153 }, { 102, 255, 255 }, { 102, 204, 255 }, | ||
57 | { 102, 153, 255 }, { 102, 102, 255 }, { 102, 51, 255 }, { 102, 0, 255 }, | ||
58 | { 102, 255, 204 }, { 102, 204, 204 }, { 102, 153, 204 }, { 102, 102, 204 }, | ||
59 | { 102, 51, 204 }, { 102, 0, 204 }, { 102, 255, 153 }, { 102, 204, 153 }, | ||
60 | { 102, 153, 153 }, { 102, 102, 153 }, { 102, 51, 153 }, { 102, 0, 153 }, | ||
61 | { 51, 255, 255 }, { 51, 204, 255 }, { 51, 153, 255 }, { 51, 102, 255 }, | ||
62 | { 51, 51, 255 }, { 51, 0, 255 }, { 51, 255, 204 }, { 51, 204, 204 }, | ||
63 | { 51, 153, 204 }, { 51, 102, 204 }, { 51, 51, 204 }, { 51, 0, 204 }, | ||
64 | { 51, 255, 153 }, { 51, 204, 153 }, { 51, 153, 153 }, { 51, 102, 153 }, | ||
65 | { 51, 51, 153 }, { 51, 0, 153 }, { 0, 255, 255 }, { 0, 204, 255 }, | ||
66 | { 0, 153, 255 }, { 0, 102, 255 }, { 0, 51, 255 }, { 0, 0, 255 }, | ||
67 | { 0, 255, 204 }, { 0, 204, 204 }, { 0, 153, 204 }, { 0, 102, 204 }, | ||
68 | { 0, 51, 204 }, { 0, 0, 204 }, { 0, 255, 153 }, { 0, 204, 153 }, | ||
69 | { 0, 153, 153 }, { 0, 102, 153 }, { 0, 51, 153 }, { 0, 0, 153 }, | ||
70 | { 255, 255, 102 }, { 255, 204, 102 }, { 255, 153, 102 }, { 255, 102, 102 }, | ||
71 | { 255, 51, 102 }, { 255, 0, 102 }, { 255, 255, 51 }, { 255, 204, 51 }, | ||
72 | { 255, 153, 51 }, { 255, 102, 51 }, { 255, 51, 51 }, { 255, 0, 51 }, | ||
73 | { 255, 255, 0 }, { 255, 204, 0 }, { 255, 153, 0 }, { 255, 102, 0 }, | ||
74 | { 255, 51, 0 }, { 255, 0, 0 }, { 204, 255, 102 }, { 204, 204, 102 }, | ||
75 | { 204, 153, 102 }, { 204, 102, 102 }, { 204, 51, 102 }, { 204, 0, 102 }, | ||
76 | { 204, 255, 51 }, { 204, 204, 51 }, { 204, 153, 51 }, { 204, 102, 51 }, | ||
77 | { 204, 51, 51 }, { 204, 0, 51 }, { 204, 255, 0 }, { 204, 204, 0 }, | ||
78 | { 204, 153, 0 }, { 204, 102, 0 }, { 204, 51, 0 }, { 204, 0, 0 }, | ||
79 | { 153, 255, 102 }, { 153, 204, 102 }, { 153, 153, 102 }, { 153, 102, 102 }, | ||
80 | { 153, 51, 102 }, { 153, 0, 102 }, { 153, 255, 51 }, { 153, 204, 51 }, | ||
81 | { 153, 153, 51 }, { 153, 102, 51 }, { 153, 51, 51 }, { 153, 0, 51 }, | ||
82 | { 153, 255, 0 }, { 153, 204, 0 }, { 153, 153, 0 }, { 153, 102, 0 }, | ||
83 | { 153, 51, 0 }, { 153, 0, 0 }, { 102, 255, 102 }, { 102, 204, 102 }, | ||
84 | { 102, 153, 102 }, { 102, 102, 102 }, { 102, 51, 102 }, { 102, 0, 102 }, | ||
85 | { 102, 255, 51 }, { 102, 204, 51 }, { 102, 153, 51 }, { 102, 102, 51 }, | ||
86 | { 102, 51, 51 }, { 102, 0, 51 }, { 102, 255, 0 }, { 102, 204, 0 }, | ||
87 | { 102, 153, 0 }, { 102, 102, 0 }, { 102, 51, 0 }, { 102, 0, 0 }, | ||
88 | { 51, 255, 102 }, { 51, 204, 102 }, { 51, 153, 102 }, { 51, 102, 102 }, | ||
89 | { 51, 51, 102 }, { 51, 0, 102 }, { 51, 255, 51 }, { 51, 204, 51 }, | ||
90 | { 51, 153, 51 }, { 51, 102, 51 }, { 51, 51, 51 }, { 51, 0, 51 }, | ||
91 | { 51, 255, 0 }, { 51, 204, 0 }, { 51, 153, 0 }, { 51, 102, 0 }, | ||
92 | { 51, 51, 0 }, { 51, 0, 0 }, { 0, 255, 102 }, { 0, 204, 102 }, | ||
93 | { 0, 153, 102 }, { 0, 102, 102 }, { 0, 51, 102 }, { 0, 0, 102 }, | ||
94 | { 0, 255, 51 }, { 0, 204, 51 }, { 0, 153, 51 }, { 0, 102, 51 }, | ||
95 | { 0, 51, 51 }, { 0, 0, 51 }, { 0, 255, 0 }, { 0, 204, 0 }, | ||
96 | { 0, 153, 0 }, { 0, 102, 0 }, { 0, 51, 0 }, { 17, 17, 17 }, | ||
97 | { 34, 34, 34 }, { 68, 68, 68 }, { 85, 85, 85 }, { 119, 119, 119 }, | ||
98 | { 136, 136, 136 }, { 170, 170, 170 }, { 187, 187, 187 }, { 221, 221, 221 }, | ||
99 | { 238, 238, 238 }, { 192, 192, 192 }, { 128, 0, 0 }, { 128, 0, 128 }, | ||
100 | { 0, 128, 0 }, { 0, 128, 128 }, { 0, 0, 0 }, { 0, 0, 0 }, | ||
101 | { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, | ||
102 | { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, | ||
103 | { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, | ||
104 | { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, | ||
105 | { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, | ||
106 | { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }}; | ||
107 | |||
108 | static ColorMapEntry Palm1BitColormap[] = {{ 255, 255, 255 }, { 0, 0, 0 }}; | ||
109 | |||
110 | static ColorMapEntry Palm2BitColormap[] = { | ||
111 | { 255, 255, 255 }, { 192, 192, 192 }, { 128, 128, 128 }, { 0, 0, 0 }}; | ||
112 | |||
113 | static ColorMapEntry Palm4BitColormap[] = { | ||
114 | { 255, 255, 255 }, { 238, 238, 238 }, { 221, 221, 221 }, { 204, 204, 204 }, | ||
115 | { 187, 187, 187 }, { 170, 170, 170 }, { 153, 153, 153 }, { 136, 136, 136 }, | ||
116 | { 119, 119, 119 }, { 102, 102, 102 }, { 85, 85, 85 }, { 68, 68, 68 }, | ||
117 | { 51, 51, 51 }, { 34, 34, 34 }, { 17, 17, 17 }, { 0, 0, 0 }}; | ||
118 | |||
119 | QImage* Palm2QImage | ||
120 | (unsigned char *image_bytes_in, int byte_count_in) | ||
121 | { | ||
122 | unsigned int width, height, bytes_per_row, flags, next_depth_offset; | ||
123 | unsigned int bits_per_pixel, version, transparent_index, compression_type, i, j, inval, inbit, mask, incount; | ||
124 | unsigned int palm_red_bits, palm_green_bits, palm_blue_bits; | ||
125 | unsigned char *palm_ptr, *x_ptr, *imagedata, *inbyte, *rowbuf, *lastrow, | ||
126 | *imagedatastart, *palmimage; | ||
127 | ColorMapEntry *colormap; | ||
128 | |||
129 | palmimage = image_bytes_in; | ||
130 | width = READ_BIGENDIAN_SHORT(palmimage + 0); | ||
131 | height = READ_BIGENDIAN_SHORT(palmimage + 2); | ||
132 | bytes_per_row = READ_BIGENDIAN_SHORT(palmimage + 4); | ||
133 | flags = READ_BIGENDIAN_SHORT(palmimage + 6); | ||
134 | bits_per_pixel = palmimage[8]; | ||
135 | version = palmimage[9]; | ||
136 | next_depth_offset = READ_BIGENDIAN_SHORT(palmimage + 10); | ||
137 | transparent_index = palmimage[12]; | ||
138 | compression_type = palmimage[13]; | ||
139 | /* bytes 14 and 15 are reserved by Palm and always 0 */ | ||
140 | |||
141 | #if 0 | ||
142 | qDebug ("Palm image is %dx%d, %d bpp, version %d, flags 0x%x, compression %d", | ||
143 | width, height, bits_per_pixel, version, flags, compression_type); | ||
144 | #endif | ||
145 | |||
146 | if (compression_type == PALM_COMPRESSION_PACKBITS) { | ||
147 | qDebug ("Image uses packbits compression; not yet supported"); | ||
148 | return NULL; | ||
149 | } else if ((compression_type != PALM_COMPRESSION_NONE) && | ||
150 | (compression_type != PALM_COMPRESSION_RLE) && | ||
151 | (compression_type != PALM_COMPRESSION_SCANLINE)) { | ||
152 | qDebug ("Image uses unknown compression, code 0x%x", compression_type); | ||
153 | return NULL; | ||
154 | } | ||
155 | |||
156 | /* as of PalmOS 4.0, there are 6 different kinds of Palm pixmaps: | ||
157 | |||
158 | 1, 2, or 4 bit grayscale | ||
159 | 8-bit StaticColor using the Palm standard colormap | ||
160 | 8-bit PseudoColor using a user-specified colormap | ||
161 | 16-bit DirectColor using 5 bits for red, 6 for green, and 5 for blue | ||
162 | |||
163 | Each of these can be compressed with one of four compression schemes, | ||
164 | "RLE", "Scanline", "PackBits", or none. | ||
165 | |||
166 | We begin by constructing the colormap. | ||
167 | */ | ||
168 | |||
169 | if (flags & PALM_HAS_COLORMAP_FLAG) { | ||
170 | qDebug("Palm images with custom colormaps are not currently supported.\n"); | ||
171 | return NULL; | ||
172 | } else if (bits_per_pixel == 1) { | ||
173 | colormap = Palm1BitColormap; | ||
174 | imagedatastart = palmimage + 16; | ||
175 | } else if (bits_per_pixel == 2) { | ||
176 | colormap = Palm2BitColormap; | ||
177 | imagedatastart = palmimage + 16; | ||
178 | } else if (bits_per_pixel == 4) { | ||
179 | colormap = Palm4BitColormap; | ||
180 | imagedatastart = palmimage + 16; | ||
181 | } else if (bits_per_pixel == 8) { | ||
182 | colormap = Palm8BitColormap; | ||
183 | imagedatastart = palmimage + 16; | ||
184 | } else if (bits_per_pixel == 16 && (flags & PALM_DIRECT_COLOR_FLAG)) { | ||
185 | colormap = NULL; | ||
186 | palm_red_bits = palmimage[16]; | ||
187 | palm_green_bits = palmimage[17]; | ||
188 | palm_blue_bits = palmimage[18]; | ||
189 | if (palm_blue_bits > 8 || palm_green_bits > 8 || palm_red_bits > 8) { | ||
190 | qDebug("Can't handle this format DirectColor image -- too wide in some color (%d:%d:%d)\n", | ||
191 | palm_red_bits, palm_green_bits, palm_blue_bits); | ||
192 | return NULL; | ||
193 | } | ||
194 | if (bits_per_pixel > (8 * sizeof(unsigned long))) { | ||
195 | qDebug ("Can't handle this format DirectColor image -- too many bits per pixel (%d)\n", | ||
196 | bits_per_pixel); | ||
197 | return NULL; | ||
198 | } | ||
199 | imagedatastart = palmimage + 24; | ||
200 | } else { | ||
201 | qDebug("Unknown bits-per-pixel of %d encountered.\n", bits_per_pixel); | ||
202 | return NULL; | ||
203 | } | ||
204 | |||
205 | QImage* qimage = new QImage(width, height, 16); | ||
206 | |||
207 | /* row by row, uncompress the Palm image and copy it to the JPEG buffer */ | ||
208 | rowbuf = new unsigned char[bytes_per_row * width]; | ||
209 | lastrow = new unsigned char[bytes_per_row * width]; | ||
210 | |||
211 | for (i=0, palm_ptr = imagedatastart , x_ptr = imagedata; i < height; ++i) { | ||
212 | |||
213 | /* first, uncompress the Palm image */ | ||
214 | if ((flags & PALM_IS_COMPRESSED_FLAG) && (compression_type == PALM_COMPRESSION_RLE)) { | ||
215 | for (j = 0; j < bytes_per_row; ) { | ||
216 | incount = *palm_ptr++; | ||
217 | inval = *palm_ptr++; | ||
218 | memset(rowbuf + j, inval, incount); | ||
219 | j += incount; | ||
220 | } | ||
221 | } else if ((flags & PALM_IS_COMPRESSED_FLAG) && (compression_type == PALM_COMPRESSION_SCANLINE)) { | ||
222 | for (j = 0; j < bytes_per_row; j += 8) { | ||
223 | incount = *palm_ptr++; | ||
224 | inval = ((bytes_per_row - j) < 8) ? (bytes_per_row - j) : 8; | ||
225 | for (inbit = 0; inbit < inval; inbit += 1) { | ||
226 | if (incount & (1 << (7 - inbit))) | ||
227 | rowbuf[j + inbit] = *palm_ptr++; | ||
228 | else | ||
229 | rowbuf[j + inbit] = lastrow[j + inbit]; | ||
230 | } | ||
231 | } | ||
232 | memcpy (lastrow, rowbuf, bytes_per_row); | ||
233 | } else if (((flags & PALM_IS_COMPRESSED_FLAG) && | ||
234 | (compression_type == PALM_COMPRESSION_NONE)) || | ||
235 | (flags && PALM_IS_COMPRESSED_FLAG) == 0) { | ||
236 | memcpy (rowbuf, palm_ptr, bytes_per_row); | ||
237 | palm_ptr += bytes_per_row; | ||
238 | } | ||
239 | |||
240 | /* next, write it to the GDK bitmap */ | ||
241 | if (colormap) { | ||
242 | mask = (1 << bits_per_pixel) - 1; | ||
243 | for (inbit = 8 - bits_per_pixel, inbyte = rowbuf, j = 0; j < width; ++j) { | ||
244 | inval = ((*inbyte) & (mask << inbit)) >> inbit; | ||
245 | /* correct for oddity of the 8-bit color Palm pixmap... */ | ||
246 | if ((bits_per_pixel == 8) && (inval == 0xFF)) inval = 231; | ||
247 | /* now lookup the correct color and set the pixel in the GTK bitmap */ | ||
248 | QRgb colour = qRgb(colormap[inval].red, colormap[inval].green, colormap[inval].blue); | ||
249 | qimage->setPixel(j, i, colour); | ||
250 | if (!inbit) { | ||
251 | ++inbyte; | ||
252 | inbit = 8 - bits_per_pixel; | ||
253 | } else { | ||
254 | inbit -= bits_per_pixel; | ||
255 | } | ||
256 | } | ||
257 | } else if (!colormap && | ||
258 | bits_per_pixel == 16) { | ||
259 | for (inbyte = rowbuf, j = 0; j < width; ++j) { | ||
260 | inval = (inbyte[0] << 8) | inbyte[1]; | ||
261 | #if 0 | ||
262 | qDebug ("pixel is %d,%d (%02x:%02x:%02x)", | ||
263 | j, i, | ||
264 | (inval >> (bits_per_pixel - palm_red_bits)) & ((1 << palm_red_bits) - 1), | ||
265 | (inval >> palm_blue_bits) & ((1 << palm_green_bits) - 1), | ||
266 | (inval >> 0) & ((1 << palm_blue_bits) - 1)); | ||
267 | #endif | ||
268 | QRgb colour = qRgb( | ||
269 | (inval >> (bits_per_pixel - palm_red_bits)) & ((1 << palm_red_bits) - 1), | ||
270 | (inval >> palm_blue_bits) & ((1 << palm_green_bits) - 1), | ||
271 | (inval >> 0) & ((1 << palm_blue_bits) - 1)); | ||
272 | qimage->setPixel(j, i, colour); | ||
273 | inbyte += 2; | ||
274 | } | ||
275 | } | ||
276 | } | ||
277 | |||
278 | delete [] rowbuf; | ||
279 | delete [] lastrow; | ||
280 | |||
281 | return qimage; | ||
282 | } | ||
283 | |||
284 | QPixmap* hRule(int w, int h, unsigned char r, unsigned char g, unsigned char b) | ||
285 | { | ||
286 | // qDebug("hrule [%d, %d]", w, h); | ||
287 | QPixmap* qimage = new QPixmap(w, h); | ||
288 | qimage->fill(QColor(r,g,b)); | ||
289 | return qimage; | ||
290 | } | ||