/[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 196 - (hide annotations)
Wed Feb 4 12:19:09 2004 UTC (20 years, 2 months ago) by frodo
File MIME type: text/plain
File size: 28755 byte(s)
(Frodo) Copyright dates update

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

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