1 /*
2     parse_image.c - Part of psiconv, a PSION 5 file formats converter
3     Copyright (c) 1999-2014  Frodo Looijaard <frodo@frodo.looijaard.name>
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 /* Extreme debugging info */
34 #undef LOUD
35 
36 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 
41 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 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 
psiconv_parse_jumptable_section(const psiconv_config config,const psiconv_buffer buf,int lev,psiconv_u32 off,int * length,psiconv_jumptable_section * result)72 int psiconv_parse_jumptable_section(const psiconv_config config,
73                                     const psiconv_buffer buf,int lev,
74                                     psiconv_u32 off, int *length,
75                                     psiconv_jumptable_section *result)
76 {
77   int res = 0;
78   int len = 0;
79   psiconv_u32 listlen,temp;
80   int i;
81 
82   psiconv_progress(config,lev+1,off+len,"Going to read the jumptable section");
83   if (!((*result) = psiconv_list_new(sizeof(psiconv_u32))))
84     goto ERROR1;
85 
86   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   if (res)
89     goto ERROR2;
90   psiconv_debug(config,lev+2,off+len,"List length: %08x",listlen);
91   len += 4;
92 
93   psiconv_progress(config,lev+2,off+len,"Going to read the list");
94   for (i = 0; i < listlen; i++) {
95     temp = psiconv_read_u32(config,buf,lev+2,off+len,&res);
96     if (res)
97       goto ERROR2;
98     if ((res = psiconv_list_add(*result,&temp)))
99       goto ERROR2;
100     psiconv_debug(config,lev+3,off+len,"Offset: %08x",temp);
101     len += 4;
102   }
103 
104   if (length)
105     *length = len;
106 
107   psiconv_progress(config,lev+1,off+len-1,"End of jumptable section "
108                    "(total length: %08x)", len);
109 
110   return 0;
111 
112 ERROR2:
113   psiconv_list_free(*result);
114 ERROR1:
115   psiconv_error(config,lev+1,off,"Reading of Jumptable Section failed");
116   if (length)
117     *length = 0;
118    if (!res)
119      return -PSICONV_E_NOMEM;
120    else
121     return res;
122 }
123 
psiconv_parse_paint_data_section(const psiconv_config config,const psiconv_buffer buf,int lev,psiconv_u32 off,int * length,int isclipart,psiconv_paint_data_section * result)124 int psiconv_parse_paint_data_section(const psiconv_config config,
125                                      const psiconv_buffer buf,int lev,
126                                      psiconv_u32 off, int *length,int isclipart,
127                                      psiconv_paint_data_section *result)
128 {
129   int res = 0;
130   int len = 0;
131   psiconv_u32 size,offset,temp,datasize,color,
132               redbits,bluebits,greenbits;
133   psiconv_u8 byte;
134   int leng,i;
135   psiconv_u32 bits_per_pixel,compression;
136   psiconv_pixel_bytes bytes,decoded;
137   psiconv_pixel_ints pixels;
138   psiconv_pixel_floats_t floats,palet;
139 
140   psiconv_progress(config,lev+1,off,"Going to read a paint data section");
141   if (!((*result) = malloc(sizeof(**result))))
142     goto ERROR1;
143 
144   if (!(bytes = psiconv_list_new(sizeof(psiconv_u8))))
145     goto ERROR2;
146 
147   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   if (res)
150     goto ERROR3;
151   psiconv_debug(config,lev+2,off+len,"Section size: %08x",size);
152   len += 4;
153 
154   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   if (res)
157     goto ERROR3;
158   if (offset != 0x28) {
159     psiconv_error(config,lev+2,off+len,
160                  "Paint data section data offset has unexpected value");
161     psiconv_debug(config,lev+2,off+len,
162                   "Data offset: read %08x, expected %08x",offset,0x28);
163     res = -1;
164   }
165   len += 4;
166 
167   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   if (res)
170     goto ERROR3;
171   psiconv_debug(config,lev+2,off+len,"Picture X size: %08x:",(*result)->xsize);
172   len += 4;
173 
174   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   if (res)
177     goto ERROR3;
178   psiconv_debug(config,lev+2,off+len,"Picture Y size: %08x:",(*result)->ysize);
179   len += 4;
180 
181   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   if (res)
184     goto ERROR3;
185   psiconv_debug(config,lev+2,off+len,"Picture x size: %f",(*result)->pic_xsize);
186   len += leng;
187 
188   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   if (res)
191     goto ERROR3;
192   psiconv_debug(config,lev+2,off+len,"Picture y size: %f",(*result)->pic_ysize);
193   len += leng;
194 
195   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   if (res)
198     goto ERROR3;
199   psiconv_debug(config,lev+2,off+len,"Bits per pixel: %d",bits_per_pixel);
200   len += 4;
201 
202   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   }
217   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 
230   psiconv_progress(config,lev+2,off+len,
231                    "Going to read whether RLE compression is used");
232   compression=psiconv_read_u32(config,buf,lev+2,off+len,&res);
233   if (res)
234     goto ERROR3;
235   if (compression > 4) {
236     psiconv_warn(config,lev+2,off+len,"Paint data section has unknown "
237                                "compression type, assuming RLE");
238     psiconv_debug(config,lev+2,off+len,"Read compression type %d",compression);
239     compression = 0;
240   }
241   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   len += 4;
245 
246   if (isclipart) {
247     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     if (res)
250       goto ERROR3;
251     if (temp != 0xffffffff) {
252       psiconv_warn(config,lev+2,off+len,
253                    "Paint data section prologue has unknown values (ignoring)");
254       psiconv_debug(config,lev+2,off+len,
255                     "Read %08x, expected %08x",temp, 0xffffffff);
256     }
257     len += 4;
258     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     if (res)
261       goto ERROR3;
262     if (temp != 0x44) {
263       psiconv_warn(config,lev+2,off+len,
264                    "Paint data section prologue has unknown values (ignoring)");
265       psiconv_debug(config,lev+2,off+len,
266                     "read %08x, expected %08x",temp, 0x44);
267     }
268     len += 4;
269   }
270 
271   len = offset;
272   datasize = size - len;
273   if (isclipart)
274     len += 8;
275 
276   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   psiconv_progress(config,lev+2,off+len,"Going to read the pixel data");
281   for (i = 0; i < datasize; i++) {
282     byte = psiconv_read_u8(config,buf,lev+2,off+len+i,&res);
283 #ifdef LOUD
284     psiconv_debug(config,lev+2,off+len+i,
285 	          "Pixel byte %04x of %04x has value %02x",
286 	          i,datasize,byte);
287 #endif
288     if (res)
289       goto ERROR3;
290     psiconv_list_add(bytes,&byte);
291   }
292   len += datasize;
293 
294   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   }
320 
321   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 
326   /* 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   if (length)
354     *length = len;
355 
356   psiconv_progress(config,lev,off+len-1,
357                    "End of Paint Data Section (total length: %08x)", len);
358 
359   return 0;
360 
361 ERROR4:
362   psiconv_list_free(pixels);
363 ERROR3:
364   psiconv_list_free(bytes);
365 ERROR2:
366   free(*result);
367 ERROR1:
368   psiconv_error(config,lev+1,off,"Reading of Paint Data Section failed");
369   if (length)
370     *length = 0;
371    if (!res)
372      return -PSICONV_E_NOMEM;
373    else
374     return res;
375 }
376 
psiconv_parse_sketch_section(const psiconv_config config,const psiconv_buffer buf,int lev,psiconv_u32 off,int * length,psiconv_sketch_section * result)377 int psiconv_parse_sketch_section(const psiconv_config config,
378                                  const psiconv_buffer buf, int lev,
379                                  psiconv_u32 off, int *length,
380                                  psiconv_sketch_section *result)
381 {
382   int res=0;
383   int len=0;
384   psiconv_u32 temp;
385   int leng;
386 
387   psiconv_progress(config,lev+1,off,"Going to read the sketch section");
388   if (!(*result = malloc(sizeof(**result))))
389     goto ERROR1;
390 
391   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   if (res)
394     goto ERROR2;
395   psiconv_debug(config,lev+2,off+len,"Displayed hor. size: %04x",
396                 (*result)->displayed_xsize);
397   len += 0x02;
398   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   if (res)
401     goto ERROR2;
402   psiconv_debug(config,lev+2,off+len,"Displayed ver. size: %04x",
403                 (*result)->displayed_ysize);
404   len += 0x02;
405 
406   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 					&res);
409   if (res)
410     goto ERROR2;
411   psiconv_debug(config,lev+2,off+len,"Data hor. offset: %04x",
412                 (*result)->picture_data_x_offset);
413   len += 0x02;
414   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 						&res);
417   if (res)
418     goto ERROR2;
419   psiconv_debug(config,lev+2,off+len,"Data ver. offset: %04x",
420                 (*result)->picture_data_y_offset);
421   len += 0x02;
422 
423   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 							&res);
426   if (res)
427     goto ERROR2;
428   psiconv_debug(config,lev+2,off+len,"Displayed hor. offset: %04x",
429                 (*result)->displayed_size_x_offset);
430   len += 0x02;
431   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 					  &res);
434   if (res)
435     goto ERROR2;
436   psiconv_debug(config,lev+2,off+len,"Displayed ver. offset: %04x",
437                 (*result)->displayed_size_y_offset);
438   len += 0x02;
439 
440   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   if (res)
443     goto ERROR2;
444   psiconv_debug(config,lev+2,off+len,"Form hor. size: %04x",
445                 (*result)->form_xsize);
446   len += 0x02;
447   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   if (res)
450     goto ERROR2;
451   psiconv_debug(config,lev+2,off+len,"Form ver. size: %04x",
452                 (*result)->form_ysize);
453   len += 0x02;
454 
455   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   if (res)
458     goto ERROR2;
459   if (temp != 0) {
460     psiconv_warn(config,lev+2,off+len,
461                  "Unexpected value in sketch section preamble (ignored)");
462     psiconv_debug(config,lev+2,off+len,"Read %04x, expected %04x",
463                   temp,0);
464   }
465   off += 0x02;
466 
467   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                                           &((*result)->picture))))
470     goto ERROR2;
471   off += leng;
472 
473   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   if (res)
476     goto ERROR3;
477   psiconv_debug(config,lev+2,off+len,"Form hor. magnification: %f",
478                 (*result)->magnification_x);
479   len += 0x02;
480   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   if (res)
483     goto ERROR3;
484   psiconv_debug(config,lev+2,off+len,"Form ver. magnification: %f",
485                 (*result)->magnification_y);
486   len += 0x02;
487 
488   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   if (res)
491     goto ERROR3;
492   (*result)->cut_left = (temp * 6.0) / (*result)->displayed_xsize;
493   psiconv_debug(config,lev+2,off+len,"Left cut: raw %08x, real: %f",
494                 temp,(*result)->cut_left);
495   len += 0x04;
496   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   if (res)
499     goto ERROR3;
500   (*result)->cut_right = (temp * 6.0) / (*result)->displayed_xsize;
501   psiconv_debug(config,lev+2,off+len,"Right cut: raw %08x, real: %f",
502                 temp,(*result)->cut_right);
503   len += 0x04;
504   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   if (res)
507     goto ERROR3;
508   (*result)->cut_top = (temp * 6.0) / (*result)->displayed_ysize;
509   psiconv_debug(config,lev+2,off+len,"Top cut: raw %08x, real: %f",
510                 temp,(*result)->cut_top);
511   len += 0x04;
512   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   if (res)
515     goto ERROR3;
516   (*result)->cut_bottom = (temp * 6.0) / (*result)->displayed_ysize;
517   psiconv_debug(config,lev+2,off+len,"Bottom cut: raw %08x, real: %f",
518                 temp,(*result)->cut_bottom);
519   len += 0x04;
520 
521   if (length)
522     *length = len;
523 
524   psiconv_progress(config,lev,off+len-1,
525                    "End of sketch section (total length: %08x)", len);
526 
527   return res;
528 ERROR3:
529   psiconv_free_paint_data_section((*result)->picture);
530 ERROR2:
531   free (*result);
532 ERROR1:
533   psiconv_error(config,lev+1,off,"Reading of Sketch Section failed");
534   if (length)
535     *length = 0;
536    if (!res)
537      return -PSICONV_E_NOMEM;
538    else
539     return res;
540 }
541 
542 
psiconv_parse_clipart_section(const psiconv_config config,const psiconv_buffer buf,int lev,psiconv_u32 off,int * length,psiconv_clipart_section * result)543 int psiconv_parse_clipart_section(const psiconv_config config,
544                                   const psiconv_buffer buf,int lev,
545                                   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   psiconv_progress(config,lev+1,off+len,"Going to read the clipart section");
554   if (!(*result = malloc(sizeof(**result))))
555     goto ERROR1;
556 
557   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   if (res)
560     goto ERROR2;
561   if (temp != PSICONV_ID_CLIPART_ITEM) {
562     psiconv_warn(config,lev+2,off+len,
563                  "Unexpected value in clipart section preamble (ignored)");
564     psiconv_debug(config,lev+2,off+len,"Read %08x, expected %08x",temp,
565                   PSICONV_ID_CLIPART_ITEM);
566   } else
567     psiconv_debug(config,lev+2,off+len,"Clipart ID: %08x", temp);
568   off += 4;
569 
570   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   if (res)
573     goto ERROR2;
574   if (temp != 0x02) {
575     psiconv_warn(config,lev+2,off+len,
576                  "Unexpected value in clipart section preamble (ignored)");
577     psiconv_debug(config,lev+2,off+len,"Read %08x, expected %08x",temp,
578                   0x02);
579   } else
580     psiconv_debug(config,lev+2,off+len,"First unknown long: %08x", temp);
581   off += 4;
582 
583   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   if (res)
586     goto ERROR2;
587   if (temp != 0) {
588     psiconv_warn(config,lev+2,off+len,
589                  "Unexpected value in clipart section preamble (ignored)");
590     psiconv_debug(config,lev+2,off+len,"Read %08x, expected %08x",temp, 0);
591   } else
592     psiconv_debug(config,lev+2,off+len,"Second unknown long: %08x", temp);
593   off += 4;
594 
595   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   if (res)
598     goto ERROR2;
599   if (temp != 0) {
600     psiconv_warn(config,lev+2,off+len,
601                  "Unexpected value in clipart section preamble (ignored)");
602     psiconv_debug(config,lev+2,off+len,"Read %08x, expected %08x",temp, 0);
603   } else
604     psiconv_debug(config,lev+2,off+len,"Third unknown long: %08x", temp);
605   off += 4;
606 
607   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   if (res)
610     goto ERROR2;
611   if ((temp != 0x0c) && (temp != 0x08)) {
612     psiconv_warn(config,lev+2,off+len,
613                  "Unexpected value in clipart section preamble (ignored)");
614     psiconv_debug(config,lev+2,off+len,"Read %08x, expected %08x or %08x",temp,
615                    0x0c, 0x08);
616   } else
617     psiconv_debug(config,lev+2,off+len,"Fourth unknown long: %08x", temp);
618   off += 4;
619 
620   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                                           &((*result)->picture))))
623     goto ERROR2;
624   len += leng;
625 
626   if (length)
627     *length = len;
628 
629   psiconv_progress(config,lev,off+len-1,
630                    "End of clipart section (total length: %08x)", len);
631   return 0;
632 
633 ERROR2:
634   free (*result);
635 ERROR1:
636   psiconv_error(config,lev+1,off,"Reading of Font failed");
637   if (length)
638     *length = 0;
639    if (!res)
640      return -PSICONV_E_NOMEM;
641    else
642     return res;
643 }
644 
psiconv_decode_rle8(const psiconv_config config,int lev,psiconv_u32 off,const psiconv_pixel_bytes encoded,psiconv_pixel_bytes * decoded)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 #ifdef LOUD
659     psiconv_progress(config,lev+2,off,"Going to read marker byte at %04x",i);
660 #endif
661     if (!(marker = psiconv_list_get(encoded,i)))
662       goto ERROR2;
663 #ifdef LOUD
664     psiconv_debug(config,lev+2,off,"Marker byte: %02x",*marker);
665 #endif
666     if (*marker < 0x80) {
667 #ifdef LOUD
668       psiconv_debug(config,lev+2,off,"Marker: repeat value byte %02x times",
669 	            *marker+1); */
670       psiconv_progress(config,lev+2,off,"Going to read value byte at %04x",i+1);
671 #endif
672       if (!(value = psiconv_list_get(encoded,i+1)))
673 	goto ERROR2;
674 #ifdef LOUD
675       psiconv_debug(config,lev+2,off,"Value byte: %02x",*value);
676       psiconv_progress(config,lev+2,off,"Adding %02x pixels %02x",
677 	               *marker+1,*value);
678 #endif
679       for (j = 0; j < *marker + 1; j++)
680         if ((res = psiconv_list_add(*decoded,value)))
681 	  goto ERROR2;
682       i += 2;
683     } else {
684 #ifdef LOUD
685       psiconv_debug(config,lev+2,off,"Marker: %02x value bytes follow",
686 	            0x100 - *marker);
687 #endif
688       for (j = 0; j < (0x100 - *marker); j++) {
689 #ifdef LOUD
690 	psiconv_progress(config,lev+2,off,"Going to read value byte at %04x",
691 	                 i+j+1);
692 #endif
693 	if (!(value = psiconv_list_get(encoded,i+j+1)))
694 	  goto ERROR2;
695 #ifdef LOUD
696 	 psiconv_debug(config,lev+2,off,"Value: %02x",*value);
697 #endif
698 	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   psiconv_error(config,lev+1,off,"Decoding of RLE8 failed");
712    if (!res)
713      return -PSICONV_E_NOMEM;
714    else
715     return res;
716 }
717 
psiconv_decode_rle12(const psiconv_config config,int lev,psiconv_u32 off,const psiconv_pixel_bytes encoded,psiconv_pixel_bytes * decoded)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   psiconv_error(config,lev+1,off,"Decoding of RLE12 failed");
755    if (!res)
756      return -PSICONV_E_NOMEM;
757    else
758     return res;
759 }
760 
psiconv_decode_rle16(const psiconv_config config,int lev,psiconv_u32 off,const psiconv_pixel_bytes encoded,psiconv_pixel_bytes * decoded)761 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   psiconv_error(config,lev+1,off,"Decoding of RLE16 failed");
821    if (!res)
822      return -PSICONV_E_NOMEM;
823    else
824     return res;
825 }
826 
psiconv_decode_rle24(const psiconv_config config,int lev,psiconv_u32 off,const psiconv_pixel_bytes encoded,psiconv_pixel_bytes * decoded)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   psiconv_error(config,lev+1,off,"Decoding of RLE24 failed");
891    if (!res)
892      return -PSICONV_E_NOMEM;
893    else
894     return res;
895 }
896 
psiconv_bytes_to_pixel_data(const psiconv_config config,int lev,psiconv_u32 off,const psiconv_pixel_bytes bytes,psiconv_pixel_ints * pixels,int colordepth,int xsize,int ysize)897 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 #ifdef LOUD
922       psiconv_progress(config,lev+2,off,
923 	               "Processing pixel at (x,y) = (%04x,%04x)",x,y);
924 #endif
925       output = 0;
926       obits = 0;
927       while (obits < colordepth) {
928 	if (ibits == 0) {
929 #ifdef LOUD
930 	  psiconv_progress(config,lev+3,off,
931 	                   "Going to read byte %08x",nr);
932 #endif
933 	  if (!(ientry = psiconv_list_get(bytes,nr)))
934 	    goto ERROR2;
935 #ifdef LOUD
936 	  psiconv_debug(config,lev+3,off,"Byte value: %02x",*ientry);
937 #endif
938 	  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 #ifdef LOUD
950       psiconv_debug(config,lev+2,off,"Pixel value: %08x",output);
951 #endif
952       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   psiconv_error(config,lev+1,off,"Converting bytes to pixels failed");
966   if (!res)
967     return -PSICONV_E_NOMEM;
968   else
969     return res;
970 }
971 
psiconv_pixel_data_to_floats(const psiconv_config config,int lev,psiconv_u32 off,const psiconv_pixel_ints pixels,psiconv_pixel_floats_t * floats,int colordepth,int color,int redbits,int bluebits,int greenbits,const psiconv_pixel_floats_t palet)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 #ifdef LOUD
1000     psiconv_progress(config,lev+2,off, "Handling pixel %04x (%04x)",i,*pixel);
1001 #endif
1002     if (!palet.length) {
1003       if (color) {
1004 	(*floats).blue[i] = ((float) (*pixel & ((1 << bluebits) - 1))) /
1005 	             ((1 << bluebits) - 1);
1006 	(*floats).green[i] = ((float) ((*pixel >> bluebits) &
1007    		            ((1 << greenbits) - 1))) / ((1 << greenbits) - 1);
1008 	(*floats).red[i] = ((float) ((*pixel >> (bluebits+greenbits)) &
1009                             ((1 << redbits) - 1))) / ((1 << redbits) - 1);
1010       } else {
1011         (*floats).red[i] = (*floats).green[i] =
1012 	                (*floats).blue[i] = ((float) *pixel) /
1013 			                     ((1 << colordepth) - 1);
1014       }
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 #ifdef LOUD
1029     psiconv_debug(config,lev+2,off, "Pixel: Red (%f), green (%f), blue (%f)",
1030 	          (*floats).red[i],(*floats).green[i],(*floats).blue[i]);
1031 #endif
1032   }
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   psiconv_error(config,lev+1,off,"Converting pixels to floats failed");
1044   if (!res)
1045     return -PSICONV_E_NOMEM;
1046   else
1047     return res;
1048 }
1049 
1050 
1051 
1052