/[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 351 - (show annotations)
Wed Oct 22 19:53:40 2014 UTC (9 years, 5 months ago) by frodo
File MIME type: text/plain
File size: 29225 byte(s)
(Frodo) Update copyright year in all source files

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

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