/[public]/psiconv/trunk/lib/psiconv/generate_image.c
ViewVC logotype

Annotation of /psiconv/trunk/lib/psiconv/generate_image.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 351 - (hide annotations)
Wed Oct 22 19:53:40 2014 UTC (9 years, 6 months ago) by frodo
File MIME type: text/plain
File size: 29225 byte(s)
(Frodo) Update copyright year in all source files

1 frodo 86 /*
2     generate_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 86
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 "generate_routines.h"
24     #include "error.h"
25 frodo 175 #include "list.h"
26 frodo 178 #include "image.h"
27 frodo 86
28 frodo 142 #ifdef DMALLOC
29     #include <dmalloc.h>
30     #endif
31    
32    
33 frodo 170 static int psiconv_collect_pixel_data(psiconv_pixel_ints *pixels,
34     int xsize,int ysize,
35 frodo 168 const psiconv_pixel_floats_t data,
36 frodo 176 int colordepth,int color,
37     int redbits,int greenbits,int bluebits,
38 frodo 168 const psiconv_pixel_floats_t palet);
39 frodo 231 static int psiconv_pixel_data_to_bytes(const psiconv_config config,int lev,
40 frodo 170 psiconv_pixel_bytes *bytes, int xsize,
41 frodo 168 int ysize, const psiconv_pixel_ints pixels,
42     int colordepth);
43 frodo 175 static int psiconv_encode_rle8(const psiconv_config config,
44     const psiconv_pixel_bytes plain_bytes,
45     psiconv_pixel_bytes *encoded_bytes);
46 frodo 176 static int psiconv_encode_rle12(const psiconv_config config,
47     const psiconv_pixel_bytes plain_bytes,
48     psiconv_pixel_bytes *encoded_bytes);
49 frodo 175 static int psiconv_encode_rle16(const psiconv_config config,
50     const psiconv_pixel_bytes plain_bytes,
51     psiconv_pixel_bytes *encoded_bytes);
52     static int psiconv_encode_rle24(const psiconv_config config,
53     const psiconv_pixel_bytes plain_bytes,
54     psiconv_pixel_bytes *encoded_bytes);
55 frodo 168
56     int psiconv_write_paint_data_section(const psiconv_config config,
57 frodo 184 psiconv_buffer buf, int lev,
58 frodo 174 const psiconv_paint_data_section value,
59     int is_clipart)
60 frodo 168 {
61 frodo 170 int res,colordepth,i;
62     psiconv_pixel_ints ints;
63     psiconv_pixel_floats_t floats,palet;
64 frodo 175 psiconv_list bytes,bytes_rle;
65     psiconv_u8 *byteptr,encoding;
66 frodo 168
67 frodo 184 psiconv_progress(config,lev,0,"Writing paint data section");
68    
69 frodo 176 /* First, we check whether we can cope with the current configuration.
70     If not, we stop at once */
71     if ((config->colordepth != 2) && (config->colordepth != 4) &&
72     (config->colordepth != 8) && (config->colordepth != 12) &&
73     (config->colordepth != 16) && (config->colordepth != 24)) {
74 frodo 231 psiconv_error(config,lev,0,
75 frodo 176 "Unsupported color depth (%d); try 2, 4, 8, 16 or 24",
76     config->colordepth);
77     res = -PSICONV_E_GENERATE;
78     goto ERROR1;
79     }
80    
81     if ((config->color) &&
82     (config->bluebits || config->redbits || config->greenbits) &&
83     (config->bluebits+config->redbits+config->greenbits!=config->colordepth)) {
84 frodo 231 psiconv_error(config,lev,0,
85 frodo 176 "Sum of red (%d), green (%d) and blue (%d) bits should be "
86     "equal to the color depth (%d)",
87     config->redbits,config->greenbits,config->bluebits,
88     config->colordepth);
89     res = -PSICONV_E_GENERATE;
90     goto ERROR1;
91     }
92    
93     if (config->color &&
94     !(config->redbits || config->greenbits || config->bluebits) &&
95     (config->colordepth != 4) && (config->colordepth != 8)) {
96 frodo 231 psiconv_error(config,lev,0,
97 frodo 176 "Current color depth (%d) has no palet associated with it",
98     config->colordepth);
99     res = -PSICONV_E_GENERATE;
100     goto ERROR1;
101     }
102    
103     if (config->color || (config->colordepth != 2))
104 frodo 231 psiconv_warn(config,lev,0,
105 frodo 176 "All image types except 2-bit greyscale are experimental!");
106    
107    
108 frodo 168 if (!value) {
109 frodo 231 psiconv_error(config,lev,0,"Null paint data section");
110 frodo 168 res = -PSICONV_E_GENERATE;
111     goto ERROR1;
112     }
113    
114 frodo 170 floats.red = value->red;
115     floats.green = value->green;
116     floats.blue = value->blue;
117     floats.length = value->xsize * value->ysize;
118    
119 frodo 178 palet = psiconv_palet_none;
120 frodo 184 if ((config->color) && (config->redbits == 0) && (config->greenbits == 0) &&
121 frodo 176 (config->bluebits == 0))
122     switch (config->colordepth) {
123 frodo 178 case 4: palet = psiconv_palet_color_4; break;
124     case 8: palet = psiconv_palet_color_8; break;
125     default: palet = psiconv_palet_none; break;
126 frodo 176 }
127 frodo 170
128     if ((res = psiconv_collect_pixel_data(&ints,value->xsize,
129     value->ysize,floats,
130 frodo 176 config->colordepth,config->color,
131     config->redbits,config->greenbits,
132 frodo 184 config->bluebits,palet))) {
133     psiconv_error(config,lev,0,"Error collecting pixel data");
134 frodo 168 goto ERROR1;
135 frodo 184 }
136 frodo 170
137 frodo 231 if ((res = psiconv_pixel_data_to_bytes(config,lev+1,&bytes,value->xsize,
138     value->ysize,ints,
139     config->colordepth))) {
140 frodo 184 psiconv_error(config,lev,0,"Error translating pixel data to bytes");
141 frodo 170 goto ERROR2;
142 frodo 184 }
143 frodo 170
144 frodo 175
145 frodo 176 switch (config->colordepth) {
146     case 2:
147     case 4:
148     case 8:
149     encoding = 0x01;
150 frodo 184 if ((res = psiconv_encode_rle8(config,bytes,&bytes_rle))) {
151     psiconv_error(config,lev,0,"Error encoding RLE8");
152 frodo 176 goto ERROR3;
153 frodo 184 }
154 frodo 176 break;
155     case 12:
156     encoding = 0x02;
157 frodo 184 if ((res = psiconv_encode_rle12(config,bytes,&bytes_rle))) {
158     psiconv_error(config,lev,0,"Error encoding RLE12");
159 frodo 176 goto ERROR3;
160 frodo 184 }
161 frodo 176 break;
162     case 16:
163     encoding = 0x03;
164 frodo 184 if ((res = psiconv_encode_rle16(config,bytes,&bytes_rle))) {
165     psiconv_error(config,lev,0,"Error encoding RLE16");
166 frodo 176 goto ERROR3;
167 frodo 184 }
168 frodo 176 break;
169     case 24:
170     encoding = 0x04;
171 frodo 184 if ((res = psiconv_encode_rle24(config,bytes,&bytes_rle))) {
172     psiconv_error(config,lev,0,"Error encoding RLE24");
173 frodo 176 goto ERROR3;
174 frodo 184 }
175 frodo 176 break;
176     default:
177     encoding = 0x00;
178 frodo 175 }
179 frodo 176 if (encoding) {
180     if (psiconv_list_length(bytes_rle) < psiconv_list_length(bytes)) {
181     psiconv_list_free(bytes);
182     bytes = bytes_rle;
183     } else {
184     psiconv_list_free(bytes_rle);
185     encoding = 0x00;
186     }
187     }
188 frodo 175
189 frodo 184 if ((res = psiconv_write_u32(config,buf,lev+1,
190 frodo 175 0x28+psiconv_list_length(bytes))))
191     goto ERROR3;
192 frodo 184 if ((res = psiconv_write_u32(config,buf,lev+1,0x28)))
193 frodo 170 goto ERROR3;
194 frodo 184 if ((res = psiconv_write_u32(config,buf,lev+1,value->xsize)))
195 frodo 170 goto ERROR3;
196 frodo 184 if ((res = psiconv_write_u32(config,buf,lev+1,value->ysize)))
197 frodo 170 goto ERROR3;
198 frodo 184 if ((res = psiconv_write_length(config,buf,lev+1,value->pic_xsize)))
199 frodo 170 goto ERROR3;
200 frodo 184 if ((res = psiconv_write_length(config,buf,lev+1,value->pic_ysize)))
201 frodo 170 goto ERROR3;
202     colordepth = config->colordepth;
203 frodo 184 if ((res = psiconv_write_u32(config,buf,lev+1,colordepth)))
204 frodo 170 goto ERROR3;
205 frodo 184 if ((res = psiconv_write_u32(config,buf,lev+1,(config->color?1:0))))
206 frodo 170 goto ERROR3;
207 frodo 184 if ((res = psiconv_write_u32(config,buf,lev+1,0)))
208 frodo 170 goto ERROR3;
209 frodo 184 if ((res = psiconv_write_u32(config,buf,lev+1,encoding)))
210 frodo 170 goto ERROR3;
211 frodo 174 if (is_clipart) {
212 frodo 184 if ((res = psiconv_write_u32(config,buf,lev+1,0xffffffff)))
213 frodo 174 goto ERROR3;
214 frodo 184 if ((res = psiconv_write_u32(config,buf,lev+1,0x00000044)))
215 frodo 174 goto ERROR3;
216     }
217 frodo 170 for (i = 0; i < psiconv_list_length(bytes); i++) {
218     if (!(byteptr = psiconv_list_get(bytes,i)))
219     goto ERROR3;
220 frodo 184 if ((res = psiconv_write_u8(config,buf,lev+1,*byteptr)))
221 frodo 170 goto ERROR3;
222 frodo 168 }
223    
224 frodo 170 ERROR3:
225     psiconv_list_free(bytes);
226 frodo 168 ERROR2:
227 frodo 170 psiconv_list_free(ints);
228 frodo 168 ERROR1:
229 frodo 231 if (res)
230     psiconv_error(config,lev,0,"Writing of paint data section failed");
231     else
232     psiconv_progress(config,lev,0,"End of paint data section");
233 frodo 168 return res;
234     }
235    
236     /* Translate the floating point RGB information into pixel values.
237     The palet is optional; without it, we just use the
238     colordepth. With a large palet this is not very fast, but it will do for
239     now. For greyscale pictures, just use the palet. */
240 frodo 170 int psiconv_collect_pixel_data(psiconv_pixel_ints *pixels,int xsize,int ysize,
241 frodo 168 const psiconv_pixel_floats_t data,
242 frodo 176 int colordepth,int color,
243     int redbits,int bluebits,int greenbits,
244 frodo 168 const psiconv_pixel_floats_t palet)
245     {
246     int res,x,y,i;
247 frodo 170 psiconv_u32 index,pixel;
248 frodo 176 float p_red,p_green,p_blue,dist,new_dist;
249 frodo 168
250     if (!(*pixels = psiconv_list_new(sizeof(psiconv_u32)))) {
251     res = -PSICONV_E_NOMEM;
252     goto ERROR1;
253     }
254    
255     for (y = 0; y < ysize; y++) {
256     for (x = 0; x < xsize; x++) {
257 frodo 170 index = y*xsize+x;
258 frodo 168 p_red = data.red[index];
259     p_green = data.green[index];
260     p_blue = data.blue[index];
261 frodo 170 if (!palet.length) {
262 frodo 176 if (color)
263     pixel = (((psiconv_u32) (p_red * (1 << redbits) + 0.5))
264     << (greenbits+bluebits)) +
265     (((psiconv_u32) (p_green * (1 << greenbits) + 0.5))
266     << bluebits) +
267     ((psiconv_u32) (p_blue * (1 << bluebits) + 0.5));
268     else
269 frodo 244 pixel = (0.212671 * p_red + 0.715160 * p_green + 0.072169 * p_blue) * ((1 << colordepth) * 0.999);
270 frodo 168 } else {
271     dist = 4; /* Max distance is 3, so this is safe */
272     pixel = -1;
273 frodo 170 for (i = 0; i < palet.length; i++) {
274 frodo 168 new_dist = (p_red - palet.red[i]) * (p_red - palet.red[i]) +
275     (p_green - palet.green[i]) * (p_green - palet.green[i]) +
276     (p_blue - palet.blue[i]) * (p_blue - palet.blue[i]);
277     if (new_dist < dist) {
278     pixel = i;
279     dist = new_dist;
280     }
281     }
282     }
283     if ((res = psiconv_list_add(*pixels,&pixel)))
284     goto ERROR2;
285     }
286     }
287     return 0;
288    
289     ERROR2:
290     psiconv_list_free(*pixels);
291     ERROR1:
292     return res;
293     }
294    
295 frodo 231 int psiconv_pixel_data_to_bytes(const psiconv_config config,int lev,
296 frodo 170 psiconv_pixel_bytes *bytes, int xsize,
297 frodo 168 int ysize, const psiconv_pixel_ints pixels,
298     int colordepth)
299     {
300     int res;
301     int x,y;
302    
303     psiconv_u32 inputdata;
304     psiconv_u8 outputbyte;
305     psiconv_u32 *pixelptr;
306 frodo 170 int inputbitsleft,outputbitnr,bitsfit,outputbytenr;
307 frodo 168
308    
309     if (!bytes) {
310 frodo 231 psiconv_error(config,lev,0,"NULL pixel data");
311 frodo 168 res = -PSICONV_E_GENERATE;
312     goto ERROR1;
313     }
314     if (!pixels) {
315 frodo 231 psiconv_error(config,lev,0,"NULL pixel data");
316 frodo 168 res = -PSICONV_E_GENERATE;
317     goto ERROR1;
318     }
319     if (psiconv_list_length(pixels) != xsize * ysize) {
320 frodo 231 psiconv_error(config,lev,0,"Pixel number is not correct");
321 frodo 168 res = -PSICONV_E_GENERATE;
322     goto ERROR1;
323     }
324    
325     if (!(*bytes = psiconv_list_new(sizeof(psiconv_u8)))) {
326     res = -PSICONV_E_NOMEM;
327     goto ERROR1;
328     }
329    
330    
331     outputbitnr = 0;
332     outputbyte = 0;
333     for (y = 0; y < ysize; y++) {
334 frodo 170 outputbytenr = 0;
335 frodo 168 for (x = 0; x < xsize; x++) {
336     if (!(pixelptr = psiconv_list_get(pixels,y*xsize+x))) {
337 frodo 233 psiconv_error(config,lev,0,"Data structure corruption");
338 frodo 168 res = -PSICONV_E_NOMEM;
339     goto ERROR2;
340     }
341     inputbitsleft = colordepth;
342     inputdata = *pixelptr;
343     while (inputbitsleft) {
344     bitsfit = (inputbitsleft+outputbitnr<=8?inputbitsleft:8-outputbitnr);
345     outputbyte |= (inputdata & ((1 << bitsfit) - 1)) << outputbitnr;
346     inputdata = inputdata >> bitsfit;
347     inputbitsleft -= bitsfit;
348     outputbitnr += bitsfit;
349     if (outputbitnr == 8) {
350     if ((res = psiconv_list_add(*bytes,&outputbyte)))
351     goto ERROR2;
352     outputbitnr = 0;
353     outputbyte = 0;
354 frodo 170 outputbytenr ++;
355 frodo 168 }
356     }
357     }
358 frodo 170 /* Always end lines on a long border */
359 frodo 168 if (outputbitnr != 0) {
360     if ((res = psiconv_list_add(*bytes,&outputbyte)))
361     goto ERROR2;
362     outputbitnr = 0;
363     outputbyte = 0;
364 frodo 170 outputbytenr ++;
365 frodo 168 }
366 frodo 170
367     while (outputbytenr % 0x04) {
368     if ((res = psiconv_list_add(*bytes,&outputbyte)))
369     goto ERROR2;
370     outputbytenr ++;
371     }
372 frodo 168 }
373    
374     return 0;
375    
376     ERROR2:
377     psiconv_list_free(*bytes);
378     ERROR1:
379     return res;
380     }
381 frodo 170
382 frodo 176 /* RLE8 encoding:
383     Marker bytes followed by one or more data bytes.
384     Marker value 0x00-0x7f: repeat the next data byte (marker+1) times
385     Marker value 0xff-0x80: (0x100-marker) data bytes follow */
386 frodo 175 int psiconv_encode_rle8(const psiconv_config config,
387     const psiconv_pixel_bytes plain_bytes,
388     psiconv_pixel_bytes *encoded_bytes)
389     {
390     int res,i,j,len;
391     psiconv_u8 *entry,*next;
392     psiconv_u8 temp;
393    
394     if (!(*encoded_bytes = psiconv_list_new(sizeof(*entry)))) {
395     res = -PSICONV_E_NOMEM;
396     goto ERROR1;
397     }
398    
399     for (i = 0; i < psiconv_list_length(plain_bytes);) {
400     if (!(entry = psiconv_list_get(plain_bytes,i))) {
401     res = -PSICONV_E_NOMEM;
402     goto ERROR2;
403     }
404     if (!(next = psiconv_list_get(plain_bytes,i+1))) {
405     res = -PSICONV_E_NOMEM;
406     goto ERROR2;
407     }
408     if (i == psiconv_list_length(plain_bytes) - 2) {
409     temp = 0xfe;
410     if ((res = psiconv_list_add(*encoded_bytes,&temp)))
411     goto ERROR2;
412     if ((res = psiconv_list_add(*encoded_bytes,entry)))
413     goto ERROR2;
414     if ((res = psiconv_list_add(*encoded_bytes,next)))
415     goto ERROR2;
416     i +=2;
417     } else if (*next == *entry) {
418 frodo 184 len = 1;
419 frodo 175 while ((*next == *entry) &&
420 frodo 184 (i+len + 2 < psiconv_list_length(plain_bytes)) &&
421 frodo 175 len < 0x80) {
422     len ++;
423     if (!(next = psiconv_list_get(plain_bytes,i+len))) {
424     res = -PSICONV_E_NOMEM;
425     goto ERROR2;
426     }
427     }
428     temp = len - 1;
429     if ((res = psiconv_list_add(*encoded_bytes,&temp)))
430     goto ERROR2;
431     if ((res = psiconv_list_add(*encoded_bytes,entry)))
432     goto ERROR2;
433     i += len;
434     } else {
435     len = 1;
436     while ((*next != *entry) &&
437     (i+len+1 < psiconv_list_length(plain_bytes)) &&
438     len < 0x80) {
439     len ++;
440     entry = next;
441     if (!(next = psiconv_list_get(plain_bytes,i+len))) {
442     res = -PSICONV_E_NOMEM;
443     goto ERROR2;
444     }
445     }
446     len --;
447     temp = 0x100 - len;
448     if ((res = psiconv_list_add(*encoded_bytes,&temp)))
449     goto ERROR2;
450     for (j = 0; j < len; j++) {
451     if (!(next = psiconv_list_get(plain_bytes,i+j))) {
452     res = -PSICONV_E_NOMEM;
453     goto ERROR2;
454     }
455     if ((res = psiconv_list_add(*encoded_bytes,next)))
456     goto ERROR2;
457     }
458     i += len;
459     }
460     }
461     return 0;
462    
463     ERROR2:
464     psiconv_list_free(*encoded_bytes);
465     ERROR1:
466     return res;
467     }
468    
469 frodo 176 /* RLE12 encoding:
470     Word based. The 12 least significant bits contain the pixel colors.
471     the 4 most signigicant bits are the number of repetitions minus 1 */
472     int psiconv_encode_rle12(const psiconv_config config,
473     const psiconv_pixel_bytes plain_bytes,
474     psiconv_pixel_bytes *encoded_bytes)
475     {
476     typedef psiconv_list psiconv_word_data; /* of psiconv_u16 */
477     psiconv_word_data data;
478     int res,i,len,location;
479     psiconv_u16 *word_entry,*word_next;
480     psiconv_u16 word_data;
481     psiconv_u8 byte_temp;
482     psiconv_u8 *byte_entry;
483    
484    
485     /* First extract the 12-bit values to encode */
486     if (!(data = psiconv_list_new(sizeof(psiconv_u16)))) {
487     res = -PSICONV_E_NOMEM;
488     goto ERROR1;
489     }
490    
491     for (i = 0; i < psiconv_list_length(plain_bytes); i++) {
492     if (!(byte_entry = psiconv_list_get(plain_bytes,i))) {
493     res = -PSICONV_E_NOMEM;
494     goto ERROR2;
495     }
496     location = 0;
497     if (location == 0) {
498     word_data = *byte_entry;
499     location ++;
500     } else if (location == 1) {
501     word_data = (word_data << 4) + (*byte_entry & 0x0f);
502     if ((res = psiconv_list_add(data,&word_data)))
503     goto ERROR2;
504     word_data = *byte_entry >> 4;
505     location ++;
506     } else {
507     word_data = (word_data << 8) + *byte_entry;
508     if ((res = psiconv_list_add(data,&word_data)))
509     goto ERROR2;
510     location = 0;
511     }
512     }
513    
514     if (!(*encoded_bytes = psiconv_list_new(sizeof(psiconv_u8)))) {
515     res = -PSICONV_E_NOMEM;
516     goto ERROR2;
517     }
518    
519     for (i = 0; i < psiconv_list_length(data);) {
520     if (!(word_entry = psiconv_list_get(data,i))) {
521     res = -PSICONV_E_NOMEM;
522     goto ERROR3;
523     }
524    
525     if (!(word_next = psiconv_list_get(data,i+1))) {
526     res = -PSICONV_E_NOMEM;
527     goto ERROR3;
528     }
529    
530     if (i == psiconv_list_length(data) - 2) {
531     byte_temp = *word_entry && 0xff;
532     if ((res = psiconv_list_add(*encoded_bytes,&byte_temp)))
533     goto ERROR3;
534     byte_temp = *word_entry >> 8;
535     if ((res = psiconv_list_add(*encoded_bytes,&byte_temp)))
536     goto ERROR3;
537     byte_temp = *word_next && 0xff;
538     if ((res = psiconv_list_add(*encoded_bytes,&byte_temp)))
539     goto ERROR3;
540     byte_temp = *word_next >> 8;
541     if ((res = psiconv_list_add(*encoded_bytes,&byte_temp)))
542     goto ERROR3;
543     i += 2;
544     }
545    
546     len = 0;
547     while ((*word_entry == *word_next) && (len < 16) &&
548     (i+len+1 < psiconv_list_length(data))) {
549     len ++;
550     if (!(word_next = psiconv_list_get(data,i+len))) {
551     res = -PSICONV_E_NOMEM;
552     goto ERROR3;
553     }
554     }
555    
556     byte_temp = *word_entry && 0xff;
557     if ((res = psiconv_list_add(*encoded_bytes,&byte_temp)))
558     goto ERROR3;
559     byte_temp = (*word_entry >> 8) + ((len - 1) << 4);
560     if ((res = psiconv_list_add(*encoded_bytes,&byte_temp)))
561     goto ERROR3;
562     i += len;
563     }
564     return 0;
565    
566     ERROR3:
567     psiconv_list_free(*encoded_bytes);
568     ERROR2:
569     psiconv_list_free(data);
570     ERROR1:
571     return res;
572     }
573    
574     /* RLE16 encoding:
575     Marker bytes followed by one or more data words.
576     Marker value 0x00-0x7f: repeat the next data word (marker+1) times
577     Marker value 0xff-0x80: (0x100-marker) data words follow */
578 frodo 175 int psiconv_encode_rle16(const psiconv_config config,
579     const psiconv_pixel_bytes plain_bytes,
580     psiconv_pixel_bytes *encoded_bytes)
581     {
582     int res,i,j,len;
583     psiconv_u8 *entry1,*entry2,*next1,*next2;
584     psiconv_u8 temp;
585    
586     if (!(*encoded_bytes = psiconv_list_new(sizeof(*entry1)))) {
587     res = -PSICONV_E_NOMEM;
588     goto ERROR1;
589     }
590    
591     for (i = 0; i < psiconv_list_length(plain_bytes);) {
592     if (!(entry1 = psiconv_list_get(plain_bytes,i))) {
593     res = -PSICONV_E_NOMEM;
594     goto ERROR2;
595     }
596     if (!(entry2 = psiconv_list_get(plain_bytes,i+1))) {
597     res = -PSICONV_E_NOMEM;
598     goto ERROR2;
599     }
600     if (!(next1 = psiconv_list_get(plain_bytes,i+2))) {
601     res = -PSICONV_E_NOMEM;
602     goto ERROR2;
603     }
604     if (!(next2 = psiconv_list_get(plain_bytes,i+3))) {
605     res = -PSICONV_E_NOMEM;
606     goto ERROR2;
607     }
608     if (i == psiconv_list_length(plain_bytes) - 4) {
609     temp = 0xfe;
610     if ((res = psiconv_list_add(*encoded_bytes,&temp)))
611     goto ERROR2;
612     if ((res = psiconv_list_add(*encoded_bytes,entry1)))
613     goto ERROR2;
614     if ((res = psiconv_list_add(*encoded_bytes,entry2)))
615     goto ERROR2;
616     if ((res = psiconv_list_add(*encoded_bytes,next1)))
617     goto ERROR2;
618     if ((res = psiconv_list_add(*encoded_bytes,next2)))
619     goto ERROR2;
620     i +=4;
621     } else if ((*next1 == *entry1) && (*next2 == *entry2)) {
622     len = 0;
623     while (((*next1 == *entry1) && (*next2 == *entry2)) &&
624     (i+2*len + 4 < psiconv_list_length(plain_bytes)) &&
625     len < 0x80) {
626     len ++;
627     if (!(next1 = psiconv_list_get(plain_bytes,i+len*2))) {
628     res = -PSICONV_E_NOMEM;
629     goto ERROR2;
630     }
631     if (!(next2 = psiconv_list_get(plain_bytes,i+len*2+1))) {
632     res = -PSICONV_E_NOMEM;
633     goto ERROR2;
634     }
635     }
636     temp = len - 1;
637     if ((res = psiconv_list_add(*encoded_bytes,&temp)))
638     goto ERROR2;
639     if ((res = psiconv_list_add(*encoded_bytes,entry1)))
640     goto ERROR2;
641     if ((res = psiconv_list_add(*encoded_bytes,entry2)))
642     goto ERROR2;
643     i += len*2;
644     } else {
645     len = 1;
646     while (((*next1 != *entry1) || (*next2 != *entry2))&&
647     (i+len*2+4 < psiconv_list_length(plain_bytes)) &&
648     len < 0x80) {
649     len ++;
650     entry1 = next1;
651     entry2 = next2;
652     if (!(next1 = psiconv_list_get(plain_bytes,i+len*2))) {
653     res = -PSICONV_E_NOMEM;
654     goto ERROR2;
655     }
656     if (!(next2 = psiconv_list_get(plain_bytes,i+len*2+1))) {
657     res = -PSICONV_E_NOMEM;
658     goto ERROR2;
659     }
660     }
661     len --;
662     temp = 0x100 - len;
663     if ((res = psiconv_list_add(*encoded_bytes,&temp)))
664     goto ERROR2;
665     for (j = 0; j < len; j++) {
666     if (!(next1 = psiconv_list_get(plain_bytes,i+j*2))) {
667     res = -PSICONV_E_NOMEM;
668     goto ERROR2;
669     }
670     if (!(next2 = psiconv_list_get(plain_bytes,i+j*2+1))) {
671     res = -PSICONV_E_NOMEM;
672     goto ERROR2;
673     }
674     if ((res = psiconv_list_add(*encoded_bytes,next1)))
675     goto ERROR2;
676     if ((res = psiconv_list_add(*encoded_bytes,next2)))
677     goto ERROR2;
678     }
679     i += len*2;
680     }
681     }
682     return 0;
683    
684     ERROR2:
685     psiconv_list_free(*encoded_bytes);
686     ERROR1:
687     return res;
688     }
689    
690 frodo 176 /* RLE24 encoding:
691     Marker bytes followed by one or more data byte-triplets.
692     Marker value 0x00-0x7f: repeat the next data byte-triplets (marker+1) times
693     Marker value 0xff-0x80: (0x100-marker) data byte-triplets follow */
694 frodo 175 int psiconv_encode_rle24(const psiconv_config config,
695     const psiconv_pixel_bytes plain_bytes,
696     psiconv_pixel_bytes *encoded_bytes)
697     {
698     int res,i,j,len;
699     psiconv_u8 *entry1,*entry2,*entry3,*next1,*next2,*next3;
700     psiconv_u8 temp;
701    
702     if (!(*encoded_bytes = psiconv_list_new(sizeof(*entry1)))) {
703     res = -PSICONV_E_NOMEM;
704     goto ERROR1;
705     }
706    
707     for (i = 0; i < psiconv_list_length(plain_bytes);) {
708     if (!(entry1 = psiconv_list_get(plain_bytes,i))) {
709     res = -PSICONV_E_NOMEM;
710     goto ERROR2;
711     }
712     if (!(entry2 = psiconv_list_get(plain_bytes,i+1))) {
713     res = -PSICONV_E_NOMEM;
714     goto ERROR2;
715     }
716     if (!(entry3 = psiconv_list_get(plain_bytes,i+2))) {
717     res = -PSICONV_E_NOMEM;
718     goto ERROR2;
719     }
720     if (!(next1 = psiconv_list_get(plain_bytes,i+3))) {
721     res = -PSICONV_E_NOMEM;
722     goto ERROR2;
723     }
724     if (!(next2 = psiconv_list_get(plain_bytes,i+4))) {
725     res = -PSICONV_E_NOMEM;
726     goto ERROR2;
727     }
728     if (!(next3 = psiconv_list_get(plain_bytes,i+5))) {
729     res = -PSICONV_E_NOMEM;
730     goto ERROR2;
731     }
732     if (i == psiconv_list_length(plain_bytes) - 6) {
733     temp = 0xfe;
734     if ((res = psiconv_list_add(*encoded_bytes,&temp)))
735     goto ERROR2;
736     if ((res = psiconv_list_add(*encoded_bytes,entry1)))
737     goto ERROR2;
738     if ((res = psiconv_list_add(*encoded_bytes,entry2)))
739     goto ERROR2;
740     if ((res = psiconv_list_add(*encoded_bytes,entry3)))
741     goto ERROR2;
742     if ((res = psiconv_list_add(*encoded_bytes,next1)))
743     goto ERROR2;
744     if ((res = psiconv_list_add(*encoded_bytes,next2)))
745     goto ERROR2;
746     if ((res = psiconv_list_add(*encoded_bytes,next3)))
747     goto ERROR2;
748     i +=4;
749     } else if ((*next1 == *entry1) && (*next2 == *entry2) &&
750     (*next3 == *entry3)) {
751     len = 0;
752     while (((*next1 == *entry1) && (*next2 == *entry2) &&
753     (*next3 == *entry3)) &&
754     (i+3*len + 6 < psiconv_list_length(plain_bytes)) &&
755     len < 0x80) {
756     len ++;
757     if (!(next1 = psiconv_list_get(plain_bytes,i+len*3))) {
758     res = -PSICONV_E_NOMEM;
759     goto ERROR2;
760     }
761     if (!(next2 = psiconv_list_get(plain_bytes,i+len*3+1))) {
762     res = -PSICONV_E_NOMEM;
763     goto ERROR2;
764     }
765     if (!(next3 = psiconv_list_get(plain_bytes,i+len*3+2))) {
766     res = -PSICONV_E_NOMEM;
767     goto ERROR2;
768     }
769     }
770     temp = len - 1;
771     if ((res = psiconv_list_add(*encoded_bytes,&temp)))
772     goto ERROR2;
773     if ((res = psiconv_list_add(*encoded_bytes,entry1)))
774     goto ERROR2;
775     if ((res = psiconv_list_add(*encoded_bytes,entry2)))
776     goto ERROR2;
777     if ((res = psiconv_list_add(*encoded_bytes,entry3)))
778     goto ERROR2;
779     i += len*3;
780     } else {
781     len = 1;
782     while (((*next1 != *entry1) || (*next2 != *entry2) ||
783     (*next3 != *entry3)) &&
784     (i+len*3+6 < psiconv_list_length(plain_bytes)) &&
785     len < 0x80) {
786     len ++;
787     entry1 = next1;
788     entry2 = next2;
789     entry3 = next3;
790     if (!(next1 = psiconv_list_get(plain_bytes,i+len*3))) {
791     res = -PSICONV_E_NOMEM;
792     goto ERROR2;
793     }
794     if (!(next2 = psiconv_list_get(plain_bytes,i+len*3+1))) {
795     res = -PSICONV_E_NOMEM;
796     goto ERROR2;
797     }
798     if (!(next3 = psiconv_list_get(plain_bytes,i+len*3+2))) {
799     res = -PSICONV_E_NOMEM;
800     goto ERROR2;
801     }
802     }
803     len --;
804     temp = 0x100 - len;
805     if ((res = psiconv_list_add(*encoded_bytes,&temp)))
806     goto ERROR2;
807     for (j = 0; j < len; j++) {
808     if (!(next1 = psiconv_list_get(plain_bytes,i+j*3))) {
809     res = -PSICONV_E_NOMEM;
810     goto ERROR2;
811     }
812     if (!(next2 = psiconv_list_get(plain_bytes,i+j*3+1))) {
813     res = -PSICONV_E_NOMEM;
814     goto ERROR2;
815     }
816     if (!(next2 = psiconv_list_get(plain_bytes,i+j*3+2))) {
817     res = -PSICONV_E_NOMEM;
818     goto ERROR2;
819     }
820     if ((res = psiconv_list_add(*encoded_bytes,next1)))
821     goto ERROR2;
822     if ((res = psiconv_list_add(*encoded_bytes,next2)))
823     goto ERROR2;
824     if ((res = psiconv_list_add(*encoded_bytes,next3)))
825     goto ERROR2;
826     }
827     i += len*3;
828     }
829     }
830     return 0;
831    
832     ERROR2:
833     psiconv_list_free(*encoded_bytes);
834     ERROR1:
835     return res;
836     }
837    
838    
839 frodo 170 int psiconv_write_sketch_section(const psiconv_config config,
840 frodo 184 psiconv_buffer buf, int lev,
841 frodo 171 const psiconv_sketch_section value)
842 frodo 170 {
843     int res;
844    
845 frodo 184 psiconv_progress(config,lev,0,"Writing sketch section");
846 frodo 170 if (!value) {
847 frodo 231 psiconv_error(config,lev,0,"NULL sketch section");
848 frodo 170 res = -PSICONV_E_GENERATE;
849     goto ERROR1;
850     }
851    
852 frodo 184 if ((res = psiconv_write_u16(config,buf,lev+1,value->displayed_xsize)))
853 frodo 170 goto ERROR1;
854 frodo 184 if ((res = psiconv_write_u16(config,buf,lev+1,value->displayed_ysize)))
855 frodo 170 goto ERROR1;
856 frodo 184 if ((res = psiconv_write_u16(config,buf,lev+1,value->picture_data_x_offset)))
857 frodo 170 goto ERROR1;
858 frodo 184 if ((res = psiconv_write_u16(config,buf,lev+1,value->picture_data_y_offset)))
859 frodo 170 goto ERROR1;
860 frodo 184 if ((res = psiconv_write_u16(config,buf,lev+1,value->displayed_size_x_offset)))
861 frodo 170 goto ERROR1;
862 frodo 184 if ((res = psiconv_write_u16(config,buf,lev+1,value->displayed_size_y_offset)))
863 frodo 170 goto ERROR1;
864 frodo 184 if ((res = psiconv_write_u16(config,buf,lev+1,value->form_xsize)))
865 frodo 170 goto ERROR1;
866 frodo 184 if ((res = psiconv_write_u16(config,buf,lev+1,value->form_ysize)))
867 frodo 170 goto ERROR1;
868 frodo 184 if ((res = psiconv_write_u16(config,buf,lev+1,0x0000)))
869 frodo 170 goto ERROR1;
870 frodo 184 if ((res = psiconv_write_paint_data_section(config,buf,lev+1,value->picture,0)))
871 frodo 170 goto ERROR1;
872 frodo 184 if ((res = psiconv_write_u16(config,buf,lev+1,value->magnification_x * 0x03e8)))
873 frodo 170 goto ERROR1;
874 frodo 184 if ((res = psiconv_write_u16(config,buf,lev+1,value->magnification_y * 0x03e8)))
875 frodo 170 goto ERROR1;
876 frodo 184 if ((res = psiconv_write_u32(config,buf,lev+1,value->cut_left * 0x0c *
877 frodo 170 value->displayed_xsize)))
878     goto ERROR1;
879 frodo 184 if ((res = psiconv_write_u32(config,buf,lev+1,value->cut_right * 0x0c *
880 frodo 170 value->displayed_xsize)))
881     goto ERROR1;
882 frodo 184 if ((res = psiconv_write_u32(config,buf,lev+1,value->cut_top * 0x0c *
883 frodo 170 value->displayed_ysize)))
884     goto ERROR1;
885 frodo 184 if ((res = psiconv_write_u32(config,buf,lev+1,value->cut_bottom * 0x0c *
886 frodo 170 value->displayed_ysize)))
887     goto ERROR1;
888    
889     ERROR1:
890 frodo 231 if (res)
891     psiconv_error(config,lev,0,"Writing of sketch section failed");
892     else
893     psiconv_progress(config,lev,0,"End of sketch section");
894 frodo 170 return res;
895     }
896 frodo 171
897 frodo 175 int psiconv_write_clipart_section(const psiconv_config config,
898 frodo 184 psiconv_buffer buf, int lev,
899 frodo 175 const psiconv_clipart_section value)
900     {
901     int res;
902    
903 frodo 184 psiconv_progress(config,lev,0,"Writing clipart section");
904 frodo 175 if (!value) {
905 frodo 231 psiconv_error(config,lev,0, "NULL Clipart Section");
906 frodo 175 res = -PSICONV_E_GENERATE;
907     goto ERROR;
908     }
909 frodo 184 if ((res = psiconv_write_u32(config,buf,lev+1,PSICONV_ID_CLIPART_ITEM)))
910 frodo 175 goto ERROR;
911 frodo 184 if ((res = psiconv_write_u32(config,buf,lev+1,0x00000002)))
912 frodo 175 goto ERROR;
913 frodo 184 if ((res = psiconv_write_u32(config,buf,lev+1,0x00000000)))
914 frodo 175 goto ERROR;
915 frodo 184 if ((res = psiconv_write_u32(config,buf,lev+1,0x00000000)))
916 frodo 175 goto ERROR;
917 frodo 184 if ((res = psiconv_write_u32(config,buf,lev+1,0x0000000C)))
918 frodo 175 goto ERROR;
919 frodo 184 if ((res = psiconv_write_paint_data_section(config,buf,lev+1,value->picture,1)))
920 frodo 175 goto ERROR;
921    
922     ERROR:
923 frodo 231 if (res)
924     psiconv_error(config,lev,0,"Writing of clipart section failed");
925     else
926     psiconv_progress(config,lev,0,"End of clipart section");
927 frodo 175 return res;
928     }
929    
930 frodo 171 int psiconv_write_jumptable_section(const psiconv_config config,
931 frodo 184 psiconv_buffer buf, int lev,
932 frodo 171 const psiconv_jumptable_section value)
933     {
934     int res,i;
935     psiconv_u32 *offset_ptr;
936    
937 frodo 184 psiconv_progress(config,lev,0,"Writing jumptable section");
938 frodo 171
939     if (!value) {
940 frodo 231 psiconv_error(config,lev,0,"NULL Jumptable Section");
941 frodo 171 res = -PSICONV_E_GENERATE;
942     goto ERROR;
943     }
944 frodo 184 if ((res = psiconv_write_u32(config,buf,lev+1,psiconv_list_length(value))))
945 frodo 171 goto ERROR;
946     for (i = 0; i < psiconv_list_length(value); i++) {
947     if (!(offset_ptr = psiconv_list_get(value,i))) {
948 frodo 231 psiconv_error(config,lev,0,"Massive memory corruption");
949 frodo 171 res = -PSICONV_E_NOMEM;
950     goto ERROR;
951     }
952 frodo 184 if ((res = psiconv_write_offset(config,buf,lev+1,*offset_ptr)))
953 frodo 171 goto ERROR;
954     }
955    
956     ERROR:
957 frodo 231 if (res)
958     psiconv_error(config,lev,0,"Writing of jumptable section failed");
959     else
960     psiconv_progress(config,lev,0,"End of jumptable section");
961 frodo 171 return res;
962     }

frodo@frodo.looijaard.name
ViewVC Help
Powered by ViewVC 1.1.26