1 |
frodo |
10 |
/* |
2 |
|
|
parse_image.c - Part of psiconv, a PSION 5 file formats converter |
3 |
frodo |
196 |
Copyright (c) 1999-2004 Frodo Looijaard <frodol@dds.nl> |
4 |
frodo |
10 |
|
5 |
|
|
This program is free software; you can redistribute it and/or modify |
6 |
|
|
it under the terms of the GNU General Public License as published by |
7 |
|
|
the Free Software Foundation; either version 2 of the License, or |
8 |
|
|
(at your option) any later version. |
9 |
|
|
|
10 |
|
|
This program is distributed in the hope that it will be useful, |
11 |
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 |
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 |
|
|
GNU General Public License for more details. |
14 |
|
|
|
15 |
|
|
You should have received a copy of the GNU General Public License |
16 |
|
|
along with this program; if not, write to the Free Software |
17 |
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
18 |
|
|
*/ |
19 |
|
|
|
20 |
|
|
#include "config.h" |
21 |
frodo |
71 |
#include "compat.h" |
22 |
|
|
|
23 |
frodo |
10 |
#include <stdlib.h> |
24 |
|
|
|
25 |
|
|
#include "parse_routines.h" |
26 |
frodo |
71 |
#include "error.h" |
27 |
frodo |
178 |
#include "image.h" |
28 |
frodo |
10 |
|
29 |
frodo |
142 |
#ifdef DMALLOC |
30 |
|
|
#include <dmalloc.h> |
31 |
|
|
#endif |
32 |
|
|
|
33 |
frodo |
230 |
/* Extreme debugging info */ |
34 |
|
|
#undef LOUD |
35 |
|
|
|
36 |
frodo |
178 |
static int psiconv_decode_rle8 (const psiconv_config config, int lev, |
37 |
|
|
psiconv_u32 off, |
38 |
|
|
const psiconv_pixel_bytes encoded, |
39 |
|
|
psiconv_pixel_bytes *decoded); |
40 |
frodo |
142 |
|
41 |
frodo |
179 |
static int psiconv_decode_rle12 (const psiconv_config config, int lev, |
42 |
|
|
psiconv_u32 off, |
43 |
|
|
const psiconv_pixel_bytes encoded, |
44 |
|
|
psiconv_pixel_bytes *decoded); |
45 |
|
|
|
46 |
|
|
static int psiconv_decode_rle16 (const psiconv_config config, int lev, |
47 |
|
|
psiconv_u32 off, |
48 |
|
|
const psiconv_pixel_bytes encoded, |
49 |
|
|
psiconv_pixel_bytes *decoded); |
50 |
|
|
|
51 |
|
|
static int psiconv_decode_rle24 (const psiconv_config config, int lev, |
52 |
|
|
psiconv_u32 off, |
53 |
|
|
const psiconv_pixel_bytes encoded, |
54 |
|
|
psiconv_pixel_bytes *decoded); |
55 |
|
|
|
56 |
frodo |
178 |
static int psiconv_bytes_to_pixel_data(const psiconv_config config, |
57 |
|
|
int lev, psiconv_u32 off, |
58 |
|
|
const psiconv_pixel_bytes bytes, |
59 |
|
|
psiconv_pixel_ints *pixels, |
60 |
|
|
int colordepth, int xsize, int ysize); |
61 |
|
|
|
62 |
|
|
static int psiconv_pixel_data_to_floats (const psiconv_config config, int lev, |
63 |
|
|
psiconv_u32 off, |
64 |
|
|
const psiconv_pixel_ints pixels, |
65 |
|
|
psiconv_pixel_floats_t *floats, |
66 |
|
|
int colordepth, int color, |
67 |
|
|
int redbits, int bluebits, int greenbits, |
68 |
|
|
const psiconv_pixel_floats_t palet); |
69 |
|
|
|
70 |
|
|
|
71 |
|
|
|
72 |
frodo |
168 |
int psiconv_parse_jumptable_section(const psiconv_config config, |
73 |
|
|
const psiconv_buffer buf,int lev, |
74 |
frodo |
42 |
psiconv_u32 off, int *length, |
75 |
|
|
psiconv_jumptable_section *result) |
76 |
frodo |
12 |
{ |
77 |
|
|
int res = 0; |
78 |
|
|
int len = 0; |
79 |
|
|
psiconv_u32 listlen,temp; |
80 |
|
|
int i; |
81 |
|
|
|
82 |
frodo |
168 |
psiconv_progress(config,lev+1,off+len,"Going to read the jumptable section"); |
83 |
frodo |
64 |
if (!((*result) = psiconv_list_new(sizeof(psiconv_u32)))) |
84 |
|
|
goto ERROR1; |
85 |
frodo |
12 |
|
86 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read the list length"); |
87 |
|
|
listlen = psiconv_read_u32(config,buf,lev+2,off+len,&res); |
88 |
frodo |
65 |
if (res) |
89 |
frodo |
64 |
goto ERROR2; |
90 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"List length: %08x",listlen); |
91 |
frodo |
12 |
len += 4; |
92 |
|
|
|
93 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read the list"); |
94 |
frodo |
12 |
for (i = 0; i < listlen; i++) { |
95 |
frodo |
168 |
temp = psiconv_read_u32(config,buf,lev+2,off+len,&res); |
96 |
frodo |
65 |
if (res) |
97 |
frodo |
64 |
goto ERROR2; |
98 |
|
|
if ((res = psiconv_list_add(*result,&temp))) |
99 |
|
|
goto ERROR2; |
100 |
frodo |
168 |
psiconv_debug(config,lev+3,off+len,"Offset: %08x",temp); |
101 |
frodo |
12 |
len += 4; |
102 |
|
|
} |
103 |
|
|
|
104 |
|
|
if (length) |
105 |
|
|
*length = len; |
106 |
|
|
|
107 |
frodo |
168 |
psiconv_progress(config,lev+1,off+len-1,"End of jumptable section " |
108 |
frodo |
13 |
"(total length: %08x)", len); |
109 |
frodo |
12 |
|
110 |
frodo |
64 |
return 0; |
111 |
|
|
|
112 |
|
|
ERROR2: |
113 |
|
|
psiconv_list_free(*result); |
114 |
|
|
ERROR1: |
115 |
frodo |
184 |
psiconv_error(config,lev+1,off,"Reading of Jumptable Section failed"); |
116 |
frodo |
64 |
if (length) |
117 |
|
|
*length = 0; |
118 |
|
|
if (!res) |
119 |
|
|
return -PSICONV_E_NOMEM; |
120 |
|
|
else |
121 |
|
|
return res; |
122 |
frodo |
12 |
} |
123 |
|
|
|
124 |
frodo |
168 |
int psiconv_parse_paint_data_section(const psiconv_config config, |
125 |
|
|
const psiconv_buffer buf,int lev, |
126 |
frodo |
45 |
psiconv_u32 off, int *length,int isclipart, |
127 |
frodo |
10 |
psiconv_paint_data_section *result) |
128 |
|
|
{ |
129 |
|
|
int res = 0; |
130 |
|
|
int len = 0; |
131 |
frodo |
179 |
psiconv_u32 size,offset,picsize,temp,datasize,color, |
132 |
|
|
redbits,bluebits,greenbits; |
133 |
|
|
psiconv_u8 byte; |
134 |
|
|
int leng,i; |
135 |
frodo |
25 |
psiconv_u32 bits_per_pixel,compression; |
136 |
frodo |
179 |
psiconv_pixel_bytes bytes,decoded; |
137 |
|
|
psiconv_pixel_ints pixels; |
138 |
|
|
psiconv_pixel_floats_t floats,palet; |
139 |
frodo |
10 |
|
140 |
frodo |
168 |
psiconv_progress(config,lev+1,off,"Going to read a paint data section"); |
141 |
frodo |
64 |
if (!((*result) = malloc(sizeof(**result)))) |
142 |
|
|
goto ERROR1; |
143 |
frodo |
10 |
|
144 |
frodo |
179 |
if (!(bytes = psiconv_list_new(sizeof(psiconv_u8)))) |
145 |
|
|
goto ERROR2; |
146 |
|
|
|
147 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read section size"); |
148 |
|
|
size = psiconv_read_u32(config,buf,lev+2,off+len,&res); |
149 |
frodo |
64 |
if (res) |
150 |
frodo |
179 |
goto ERROR3; |
151 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Section size: %08x",size); |
152 |
frodo |
10 |
len += 4; |
153 |
|
|
|
154 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read pixel data offset"); |
155 |
|
|
offset = psiconv_read_u32(config,buf,lev+2,off+len,&res); |
156 |
frodo |
64 |
if (res) |
157 |
frodo |
179 |
goto ERROR3; |
158 |
frodo |
13 |
if (offset != 0x28) { |
159 |
frodo |
184 |
psiconv_error(config,lev+2,off+len, |
160 |
frodo |
10 |
"Paint data section data offset has unexpected value"); |
161 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len, |
162 |
frodo |
10 |
"Data offset: read %08x, expected %08x",offset,0x28); |
163 |
frodo |
12 |
res = -1; |
164 |
frodo |
10 |
} |
165 |
|
|
len += 4; |
166 |
|
|
|
167 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read picture X size"); |
168 |
|
|
(*result)->xsize = psiconv_read_u32(config,buf,lev+2,off+len,&res); |
169 |
frodo |
64 |
if (res) |
170 |
frodo |
179 |
goto ERROR3; |
171 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Picture X size: %08x:",(*result)->xsize); |
172 |
frodo |
10 |
len += 4; |
173 |
|
|
|
174 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read picture Y size"); |
175 |
|
|
(*result)->ysize = psiconv_read_u32(config,buf,lev+2,off+len,&res); |
176 |
frodo |
64 |
if (res) |
177 |
frodo |
179 |
goto ERROR3; |
178 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Picture Y size: %08x:",(*result)->ysize); |
179 |
frodo |
10 |
len += 4; |
180 |
|
|
|
181 |
frodo |
25 |
picsize = (*result)->ysize * (*result)->xsize; |
182 |
frodo |
10 |
|
183 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read the real picture x size"); |
184 |
|
|
(*result)->pic_xsize = psiconv_read_length(config,buf,lev+2,off+len,&leng,&res); |
185 |
frodo |
64 |
if (res) |
186 |
frodo |
179 |
goto ERROR3; |
187 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Picture x size: %f",(*result)->pic_xsize); |
188 |
frodo |
25 |
len += leng; |
189 |
|
|
|
190 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read the real picture y size"); |
191 |
|
|
(*result)->pic_ysize = psiconv_read_length(config,buf,lev+2,off+len,&leng,&res); |
192 |
frodo |
64 |
if (res) |
193 |
frodo |
179 |
goto ERROR3; |
194 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Picture y size: %f",(*result)->pic_ysize); |
195 |
frodo |
25 |
len += leng; |
196 |
|
|
|
197 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read the number of bits per pixel"); |
198 |
|
|
bits_per_pixel=psiconv_read_u32(config,buf,lev+2,off+len,&res); |
199 |
frodo |
64 |
if (res) |
200 |
frodo |
179 |
goto ERROR3; |
201 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Bits per pixel: %d",bits_per_pixel); |
202 |
frodo |
25 |
len += 4; |
203 |
|
|
|
204 |
frodo |
179 |
psiconv_progress(config,lev+2,off+len, |
205 |
|
|
"Going to read whether this is a colour or greyscale picture"); |
206 |
|
|
color = psiconv_read_u32(config,buf,lev+2,off+len,&res); |
207 |
|
|
if (res) |
208 |
|
|
goto ERROR3; |
209 |
|
|
if ((color != 0) && (color != 1)) { |
210 |
|
|
psiconv_warn(config,lev+2,off+len, |
211 |
|
|
"Paint data section unknown color type (ignored)"); |
212 |
|
|
psiconv_debug(config,lev+2,off+len, |
213 |
|
|
"Color: read %08x, expected %08x or %08x",color,0,1); |
214 |
|
|
color = 1; |
215 |
|
|
} else { |
216 |
|
|
psiconv_debug(config,lev+2,off+len,"Color: %08x (%s picture)", |
217 |
|
|
color,(color?"color":"greyscale")); |
218 |
frodo |
10 |
} |
219 |
frodo |
179 |
len += 4; |
220 |
|
|
|
221 |
|
|
temp = psiconv_read_u32(config,buf,lev+2,off+len,&res); |
222 |
|
|
if (res) |
223 |
|
|
goto ERROR3; |
224 |
|
|
if (temp != 00) { |
225 |
|
|
psiconv_warn(config,lev+2,off+len, |
226 |
|
|
"Paint data section prologue has unknown values (ignored)"); |
227 |
|
|
psiconv_debug(config,lev+2,off+len, |
228 |
|
|
"read %08x, expected %08x",temp, 0x00); |
229 |
|
|
} |
230 |
|
|
len += 4; |
231 |
frodo |
25 |
|
232 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len, |
233 |
frodo |
25 |
"Going to read whether RLE compression is used"); |
234 |
frodo |
168 |
compression=psiconv_read_u32(config,buf,lev+2,off+len,&res); |
235 |
frodo |
64 |
if (res) |
236 |
frodo |
179 |
goto ERROR3; |
237 |
|
|
if (compression > 4) { |
238 |
frodo |
168 |
psiconv_warn(config,lev+2,off+len,"Paint data section has unknown " |
239 |
frodo |
25 |
"compression type, assuming RLE"); |
240 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Read compression type %d",compression); |
241 |
frodo |
179 |
compression = 0; |
242 |
frodo |
25 |
} |
243 |
frodo |
179 |
psiconv_debug(config,lev+2,off+len,"Compression: %s", |
244 |
|
|
compression == 4?"RLE24":compression == 3?"RLE16": |
245 |
|
|
compression == 2?"RLE12":compression == 1?"RLE8":"none"); |
246 |
frodo |
45 |
len += 4; |
247 |
frodo |
10 |
|
248 |
frodo |
45 |
if (isclipart) { |
249 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read an unknown long"); |
250 |
|
|
temp = psiconv_read_u32(config,buf,lev+2,off+len,&res); |
251 |
frodo |
64 |
if (res) |
252 |
frodo |
179 |
goto ERROR3; |
253 |
frodo |
45 |
if (temp != 0xffffffff) { |
254 |
frodo |
168 |
psiconv_warn(config,lev+2,off+len, |
255 |
frodo |
64 |
"Paint data section prologue has unknown values (ignoring)"); |
256 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len, |
257 |
frodo |
179 |
"Read %08x, expected %08x",temp, 0xffffffff); |
258 |
frodo |
45 |
} |
259 |
|
|
len += 4; |
260 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read a second unknown long"); |
261 |
|
|
temp = psiconv_read_u32(config,buf,lev+2,off+len,&res); |
262 |
frodo |
64 |
if (res) |
263 |
frodo |
179 |
goto ERROR3; |
264 |
frodo |
45 |
if (temp != 0x44) { |
265 |
frodo |
168 |
psiconv_warn(config,lev+2,off+len, |
266 |
frodo |
64 |
"Paint data section prologue has unknown values (ignoring)"); |
267 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len, |
268 |
frodo |
179 |
"read %08x, expected %08x",temp, 0x44); |
269 |
frodo |
45 |
} |
270 |
|
|
len += 4; |
271 |
|
|
} |
272 |
|
|
|
273 |
frodo |
10 |
len = offset; |
274 |
|
|
datasize = size - len; |
275 |
frodo |
45 |
if (isclipart) |
276 |
|
|
len += 8; |
277 |
frodo |
10 |
|
278 |
frodo |
179 |
if (color || (bits_per_pixel != 2)) |
279 |
|
|
psiconv_warn(config,lev+2,off+len, |
280 |
|
|
"All image types except 2-bit greyscale are experimental!"); |
281 |
|
|
|
282 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read the pixel data"); |
283 |
frodo |
179 |
for (i = 0; i < datasize; i++) { |
284 |
|
|
byte = psiconv_read_u8(config,buf,lev+2,off+len+i,&res); |
285 |
frodo |
230 |
#ifdef LOUD |
286 |
frodo |
179 |
psiconv_debug(config,lev+2,off+len+i, |
287 |
|
|
"Pixel byte %04x of %04x has value %02x", |
288 |
|
|
i,datasize,byte); |
289 |
frodo |
230 |
#endif |
290 |
frodo |
179 |
if (res) |
291 |
|
|
goto ERROR3; |
292 |
|
|
psiconv_list_add(bytes,&byte); |
293 |
frodo |
10 |
} |
294 |
frodo |
179 |
len += datasize; |
295 |
frodo |
25 |
|
296 |
frodo |
179 |
switch(compression) { |
297 |
|
|
case 1: |
298 |
|
|
if ((res = psiconv_decode_rle8(config,lev+2,off+len,bytes,&decoded))) |
299 |
|
|
goto ERROR3; |
300 |
|
|
psiconv_list_free(bytes); |
301 |
|
|
bytes = decoded; |
302 |
|
|
break; |
303 |
|
|
case 2: |
304 |
|
|
if ((psiconv_decode_rle12(config,lev+2,off+len,bytes,&decoded))) |
305 |
|
|
goto ERROR3; |
306 |
|
|
psiconv_list_free(bytes); |
307 |
|
|
bytes = decoded; |
308 |
|
|
break; |
309 |
|
|
case 3: |
310 |
|
|
if ((psiconv_decode_rle16(config,lev+2,off+len,bytes,&decoded))) |
311 |
|
|
goto ERROR3; |
312 |
|
|
psiconv_list_free(bytes); |
313 |
|
|
bytes = decoded; |
314 |
|
|
break; |
315 |
|
|
case 4: |
316 |
|
|
if ((psiconv_decode_rle24(config,lev+2,off+len,bytes,&decoded))) |
317 |
|
|
goto ERROR3; |
318 |
|
|
psiconv_list_free(bytes); |
319 |
|
|
bytes = decoded; |
320 |
|
|
break; |
321 |
frodo |
12 |
} |
322 |
|
|
|
323 |
frodo |
179 |
if ((res = psiconv_bytes_to_pixel_data(config,lev+2,off+len,bytes, |
324 |
|
|
&pixels,bits_per_pixel, |
325 |
|
|
(*result)->xsize,(*result)->ysize))) |
326 |
|
|
goto ERROR3; |
327 |
frodo |
10 |
|
328 |
frodo |
179 |
/* Use some heuristics; things may get unexpected around here */ |
329 |
|
|
bluebits = redbits = greenbits = 0; |
330 |
|
|
palet = psiconv_palet_none; |
331 |
|
|
if (color) { |
332 |
|
|
if (bits_per_pixel == 4) |
333 |
|
|
palet = psiconv_palet_color_4; |
334 |
|
|
else if (bits_per_pixel == 8) |
335 |
|
|
palet = psiconv_palet_color_8; |
336 |
|
|
else { |
337 |
|
|
redbits = (bits_per_pixel+2) / 3; |
338 |
|
|
greenbits = (bits_per_pixel+2) / 3; |
339 |
|
|
bluebits = bits_per_pixel - redbits - greenbits; |
340 |
|
|
} |
341 |
|
|
} |
342 |
|
|
if ((res = psiconv_pixel_data_to_floats(config,lev+2,off+len,pixels, |
343 |
|
|
&floats,bits_per_pixel,color, |
344 |
|
|
redbits,greenbits,bluebits,palet))) |
345 |
|
|
goto ERROR4; |
346 |
|
|
|
347 |
|
|
(*result)->red = floats.red; |
348 |
|
|
(*result)->green = floats.green; |
349 |
|
|
(*result)->blue = floats.blue; |
350 |
|
|
|
351 |
|
|
psiconv_list_free(bytes); |
352 |
|
|
psiconv_list_free(pixels); |
353 |
|
|
|
354 |
|
|
|
355 |
frodo |
10 |
if (length) |
356 |
|
|
*length = len; |
357 |
|
|
|
358 |
frodo |
179 |
psiconv_progress(config,lev,off+len-1, |
359 |
|
|
"End of Paint Data Section (total length: %08x)", len); |
360 |
frodo |
10 |
|
361 |
frodo |
179 |
return 0; |
362 |
frodo |
64 |
|
363 |
|
|
ERROR4: |
364 |
frodo |
179 |
psiconv_list_free(pixels); |
365 |
frodo |
64 |
ERROR3: |
366 |
frodo |
179 |
psiconv_list_free(bytes); |
367 |
frodo |
64 |
ERROR2: |
368 |
frodo |
179 |
free(*result); |
369 |
frodo |
64 |
ERROR1: |
370 |
frodo |
184 |
psiconv_error(config,lev+1,off,"Reading of Paint Data Section failed"); |
371 |
frodo |
64 |
if (length) |
372 |
|
|
*length = 0; |
373 |
|
|
if (!res) |
374 |
|
|
return -PSICONV_E_NOMEM; |
375 |
|
|
else |
376 |
|
|
return res; |
377 |
frodo |
10 |
} |
378 |
|
|
|
379 |
frodo |
168 |
int psiconv_parse_sketch_section(const psiconv_config config, |
380 |
|
|
const psiconv_buffer buf, int lev, |
381 |
frodo |
163 |
psiconv_u32 off, int *length, |
382 |
frodo |
24 |
psiconv_sketch_section *result) |
383 |
|
|
{ |
384 |
|
|
int res=0; |
385 |
|
|
int len=0; |
386 |
|
|
psiconv_u32 temp; |
387 |
|
|
int leng; |
388 |
|
|
|
389 |
frodo |
168 |
psiconv_progress(config,lev+1,off,"Going to read the sketch section"); |
390 |
frodo |
64 |
if (!(*result = malloc(sizeof(**result)))) |
391 |
|
|
goto ERROR1; |
392 |
frodo |
24 |
|
393 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read the displayed hor. size"); |
394 |
|
|
(*result)->displayed_xsize = psiconv_read_u16(config,buf,lev+2,off + len,&res); |
395 |
frodo |
163 |
if (res) |
396 |
|
|
goto ERROR2; |
397 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Displayed hor. size: %04x", |
398 |
frodo |
163 |
(*result)->displayed_xsize); |
399 |
|
|
len += 0x02; |
400 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read displayed ver. size"); |
401 |
|
|
(*result)->displayed_ysize = psiconv_read_u16(config,buf,lev+2,off + len,&res); |
402 |
frodo |
163 |
if (res) |
403 |
|
|
goto ERROR2; |
404 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Displayed ver. size: %04x", |
405 |
frodo |
163 |
(*result)->displayed_ysize); |
406 |
|
|
len += 0x02; |
407 |
frodo |
24 |
|
408 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read the data hor. offset"); |
409 |
|
|
(*result)->picture_data_x_offset = psiconv_read_u16(config,buf,lev+2,off + len, |
410 |
frodo |
163 |
&res); |
411 |
|
|
if (res) |
412 |
|
|
goto ERROR2; |
413 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Data hor. offset: %04x", |
414 |
frodo |
163 |
(*result)->picture_data_x_offset); |
415 |
|
|
len += 0x02; |
416 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read the data ver. offset"); |
417 |
|
|
(*result)->picture_data_y_offset = psiconv_read_u16(config,buf,lev+2,off + len, |
418 |
frodo |
163 |
&res); |
419 |
|
|
if (res) |
420 |
|
|
goto ERROR2; |
421 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Data ver. offset: %04x", |
422 |
frodo |
163 |
(*result)->picture_data_y_offset); |
423 |
|
|
len += 0x02; |
424 |
|
|
|
425 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read the displayed hor. offset"); |
426 |
|
|
(*result)->displayed_size_x_offset = psiconv_read_u16(config,buf,lev+2,off + len, |
427 |
frodo |
163 |
&res); |
428 |
|
|
if (res) |
429 |
|
|
goto ERROR2; |
430 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Displayed hor. offset: %04x", |
431 |
frodo |
163 |
(*result)->displayed_size_x_offset); |
432 |
|
|
len += 0x02; |
433 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read the displayed ver. offset"); |
434 |
|
|
(*result)->displayed_size_y_offset = psiconv_read_u16(config,buf,lev+2,off + len, |
435 |
frodo |
163 |
&res); |
436 |
|
|
if (res) |
437 |
|
|
goto ERROR2; |
438 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Displayed ver. offset: %04x", |
439 |
frodo |
163 |
(*result)->displayed_size_y_offset); |
440 |
|
|
len += 0x02; |
441 |
|
|
|
442 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read the form hor. size"); |
443 |
|
|
(*result)->form_xsize = psiconv_read_u16(config,buf,lev+2,off + len,&res); |
444 |
frodo |
163 |
if (res) |
445 |
|
|
goto ERROR2; |
446 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Form hor. size: %04x", |
447 |
frodo |
163 |
(*result)->form_xsize); |
448 |
|
|
len += 0x02; |
449 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read form ver. size"); |
450 |
|
|
(*result)->form_ysize = psiconv_read_u16(config,buf,lev+2,off + len,&res); |
451 |
frodo |
163 |
if (res) |
452 |
|
|
goto ERROR2; |
453 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Form ver. size: %04x", |
454 |
frodo |
163 |
(*result)->form_ysize); |
455 |
|
|
len += 0x02; |
456 |
|
|
|
457 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to skip 1 word of zeros"); |
458 |
|
|
temp = psiconv_read_u16(config,buf,lev+2,off+len,&res); |
459 |
frodo |
163 |
if (res) |
460 |
|
|
goto ERROR2; |
461 |
|
|
if (temp != 0) { |
462 |
frodo |
168 |
psiconv_warn(config,lev+2,off+len, |
463 |
frodo |
163 |
"Unexpected value in sketch section preamble (ignored)"); |
464 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Read %04x, expected %04x", |
465 |
frodo |
163 |
temp,0); |
466 |
frodo |
24 |
} |
467 |
frodo |
163 |
off += 0x02; |
468 |
frodo |
24 |
|
469 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read the picture data"); |
470 |
|
|
if ((res = psiconv_parse_paint_data_section(config,buf,lev+2,off+len,&leng,0, |
471 |
frodo |
64 |
&((*result)->picture)))) |
472 |
|
|
goto ERROR2; |
473 |
frodo |
24 |
off += leng; |
474 |
|
|
|
475 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read the hor. magnification"); |
476 |
|
|
(*result)->magnification_x = psiconv_read_u16(config,buf,lev+2,off+len,&res)/1000.0; |
477 |
frodo |
64 |
if (res) |
478 |
|
|
goto ERROR3; |
479 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Form hor. magnification: %f", |
480 |
frodo |
24 |
(*result)->magnification_x); |
481 |
|
|
len += 0x02; |
482 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read the ver. magnification"); |
483 |
|
|
(*result)->magnification_y = psiconv_read_u16(config,buf,lev+2,off+len,&res)/1000.0; |
484 |
frodo |
64 |
if (res) |
485 |
|
|
goto ERROR3; |
486 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Form ver. magnification: %f", |
487 |
frodo |
24 |
(*result)->magnification_y); |
488 |
|
|
len += 0x02; |
489 |
|
|
|
490 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read the left cut"); |
491 |
|
|
temp = psiconv_read_u32(config,buf,lev+2,off + len,&res); |
492 |
frodo |
64 |
if (res) |
493 |
|
|
goto ERROR3; |
494 |
frodo |
163 |
(*result)->cut_left = (temp * 6.0) / (*result)->displayed_xsize; |
495 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Left cut: raw %08x, real: %f", |
496 |
frodo |
24 |
temp,(*result)->cut_left); |
497 |
|
|
len += 0x04; |
498 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read the right cut"); |
499 |
|
|
temp = psiconv_read_u32(config,buf,lev+2,off + len,&res); |
500 |
frodo |
64 |
if (res) |
501 |
|
|
goto ERROR3; |
502 |
frodo |
163 |
(*result)->cut_right = (temp * 6.0) / (*result)->displayed_xsize; |
503 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Right cut: raw %08x, real: %f", |
504 |
frodo |
24 |
temp,(*result)->cut_right); |
505 |
|
|
len += 0x04; |
506 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read the top cut"); |
507 |
|
|
temp = psiconv_read_u32(config,buf,lev+2,off + len,&res); |
508 |
frodo |
64 |
if (res) |
509 |
|
|
goto ERROR3; |
510 |
frodo |
163 |
(*result)->cut_top = (temp * 6.0) / (*result)->displayed_ysize; |
511 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Top cut: raw %08x, real: %f", |
512 |
frodo |
24 |
temp,(*result)->cut_top); |
513 |
|
|
len += 0x04; |
514 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read the bottom cut"); |
515 |
|
|
temp = psiconv_read_u32(config,buf,lev+2,off + len,&res); |
516 |
frodo |
64 |
if (res) |
517 |
|
|
goto ERROR3; |
518 |
frodo |
163 |
(*result)->cut_bottom = (temp * 6.0) / (*result)->displayed_ysize; |
519 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Bottom cut: raw %08x, real: %f", |
520 |
frodo |
24 |
temp,(*result)->cut_bottom); |
521 |
|
|
len += 0x04; |
522 |
|
|
|
523 |
|
|
if (length) |
524 |
|
|
*length = len; |
525 |
|
|
|
526 |
frodo |
168 |
psiconv_progress(config,lev,off+len-1, |
527 |
frodo |
24 |
"End of sketch section (total length: %08x)", len); |
528 |
|
|
|
529 |
|
|
return res; |
530 |
frodo |
64 |
ERROR3: |
531 |
|
|
psiconv_free_paint_data_section((*result)->picture); |
532 |
|
|
ERROR2: |
533 |
|
|
free (*result); |
534 |
|
|
ERROR1: |
535 |
frodo |
184 |
psiconv_error(config,lev+1,off,"Reading of Sketch Section failed"); |
536 |
frodo |
64 |
if (length) |
537 |
|
|
*length = 0; |
538 |
|
|
if (!res) |
539 |
|
|
return -PSICONV_E_NOMEM; |
540 |
|
|
else |
541 |
|
|
return res; |
542 |
frodo |
24 |
} |
543 |
|
|
|
544 |
frodo |
43 |
|
545 |
frodo |
168 |
int psiconv_parse_clipart_section(const psiconv_config config, |
546 |
|
|
const psiconv_buffer buf,int lev, |
547 |
frodo |
43 |
psiconv_u32 off, int *length, |
548 |
|
|
psiconv_clipart_section *result) |
549 |
|
|
{ |
550 |
|
|
int res=0; |
551 |
|
|
int len=0; |
552 |
|
|
int leng; |
553 |
|
|
psiconv_u32 temp; |
554 |
|
|
|
555 |
frodo |
168 |
psiconv_progress(config,lev+1,off+len,"Going to read the clipart section"); |
556 |
frodo |
64 |
if (!(*result = malloc(sizeof(**result)))) |
557 |
|
|
goto ERROR1; |
558 |
frodo |
43 |
|
559 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read the section ID"); |
560 |
|
|
temp = psiconv_read_u32(config,buf,lev+2,off+len,&res); |
561 |
frodo |
64 |
if (res) |
562 |
|
|
goto ERROR2; |
563 |
frodo |
43 |
if (temp != PSICONV_ID_CLIPART_ITEM) { |
564 |
frodo |
168 |
psiconv_warn(config,lev+2,off+len, |
565 |
frodo |
64 |
"Unexpected value in clipart section preamble (ignored)"); |
566 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Read %08x, expected %08x",temp, |
567 |
frodo |
43 |
PSICONV_ID_CLIPART_ITEM); |
568 |
|
|
} else |
569 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Clipart ID: %08x", temp); |
570 |
frodo |
43 |
off += 4; |
571 |
|
|
|
572 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read an unknown long"); |
573 |
|
|
temp = psiconv_read_u32(config,buf,lev+2,off+len,&res); |
574 |
frodo |
64 |
if (res) |
575 |
|
|
goto ERROR2; |
576 |
frodo |
43 |
if (temp != 0x02) { |
577 |
frodo |
168 |
psiconv_warn(config,lev+2,off+len, |
578 |
frodo |
64 |
"Unexpected value in clipart section preamble (ignored)"); |
579 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Read %08x, expected %08x",temp, |
580 |
frodo |
43 |
0x02); |
581 |
|
|
} else |
582 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"First unknown long: %08x", temp); |
583 |
frodo |
43 |
off += 4; |
584 |
|
|
|
585 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read a second unknown long"); |
586 |
|
|
temp = psiconv_read_u32(config,buf,lev+2,off+len,&res); |
587 |
frodo |
64 |
if (res) |
588 |
|
|
goto ERROR2; |
589 |
frodo |
43 |
if (temp != 0) { |
590 |
frodo |
168 |
psiconv_warn(config,lev+2,off+len, |
591 |
frodo |
64 |
"Unexpected value in clipart section preamble (ignored)"); |
592 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Read %08x, expected %08x",temp, 0); |
593 |
frodo |
43 |
} else |
594 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Second unknown long: %08x", temp); |
595 |
frodo |
43 |
off += 4; |
596 |
|
|
|
597 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read a third unknown long"); |
598 |
|
|
temp = psiconv_read_u32(config,buf,lev+2,off+len,&res); |
599 |
frodo |
64 |
if (res) |
600 |
|
|
goto ERROR2; |
601 |
frodo |
43 |
if (temp != 0) { |
602 |
frodo |
168 |
psiconv_warn(config,lev+2,off+len, |
603 |
frodo |
64 |
"Unexpected value in clipart section preamble (ignored)"); |
604 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Read %08x, expected %08x",temp, 0); |
605 |
frodo |
43 |
} else |
606 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Third unknown long: %08x", temp); |
607 |
frodo |
43 |
off += 4; |
608 |
|
|
|
609 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read a fourth unknown long"); |
610 |
|
|
temp = psiconv_read_u32(config,buf,lev+2,off+len,&res); |
611 |
frodo |
64 |
if (res) |
612 |
|
|
goto ERROR2; |
613 |
frodo |
43 |
if ((temp != 0x0c) && (temp != 0x08)) { |
614 |
frodo |
168 |
psiconv_warn(config,lev+2,off+len, |
615 |
frodo |
64 |
"Unexpected value in clipart section preamble (ignored)"); |
616 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Read %08x, expected %08x or %08x",temp, |
617 |
frodo |
43 |
0x0c, 0x08); |
618 |
|
|
} else |
619 |
frodo |
168 |
psiconv_debug(config,lev+2,off+len,"Fourth unknown long: %08x", temp); |
620 |
frodo |
43 |
off += 4; |
621 |
|
|
|
622 |
frodo |
168 |
psiconv_progress(config,lev+2,off+len,"Going to read the Paint Data Section"); |
623 |
|
|
if ((res = psiconv_parse_paint_data_section(config,buf,lev+2,off+len,&leng,1, |
624 |
frodo |
64 |
&((*result)->picture)))) |
625 |
|
|
goto ERROR2; |
626 |
frodo |
43 |
len += leng; |
627 |
|
|
|
628 |
|
|
if (length) |
629 |
|
|
*length = len; |
630 |
|
|
|
631 |
frodo |
168 |
psiconv_progress(config,lev,off+len-1, |
632 |
frodo |
43 |
"End of clipart section (total length: %08x)", len); |
633 |
frodo |
64 |
return 0; |
634 |
frodo |
43 |
|
635 |
frodo |
64 |
ERROR2: |
636 |
|
|
free (*result); |
637 |
|
|
ERROR1: |
638 |
frodo |
184 |
psiconv_error(config,lev+1,off,"Reading of Font failed"); |
639 |
frodo |
64 |
if (length) |
640 |
|
|
*length = 0; |
641 |
|
|
if (!res) |
642 |
|
|
return -PSICONV_E_NOMEM; |
643 |
|
|
else |
644 |
|
|
return res; |
645 |
frodo |
43 |
} |
646 |
frodo |
178 |
|
647 |
|
|
int psiconv_decode_rle8 (const psiconv_config config, int lev, psiconv_u32 off, |
648 |
|
|
const psiconv_pixel_bytes encoded, |
649 |
|
|
psiconv_pixel_bytes *decoded) |
650 |
|
|
{ |
651 |
|
|
int res=0; |
652 |
|
|
psiconv_u8 *marker,*value; |
653 |
|
|
int i,j; |
654 |
|
|
|
655 |
|
|
psiconv_progress(config,lev+1,off,"Going to decode the RLE8 encoding"); |
656 |
|
|
if (!(*decoded = psiconv_list_new(sizeof(psiconv_u8)))) |
657 |
|
|
goto ERROR1; |
658 |
|
|
|
659 |
|
|
for (i = 0; i < psiconv_list_length(encoded);) { |
660 |
frodo |
230 |
#ifdef LOUD |
661 |
frodo |
178 |
psiconv_progress(config,lev+2,off,"Going to read marker byte at %04x",i); |
662 |
frodo |
230 |
#endif |
663 |
frodo |
178 |
if (!(marker = psiconv_list_get(encoded,i))) |
664 |
|
|
goto ERROR2; |
665 |
frodo |
230 |
#ifdef LOUD |
666 |
frodo |
178 |
psiconv_debug(config,lev+2,off,"Marker byte: %02x",*marker); |
667 |
frodo |
230 |
#endif |
668 |
frodo |
178 |
if (*marker < 0x80) { |
669 |
frodo |
230 |
#ifdef LOUD |
670 |
frodo |
178 |
psiconv_debug(config,lev+2,off,"Marker: repeat value byte %02x times", |
671 |
frodo |
230 |
*marker+1); */ |
672 |
frodo |
178 |
psiconv_progress(config,lev+2,off,"Going to read value byte at %04x",i+1); |
673 |
frodo |
230 |
#endif |
674 |
frodo |
178 |
if (!(value = psiconv_list_get(encoded,i+1))) |
675 |
|
|
goto ERROR2; |
676 |
frodo |
230 |
#ifdef LOUD |
677 |
|
|
psiconv_debug(config,lev+2,off,"Value byte: %02x",*value); |
678 |
frodo |
179 |
psiconv_progress(config,lev+2,off,"Adding %02x pixels %02x", |
679 |
frodo |
178 |
*marker+1,*value); |
680 |
frodo |
230 |
#endif |
681 |
frodo |
178 |
for (j = 0; j < *marker + 1; j++) |
682 |
|
|
if ((res = psiconv_list_add(*decoded,value))) |
683 |
|
|
goto ERROR2; |
684 |
|
|
i += 2; |
685 |
|
|
} else { |
686 |
frodo |
230 |
#ifdef LOUD |
687 |
frodo |
178 |
psiconv_debug(config,lev+2,off,"Marker: %02x value bytes follow", |
688 |
|
|
0x100 - *marker); |
689 |
frodo |
230 |
#endif |
690 |
frodo |
178 |
for (j = 0; j < (0x100 - *marker); j++) { |
691 |
frodo |
230 |
#ifdef LOUD |
692 |
frodo |
178 |
psiconv_progress(config,lev+2,off,"Going to read value byte at %04x", |
693 |
|
|
i+j+1); |
694 |
frodo |
230 |
#endif |
695 |
frodo |
178 |
if (!(value = psiconv_list_get(encoded,i+j+1))) |
696 |
|
|
goto ERROR2; |
697 |
frodo |
230 |
#ifdef LOUD |
698 |
|
|
psiconv_debug(config,lev+2,off,"Value: %02x",*value); |
699 |
|
|
#endif |
700 |
frodo |
178 |
if ((res = psiconv_list_add(*decoded,value))) |
701 |
|
|
goto ERROR2; |
702 |
|
|
} |
703 |
|
|
i += (0x100 - *marker) + 1; |
704 |
|
|
} |
705 |
|
|
} |
706 |
|
|
psiconv_progress(config,lev,off, |
707 |
|
|
"End of RLE8 decoding process"); |
708 |
|
|
return 0; |
709 |
|
|
|
710 |
|
|
ERROR2: |
711 |
|
|
psiconv_list_free(*decoded); |
712 |
|
|
ERROR1: |
713 |
frodo |
184 |
psiconv_error(config,lev+1,off,"Decoding of RLE8 failed"); |
714 |
frodo |
178 |
if (!res) |
715 |
|
|
return -PSICONV_E_NOMEM; |
716 |
|
|
else |
717 |
|
|
return res; |
718 |
frodo |
179 |
} |
719 |
|
|
|
720 |
|
|
int psiconv_decode_rle12 (const psiconv_config config, int lev, psiconv_u32 off, |
721 |
|
|
const psiconv_pixel_bytes encoded, |
722 |
|
|
psiconv_pixel_bytes *decoded) |
723 |
|
|
{ |
724 |
|
|
int res=0; |
725 |
|
|
psiconv_u8 *value0,*value1; |
726 |
|
|
psiconv_u32 value,repeat; |
727 |
|
|
int i,j; |
728 |
|
|
|
729 |
|
|
psiconv_progress(config,lev+1,off,"Going to decode the RLE12 encoding"); |
730 |
|
|
if (!(*decoded = psiconv_list_new(sizeof(psiconv_u8)))) |
731 |
|
|
goto ERROR1; |
732 |
|
|
|
733 |
|
|
for (i = 0; i < psiconv_list_length(encoded);) { |
734 |
|
|
psiconv_progress(config,lev+2,off,"Going to read data word at %04x",i); |
735 |
|
|
if (!(value0 = psiconv_list_get(encoded,i))) |
736 |
|
|
goto ERROR2; |
737 |
|
|
if (!(value1 = psiconv_list_get(encoded,i+1))) |
738 |
|
|
goto ERROR2; |
739 |
|
|
psiconv_debug(config,lev+2,off,"Data Word: %04x",*value0 + (*value1 << 8)); |
740 |
|
|
value = *value0 + ((*value1 & 0x0f) << 8); |
741 |
|
|
repeat = (*value1 >> 4) + 1; |
742 |
|
|
psiconv_progress(config,lev+2,off,"Adding %02x pixels %03x", |
743 |
|
|
repeat,value); |
744 |
|
|
for (j = 0; j < repeat; j ++) |
745 |
|
|
if ((res = psiconv_list_add(*decoded,&value))) |
746 |
|
|
goto ERROR2; |
747 |
|
|
i += 2; |
748 |
|
|
} |
749 |
|
|
psiconv_progress(config,lev,off, |
750 |
|
|
"End of RLE12 decoding process"); |
751 |
|
|
return 0; |
752 |
|
|
|
753 |
|
|
ERROR2: |
754 |
|
|
psiconv_list_free(*decoded); |
755 |
|
|
ERROR1: |
756 |
frodo |
184 |
psiconv_error(config,lev+1,off,"Decoding of RLE12 failed"); |
757 |
frodo |
179 |
if (!res) |
758 |
|
|
return -PSICONV_E_NOMEM; |
759 |
|
|
else |
760 |
|
|
return res; |
761 |
frodo |
178 |
} |
762 |
|
|
|
763 |
frodo |
179 |
int psiconv_decode_rle16 (const psiconv_config config, int lev, psiconv_u32 off, |
764 |
|
|
const psiconv_pixel_bytes encoded, |
765 |
|
|
psiconv_pixel_bytes *decoded) |
766 |
|
|
{ |
767 |
|
|
int res=0; |
768 |
|
|
psiconv_u8 *marker,*value0,*value1; |
769 |
|
|
psiconv_u32 value; |
770 |
|
|
int i,j; |
771 |
|
|
|
772 |
|
|
psiconv_progress(config,lev+1,off,"Going to decode the RLE16 encoding"); |
773 |
|
|
if (!(*decoded = psiconv_list_new(sizeof(psiconv_u8)))) |
774 |
|
|
goto ERROR1; |
775 |
|
|
|
776 |
|
|
for (i = 0; i < psiconv_list_length(encoded);) { |
777 |
|
|
psiconv_progress(config,lev+2,off,"Going to read marker byte at %04x",i); |
778 |
|
|
if (!(marker = psiconv_list_get(encoded,i))) |
779 |
|
|
goto ERROR2; |
780 |
|
|
psiconv_debug(config,lev+2,off,"Marker byte: %02x",*marker); |
781 |
|
|
if (*marker < 0x80) { |
782 |
|
|
psiconv_debug(config,lev+2,off,"Marker: repeat value word %02x times", |
783 |
|
|
*marker+1); |
784 |
|
|
psiconv_progress(config,lev+2,off,"Going to read value word at %04x",i+1); |
785 |
|
|
if (!(value0 = psiconv_list_get(encoded,i+1))) |
786 |
|
|
goto ERROR2; |
787 |
|
|
if (!(value1 = psiconv_list_get(encoded,i+2))) |
788 |
|
|
goto ERROR2; |
789 |
|
|
value = *value0 + (*value1 << 8); |
790 |
|
|
psiconv_debug(config,lev+2,off,"Value word: %02x",value); |
791 |
|
|
psiconv_progress(config,lev+2,off,"Adding %02x pixels %04x", |
792 |
|
|
*marker+1,value); |
793 |
|
|
for (j = 0; j < *marker + 1; j++) |
794 |
|
|
if ((res = psiconv_list_add(*decoded,&value))) |
795 |
|
|
goto ERROR2; |
796 |
|
|
i += 3; |
797 |
|
|
} else { |
798 |
|
|
psiconv_debug(config,lev+2,off,"Marker: %02x value words follow", |
799 |
|
|
0x100 - *marker); |
800 |
|
|
for (j = 0; j < (0x100 - *marker); j++) { |
801 |
|
|
psiconv_progress(config,lev+2,off,"Going to read value word at %04x", |
802 |
|
|
i+j*2+1); |
803 |
|
|
if (!(value0 = psiconv_list_get(encoded,i+j*2+1))) |
804 |
|
|
goto ERROR2; |
805 |
|
|
if (!(value1 = psiconv_list_get(encoded,i+j*2+2))) |
806 |
|
|
goto ERROR2; |
807 |
|
|
value = *value0 + (*value1 << 8); |
808 |
|
|
psiconv_debug(config,lev+2,off,"Value: %04x",value); |
809 |
|
|
if ((res = psiconv_list_add(*decoded,&value))) |
810 |
|
|
goto ERROR2; |
811 |
|
|
} |
812 |
|
|
i += (0x100 - *marker)*2 + 1; |
813 |
|
|
} |
814 |
|
|
} |
815 |
|
|
psiconv_progress(config,lev,off, |
816 |
|
|
"End of RLE16 decoding process"); |
817 |
|
|
return 0; |
818 |
|
|
|
819 |
|
|
ERROR2: |
820 |
|
|
psiconv_list_free(*decoded); |
821 |
|
|
ERROR1: |
822 |
frodo |
184 |
psiconv_error(config,lev+1,off,"Decoding of RLE16 failed"); |
823 |
frodo |
179 |
if (!res) |
824 |
|
|
return -PSICONV_E_NOMEM; |
825 |
|
|
else |
826 |
|
|
return res; |
827 |
|
|
} |
828 |
|
|
|
829 |
|
|
int psiconv_decode_rle24 (const psiconv_config config, int lev, psiconv_u32 off, |
830 |
|
|
const psiconv_pixel_bytes encoded, |
831 |
|
|
psiconv_pixel_bytes *decoded) |
832 |
|
|
{ |
833 |
|
|
int res=0; |
834 |
|
|
psiconv_u8 *marker,*value0,*value1,*value2; |
835 |
|
|
psiconv_u32 value; |
836 |
|
|
int i,j; |
837 |
|
|
|
838 |
|
|
psiconv_progress(config,lev+1,off,"Going to decode the RLE24 encoding"); |
839 |
|
|
if (!(*decoded = psiconv_list_new(sizeof(psiconv_u8)))) |
840 |
|
|
goto ERROR1; |
841 |
|
|
|
842 |
|
|
for (i = 0; i < psiconv_list_length(encoded);) { |
843 |
|
|
psiconv_progress(config,lev+2,off,"Going to read marker byte at %04x",i); |
844 |
|
|
if (!(marker = psiconv_list_get(encoded,i))) |
845 |
|
|
goto ERROR2; |
846 |
|
|
psiconv_debug(config,lev+2,off,"Marker byte: %02x",*marker); |
847 |
|
|
if (*marker < 0x80) { |
848 |
|
|
psiconv_debug(config,lev+2,off,"Marker: repeat value byte triplet %02x times", |
849 |
|
|
*marker+1); |
850 |
|
|
psiconv_progress(config,lev+2,off,"Going to read value byte triplet at %04x",i+1); |
851 |
|
|
if (!(value0 = psiconv_list_get(encoded,i+1))) |
852 |
|
|
goto ERROR2; |
853 |
|
|
if (!(value1 = psiconv_list_get(encoded,i+2))) |
854 |
|
|
goto ERROR2; |
855 |
|
|
if (!(value2 = psiconv_list_get(encoded,i+3))) |
856 |
|
|
goto ERROR2; |
857 |
|
|
value = *value0 + (*value1 << 8) + (*value2 << 16); |
858 |
|
|
psiconv_debug(config,lev+2,off,"Value byte triplet: %06x",value); |
859 |
|
|
psiconv_progress(config,lev+2,off,"Adding %02x pixels %06x", |
860 |
|
|
*marker+1,value); |
861 |
|
|
for (j = 0; j < *marker + 1; j++) |
862 |
|
|
if ((res = psiconv_list_add(*decoded,&value))) |
863 |
|
|
goto ERROR2; |
864 |
|
|
i += 4; |
865 |
|
|
} else { |
866 |
|
|
psiconv_debug(config,lev+2,off,"Marker: %02x value byte triplets follow", |
867 |
|
|
0x100 - *marker); |
868 |
|
|
for (j = 0; j < (0x100 - *marker); j++) { |
869 |
|
|
psiconv_progress(config,lev+2,off,"Going to read value byte triplets at %04x", |
870 |
|
|
i+j*3+1); |
871 |
|
|
if (!(value0 = psiconv_list_get(encoded,i+j*3+1))) |
872 |
|
|
goto ERROR2; |
873 |
|
|
if (!(value1 = psiconv_list_get(encoded,i+j*3+2))) |
874 |
|
|
goto ERROR2; |
875 |
|
|
if (!(value2 = psiconv_list_get(encoded,i+j*3+3))) |
876 |
|
|
goto ERROR2; |
877 |
|
|
value = *value0 + (*value1 << 8) + (*value2 << 16); |
878 |
|
|
psiconv_debug(config,lev+2,off,"Value: %06x",value); |
879 |
|
|
if ((res = psiconv_list_add(*decoded,&value))) |
880 |
|
|
goto ERROR2; |
881 |
|
|
} |
882 |
|
|
i += (0x100 - *marker)*3 + 1; |
883 |
|
|
} |
884 |
|
|
} |
885 |
|
|
psiconv_progress(config,lev,off, |
886 |
|
|
"End of RLE24 decoding process"); |
887 |
|
|
return 0; |
888 |
|
|
|
889 |
|
|
ERROR2: |
890 |
|
|
psiconv_list_free(*decoded); |
891 |
|
|
ERROR1: |
892 |
frodo |
184 |
psiconv_error(config,lev+1,off,"Decoding of RLE24 failed"); |
893 |
frodo |
179 |
if (!res) |
894 |
|
|
return -PSICONV_E_NOMEM; |
895 |
|
|
else |
896 |
|
|
return res; |
897 |
|
|
} |
898 |
|
|
|
899 |
frodo |
178 |
int psiconv_bytes_to_pixel_data(const psiconv_config config, |
900 |
|
|
int lev, psiconv_u32 off, |
901 |
|
|
const psiconv_pixel_bytes bytes, |
902 |
|
|
psiconv_pixel_ints *pixels, |
903 |
|
|
int colordepth, int xsize, int ysize) |
904 |
|
|
{ |
905 |
|
|
int res=0; |
906 |
|
|
int ibits,obits,x,y,bits; |
907 |
|
|
psiconv_u8 input; |
908 |
|
|
psiconv_u32 nr,output; |
909 |
|
|
psiconv_u8 *ientry; |
910 |
|
|
|
911 |
|
|
psiconv_progress(config,lev+1,off,"Going to convert the bytes to pixels"); |
912 |
|
|
if (!(*pixels = psiconv_list_new(sizeof(psiconv_u32)))) |
913 |
|
|
goto ERROR1; |
914 |
|
|
|
915 |
|
|
nr = 0; |
916 |
|
|
for (y = 0; y < ysize; y++) { |
917 |
|
|
/* New lines will start at longs */ |
918 |
|
|
while (nr % 4) |
919 |
|
|
nr ++; |
920 |
|
|
input = 0; |
921 |
|
|
ibits = 0; |
922 |
|
|
for (x= 0; x < xsize; x++) { |
923 |
frodo |
230 |
#ifdef LOUD |
924 |
frodo |
178 |
psiconv_progress(config,lev+2,off, |
925 |
|
|
"Processing pixel at (x,y) = (%04x,%04x)",x,y); |
926 |
frodo |
230 |
#endif |
927 |
frodo |
178 |
output = 0; |
928 |
|
|
obits = 0; |
929 |
|
|
while (obits < colordepth) { |
930 |
|
|
if (ibits == 0) { |
931 |
frodo |
230 |
#ifdef LOUD |
932 |
frodo |
178 |
psiconv_progress(config,lev+3,off, |
933 |
|
|
"Going to read byte %08x",nr); |
934 |
frodo |
230 |
#endif |
935 |
frodo |
178 |
if (!(ientry = psiconv_list_get(bytes,nr))) |
936 |
|
|
goto ERROR2; |
937 |
frodo |
230 |
#ifdef LOUD |
938 |
frodo |
178 |
psiconv_debug(config,lev+3,off,"Byte value: %02x",*ientry); |
939 |
frodo |
230 |
#endif |
940 |
frodo |
178 |
input = *ientry; |
941 |
|
|
ibits = 8; |
942 |
|
|
nr ++; |
943 |
|
|
} |
944 |
|
|
bits = ibits + obits > colordepth?colordepth-obits:ibits; |
945 |
|
|
output = output << bits; |
946 |
|
|
output |= input & ((1 << bits) - 1); |
947 |
|
|
input = input >> bits; |
948 |
|
|
ibits -= bits; |
949 |
|
|
obits += bits; |
950 |
|
|
} |
951 |
frodo |
230 |
#ifdef LOUD |
952 |
frodo |
178 |
psiconv_debug(config,lev+2,off,"Pixel value: %08x",output); |
953 |
frodo |
230 |
#endif |
954 |
frodo |
178 |
if ((res = psiconv_list_add(*pixels,&output))) |
955 |
|
|
goto ERROR2; |
956 |
|
|
} |
957 |
|
|
} |
958 |
|
|
|
959 |
|
|
psiconv_progress(config,lev,off, |
960 |
|
|
"Converting bytes to pixels completed"); |
961 |
|
|
return 0; |
962 |
|
|
|
963 |
|
|
|
964 |
|
|
ERROR2: |
965 |
|
|
psiconv_list_free(*pixels); |
966 |
|
|
ERROR1: |
967 |
frodo |
184 |
psiconv_error(config,lev+1,off,"Converting bytes to pixels failed"); |
968 |
frodo |
178 |
if (!res) |
969 |
|
|
return -PSICONV_E_NOMEM; |
970 |
|
|
else |
971 |
|
|
return res; |
972 |
|
|
} |
973 |
|
|
|
974 |
|
|
int psiconv_pixel_data_to_floats (const psiconv_config config, int lev, |
975 |
|
|
psiconv_u32 off, |
976 |
|
|
const psiconv_pixel_ints pixels, |
977 |
|
|
psiconv_pixel_floats_t *floats, |
978 |
|
|
int colordepth, int color, |
979 |
|
|
int redbits, int bluebits, int greenbits, |
980 |
|
|
const psiconv_pixel_floats_t palet) |
981 |
|
|
{ |
982 |
|
|
int res = 0; |
983 |
|
|
psiconv_u32 i; |
984 |
|
|
psiconv_u32 *pixel; |
985 |
|
|
|
986 |
|
|
psiconv_progress(config,lev+1,off,"Going to convert pixels to floats"); |
987 |
|
|
if (!((*floats).red = malloc(psiconv_list_length(pixels) * |
988 |
|
|
sizeof(*(*floats).red)))) |
989 |
|
|
goto ERROR1; |
990 |
|
|
if (!((*floats).green = malloc(psiconv_list_length(pixels) * |
991 |
|
|
sizeof(*(*floats).green)))) |
992 |
|
|
goto ERROR2; |
993 |
|
|
if (!((*floats).blue = malloc(psiconv_list_length(pixels) * |
994 |
|
|
sizeof(*(*floats).blue)))) |
995 |
|
|
goto ERROR3; |
996 |
|
|
(*floats).length = psiconv_list_length(pixels); |
997 |
|
|
|
998 |
|
|
for (i = 0; i < psiconv_list_length(pixels); i++) { |
999 |
|
|
if (!(pixel = psiconv_list_get(pixels,i))) |
1000 |
|
|
goto ERROR4; |
1001 |
frodo |
230 |
#ifdef LOUD |
1002 |
frodo |
178 |
psiconv_progress(config,lev+2,off, "Handling pixel %04x (%04x)",i,*pixel); |
1003 |
frodo |
230 |
#endif |
1004 |
frodo |
178 |
if (!palet.length) { |
1005 |
|
|
if (color) { |
1006 |
frodo |
179 |
(*floats).blue[i] = ((float) (*pixel & ((1 << bluebits) - 1))) / |
1007 |
frodo |
178 |
(1 << bluebits); |
1008 |
frodo |
179 |
(*floats).green[i] = ((float) ((*pixel >> bluebits) & |
1009 |
|
|
((1 << greenbits) - 1))) / (1 << greenbits); |
1010 |
|
|
(*floats).red[i] = ((float) ((*pixel >> (bluebits+greenbits)) & |
1011 |
|
|
((1 << redbits) - 1))) / (1 << redbits); |
1012 |
frodo |
178 |
} else { |
1013 |
|
|
(*floats).red[i] = (*floats).green[i] = |
1014 |
frodo |
179 |
(*floats).blue[i] = ((float) *pixel) / |
1015 |
|
|
(1 << colordepth); |
1016 |
frodo |
178 |
} |
1017 |
|
|
} else { |
1018 |
|
|
if (*pixel >= palet.length) { |
1019 |
|
|
psiconv_warn(config,lev+2,off, |
1020 |
|
|
"Invalid palet color found (using color 0x00)"); |
1021 |
|
|
(*floats).red[i] = palet.red[0]; |
1022 |
|
|
(*floats).green[i] = palet.green[0]; |
1023 |
|
|
(*floats).blue[i] = palet.blue[0]; |
1024 |
|
|
} else { |
1025 |
|
|
(*floats).red[i] = palet.red[*pixel]; |
1026 |
|
|
(*floats).green[i] = palet.green[*pixel]; |
1027 |
|
|
(*floats).blue[i] = palet.blue[*pixel]; |
1028 |
|
|
} |
1029 |
|
|
} |
1030 |
frodo |
230 |
#ifdef LOUD |
1031 |
frodo |
178 |
psiconv_debug(config,lev+2,off, "Pixel: Red (%f), green (%f), blue (%f)", |
1032 |
|
|
(*floats).red[i],(*floats).green[i],(*floats).blue[i]); |
1033 |
frodo |
230 |
#endif |
1034 |
frodo |
178 |
} |
1035 |
|
|
psiconv_progress(config,lev+1,off,"Finished converting pixels to floats"); |
1036 |
|
|
return 0; |
1037 |
|
|
|
1038 |
|
|
ERROR4: |
1039 |
|
|
free((*floats).blue); |
1040 |
|
|
ERROR3: |
1041 |
|
|
free((*floats).green); |
1042 |
|
|
ERROR2: |
1043 |
|
|
free((*floats).red); |
1044 |
|
|
ERROR1: |
1045 |
frodo |
184 |
psiconv_error(config,lev+1,off,"Converting pixels to floats failed"); |
1046 |
frodo |
178 |
if (!res) |
1047 |
|
|
return -PSICONV_E_NOMEM; |
1048 |
|
|
else |
1049 |
|
|
return res; |
1050 |
|
|
} |
1051 |
|
|
|
1052 |
|
|
|
1053 |
|
|
|