/[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 178 - (hide annotations)
Wed Dec 3 15:16:43 2003 UTC (20 years, 5 months ago) by frodo
Original Path: psiconv/trunk/lib/psiconv/generate_image.c
File MIME type: text/plain
File size: 27817 byte(s)
(Frodo) Enhancing image parsing

* Preparations in parse_image to do a pass-based decoding with support for
  all image formats
* Moved some stuff to image.h/image.c that is used both for the generation
  and parsing of images
* image.h is not installed

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

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