/[public]/psiconv/tags/rel-0-9-9/lib/psiconv/generate_image.c
ViewVC logotype

Annotation of /psiconv/tags/rel-0-9-9/lib/psiconv/generate_image.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 184 - (hide annotations)
Tue Jan 6 20:15:01 2004 UTC (20 years, 3 months ago) by frodo
Original Path: psiconv/trunk/lib/psiconv/generate_image.c
File MIME type: text/plain
File size: 28757 byte(s)
(Frodo) Unicode transition

Note: this commit breaks psiconv. The programs in the extra directory should
work properly.

  * Change all datastructures to use unicode for character encodings
  * Added psiconv_error function
  * Called psiconv_error at places where a warning was stupid
  * Added psiconv_progress in all generate functions
  * Added lev parameter to all generate functions
  * Removed general.h from CVS (we have general.h.in, after all)
  * Probably other stuff I forgot

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

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