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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 196 - (show 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 /*
2 generate_image.c - Part of psiconv, a PSION 5 file formats converter
3 Copyright (c) 1999-2004 Frodo Looijaard <frodol@dds.nl>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include "config.h"
21 #include "compat.h"
22
23 #include "generate_routines.h"
24 #include "error.h"
25 #include "list.h"
26 #include "image.h"
27
28 #ifdef DMALLOC
29 #include <dmalloc.h>
30 #endif
31
32
33 static int psiconv_collect_pixel_data(psiconv_pixel_ints *pixels,
34 int xsize,int ysize,
35 const psiconv_pixel_floats_t data,
36 int colordepth,int color,
37 int redbits,int greenbits,int bluebits,
38 const psiconv_pixel_floats_t palet);
39 static int psiconv_pixel_data_to_bytes(const psiconv_config config,
40 psiconv_pixel_bytes *bytes, int xsize,
41 int ysize, const psiconv_pixel_ints pixels,
42 int colordepth);
43 static int psiconv_encode_rle8(const psiconv_config config,
44 const psiconv_pixel_bytes plain_bytes,
45 psiconv_pixel_bytes *encoded_bytes);
46 static int psiconv_encode_rle12(const psiconv_config config,
47 const psiconv_pixel_bytes plain_bytes,
48 psiconv_pixel_bytes *encoded_bytes);
49 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
56 int psiconv_write_paint_data_section(const psiconv_config config,
57 psiconv_buffer buf, int lev,
58 const psiconv_paint_data_section value,
59 int is_clipart)
60 {
61 int res,colordepth,i;
62 psiconv_pixel_ints ints;
63 psiconv_pixel_floats_t floats,palet;
64 psiconv_list bytes,bytes_rle;
65 psiconv_u8 *byteptr,encoding;
66
67 psiconv_progress(config,lev,0,"Writing paint data section");
68
69 /* 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 psiconv_error(config,0,psiconv_buffer_length(buf),
75 "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 psiconv_error(config,0,psiconv_buffer_length(buf),
85 "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 psiconv_error(config,0,psiconv_buffer_length(buf),
97 "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 if (!value) {
109 psiconv_error(config,0,psiconv_buffer_length(buf),"Null paint data section");
110 res = -PSICONV_E_GENERATE;
111 goto ERROR1;
112 }
113
114 floats.red = value->red;
115 floats.green = value->green;
116 floats.blue = value->blue;
117 floats.length = value->xsize * value->ysize;
118
119 palet = psiconv_palet_none;
120 if ((config->color) && (config->redbits == 0) && (config->greenbits == 0) &&
121 (config->bluebits == 0))
122 switch (config->colordepth) {
123 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 }
127
128 if ((res = psiconv_collect_pixel_data(&ints,value->xsize,
129 value->ysize,floats,
130 config->colordepth,config->color,
131 config->redbits,config->greenbits,
132 config->bluebits,palet))) {
133 psiconv_error(config,lev,0,"Error collecting pixel data");
134 goto ERROR1;
135 }
136
137 if ((res = psiconv_pixel_data_to_bytes(config,&bytes,value->xsize,value->ysize,
138 ints,config->colordepth))) {
139 psiconv_error(config,lev,0,"Error translating pixel data to bytes");
140 goto ERROR2;
141 }
142
143
144 switch (config->colordepth) {
145 case 2:
146 case 4:
147 case 8:
148 encoding = 0x01;
149 if ((res = psiconv_encode_rle8(config,bytes,&bytes_rle))) {
150 psiconv_error(config,lev,0,"Error encoding RLE8");
151 goto ERROR3;
152 }
153 break;
154 case 12:
155 encoding = 0x02;
156 if ((res = psiconv_encode_rle12(config,bytes,&bytes_rle))) {
157 psiconv_error(config,lev,0,"Error encoding RLE12");
158 goto ERROR3;
159 }
160 break;
161 case 16:
162 encoding = 0x03;
163 if ((res = psiconv_encode_rle16(config,bytes,&bytes_rle))) {
164 psiconv_error(config,lev,0,"Error encoding RLE16");
165 goto ERROR3;
166 }
167 break;
168 case 24:
169 encoding = 0x04;
170 if ((res = psiconv_encode_rle24(config,bytes,&bytes_rle))) {
171 psiconv_error(config,lev,0,"Error encoding RLE24");
172 goto ERROR3;
173 }
174 break;
175 default:
176 encoding = 0x00;
177 }
178 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
188 if ((res = psiconv_write_u32(config,buf,lev+1,
189 0x28+psiconv_list_length(bytes))))
190 goto ERROR3;
191 if ((res = psiconv_write_u32(config,buf,lev+1,0x28)))
192 goto ERROR3;
193 if ((res = psiconv_write_u32(config,buf,lev+1,value->xsize)))
194 goto ERROR3;
195 if ((res = psiconv_write_u32(config,buf,lev+1,value->ysize)))
196 goto ERROR3;
197 if ((res = psiconv_write_length(config,buf,lev+1,value->pic_xsize)))
198 goto ERROR3;
199 if ((res = psiconv_write_length(config,buf,lev+1,value->pic_ysize)))
200 goto ERROR3;
201 colordepth = config->colordepth;
202 if ((res = psiconv_write_u32(config,buf,lev+1,colordepth)))
203 goto ERROR3;
204 if ((res = psiconv_write_u32(config,buf,lev+1,(config->color?1:0))))
205 goto ERROR3;
206 if ((res = psiconv_write_u32(config,buf,lev+1,0)))
207 goto ERROR3;
208 if ((res = psiconv_write_u32(config,buf,lev+1,encoding)))
209 goto ERROR3;
210 if (is_clipart) {
211 if ((res = psiconv_write_u32(config,buf,lev+1,0xffffffff)))
212 goto ERROR3;
213 if ((res = psiconv_write_u32(config,buf,lev+1,0x00000044)))
214 goto ERROR3;
215 }
216 for (i = 0; i < psiconv_list_length(bytes); i++) {
217 if (!(byteptr = psiconv_list_get(bytes,i)))
218 goto ERROR3;
219 if ((res = psiconv_write_u8(config,buf,lev+1,*byteptr)))
220 goto ERROR3;
221 }
222
223 ERROR3:
224 psiconv_list_free(bytes);
225 ERROR2:
226 psiconv_list_free(ints);
227 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 int psiconv_collect_pixel_data(psiconv_pixel_ints *pixels,int xsize,int ysize,
236 const psiconv_pixel_floats_t data,
237 int colordepth,int color,
238 int redbits,int bluebits,int greenbits,
239 const psiconv_pixel_floats_t palet)
240 {
241 int res,x,y,i;
242 psiconv_u32 index,pixel;
243 float p_red,p_green,p_blue,dist,new_dist;
244
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 index = y*xsize+x;
253 p_red = data.red[index];
254 p_green = data.green[index];
255 p_blue = data.blue[index];
256 if (!palet.length) {
257 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 } else {
266 dist = 4; /* Max distance is 3, so this is safe */
267 pixel = -1;
268 for (i = 0; i < palet.length; i++) {
269 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 int psiconv_pixel_data_to_bytes(const psiconv_config config,
291 psiconv_pixel_bytes *bytes, int xsize,
292 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 int inputbitsleft,outputbitnr,bitsfit,outputbytenr;
302
303
304 if (!bytes) {
305 psiconv_error(config,0,0,"NULL pixel data");
306 res = -PSICONV_E_GENERATE;
307 goto ERROR1;
308 }
309 if (!pixels) {
310 psiconv_error(config,0,0,"NULL pixel data");
311 res = -PSICONV_E_GENERATE;
312 goto ERROR1;
313 }
314 if (psiconv_list_length(pixels) != xsize * ysize) {
315 psiconv_error(config,0,0,"Pixel number is not correct");
316 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 outputbytenr = 0;
330 for (x = 0; x < xsize; x++) {
331 if (!(pixelptr = psiconv_list_get(pixels,y*xsize+x))) {
332 psiconv_error(config,0,0,"Massive internal corruption");
333 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 outputbytenr ++;
350 }
351 }
352 }
353 /* Always end lines on a long border */
354 if (outputbitnr != 0) {
355 if ((res = psiconv_list_add(*bytes,&outputbyte)))
356 goto ERROR2;
357 outputbitnr = 0;
358 outputbyte = 0;
359 outputbytenr ++;
360 }
361
362 while (outputbytenr % 0x04) {
363 if ((res = psiconv_list_add(*bytes,&outputbyte)))
364 goto ERROR2;
365 outputbytenr ++;
366 }
367 }
368
369 return 0;
370
371 ERROR2:
372 psiconv_list_free(*bytes);
373 ERROR1:
374 return res;
375 }
376
377 /* 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 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 len = 1;
414 while ((*next == *entry) &&
415 (i+len + 2 < psiconv_list_length(plain_bytes)) &&
416 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 /* 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 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 /* 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 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 int psiconv_write_sketch_section(const psiconv_config config,
835 psiconv_buffer buf, int lev,
836 const psiconv_sketch_section value)
837 {
838 int res;
839
840 psiconv_progress(config,lev,0,"Writing sketch section");
841 if (!value) {
842 psiconv_error(config,0,0,"NULL sketch section");
843 res = -PSICONV_E_GENERATE;
844 goto ERROR1;
845 }
846
847 if ((res = psiconv_write_u16(config,buf,lev+1,value->displayed_xsize)))
848 goto ERROR1;
849 if ((res = psiconv_write_u16(config,buf,lev+1,value->displayed_ysize)))
850 goto ERROR1;
851 if ((res = psiconv_write_u16(config,buf,lev+1,value->picture_data_x_offset)))
852 goto ERROR1;
853 if ((res = psiconv_write_u16(config,buf,lev+1,value->picture_data_y_offset)))
854 goto ERROR1;
855 if ((res = psiconv_write_u16(config,buf,lev+1,value->displayed_size_x_offset)))
856 goto ERROR1;
857 if ((res = psiconv_write_u16(config,buf,lev+1,value->displayed_size_y_offset)))
858 goto ERROR1;
859 if ((res = psiconv_write_u16(config,buf,lev+1,value->form_xsize)))
860 goto ERROR1;
861 if ((res = psiconv_write_u16(config,buf,lev+1,value->form_ysize)))
862 goto ERROR1;
863 if ((res = psiconv_write_u16(config,buf,lev+1,0x0000)))
864 goto ERROR1;
865 if ((res = psiconv_write_paint_data_section(config,buf,lev+1,value->picture,0)))
866 goto ERROR1;
867 if ((res = psiconv_write_u16(config,buf,lev+1,value->magnification_x * 0x03e8)))
868 goto ERROR1;
869 if ((res = psiconv_write_u16(config,buf,lev+1,value->magnification_y * 0x03e8)))
870 goto ERROR1;
871 if ((res = psiconv_write_u32(config,buf,lev+1,value->cut_left * 0x0c *
872 value->displayed_xsize)))
873 goto ERROR1;
874 if ((res = psiconv_write_u32(config,buf,lev+1,value->cut_right * 0x0c *
875 value->displayed_xsize)))
876 goto ERROR1;
877 if ((res = psiconv_write_u32(config,buf,lev+1,value->cut_top * 0x0c *
878 value->displayed_ysize)))
879 goto ERROR1;
880 if ((res = psiconv_write_u32(config,buf,lev+1,value->cut_bottom * 0x0c *
881 value->displayed_ysize)))
882 goto ERROR1;
883
884 ERROR1:
885 return res;
886 }
887
888 int psiconv_write_clipart_section(const psiconv_config config,
889 psiconv_buffer buf, int lev,
890 const psiconv_clipart_section value)
891 {
892 int res;
893
894 psiconv_progress(config,lev,0,"Writing clipart section");
895 if (!value) {
896 psiconv_error(config,0,psiconv_buffer_length(buf),
897 "NULL Clipart Section");
898 res = -PSICONV_E_GENERATE;
899 goto ERROR;
900 }
901 if ((res = psiconv_write_u32(config,buf,lev+1,PSICONV_ID_CLIPART_ITEM)))
902 goto ERROR;
903 if ((res = psiconv_write_u32(config,buf,lev+1,0x00000002)))
904 goto ERROR;
905 if ((res = psiconv_write_u32(config,buf,lev+1,0x00000000)))
906 goto ERROR;
907 if ((res = psiconv_write_u32(config,buf,lev+1,0x00000000)))
908 goto ERROR;
909 if ((res = psiconv_write_u32(config,buf,lev+1,0x0000000C)))
910 goto ERROR;
911 if ((res = psiconv_write_paint_data_section(config,buf,lev+1,value->picture,1)))
912 goto ERROR;
913
914 ERROR:
915 return res;
916 }
917
918 int psiconv_write_jumptable_section(const psiconv_config config,
919 psiconv_buffer buf, int lev,
920 const psiconv_jumptable_section value)
921 {
922 int res,i;
923 psiconv_u32 *offset_ptr;
924
925 psiconv_progress(config,lev,0,"Writing jumptable section");
926
927 if (!value) {
928 psiconv_error(config,0,psiconv_buffer_length(buf),
929 "NULL Jumptable Section");
930 res = -PSICONV_E_GENERATE;
931 goto ERROR;
932 }
933 if ((res = psiconv_write_u32(config,buf,lev+1,psiconv_list_length(value))))
934 goto ERROR;
935 for (i = 0; i < psiconv_list_length(value); i++) {
936 if (!(offset_ptr = psiconv_list_get(value,i))) {
937 psiconv_error(config,0,psiconv_buffer_length(buf),
938 "Massive memory corruption");
939 res = -PSICONV_E_NOMEM;
940 goto ERROR;
941 }
942 if ((res = psiconv_write_offset(config,buf,lev+1,*offset_ptr)))
943 goto ERROR;
944 }
945
946 ERROR:
947 return res;
948 }
949

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