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