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