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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 168 Revision 178
1/* 1/*
2
2 generate_image.c - Part of psiconv, a PSION 5 file formats converter 3 generate_image.c - Part of psiconv, a PSION 5 file formats converter
3 Copyright (c) 1999, 2000 Frodo Looijaard <frodol@dds.nl> 4 Copyright (c) 1999, 2000 Frodo Looijaard <frodol@dds.nl>
4 5
5 This program is free software; you can redistribute it and/or modify 6 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 it under the terms of the GNU General Public License as published by
20#include "config.h" 21#include "config.h"
21#include "compat.h" 22#include "compat.h"
22 23
23#include "generate_routines.h" 24#include "generate_routines.h"
24#include "error.h" 25#include "error.h"
26#include "list.h"
27#include "image.h"
25 28
26#ifdef DMALLOC 29#ifdef DMALLOC
27#include <dmalloc.h> 30#include <dmalloc.h>
28#endif 31#endif
29 32
30typedef psiconv_list psiconv_pixel_bytes; /* psiconv_u8 */
31 33
32typedef psiconv_list psiconv_pixel_ints; /* of psiconv_u32 */ 34static int psiconv_collect_pixel_data(psiconv_pixel_ints *pixels,
33
34typedef struct psiconv_pixel_float_s
35{
36 float *red;
37 float *green;
38 float *blue;
39} psiconv_pixel_floats_t;
40
41static int psiconv_collect_pixel_data(const psiconv_config config,
42 psiconv_pixel_ints *pixels,int xsize,
43 int ysize, 35 int xsize,int ysize,
44 const psiconv_pixel_floats_t data, 36 const psiconv_pixel_floats_t data,
45 int colordepth, int palet_len, 37 int colordepth,int color,
38 int redbits,int greenbits,int bluebits,
46 const psiconv_pixel_floats_t palet); 39 const psiconv_pixel_floats_t palet);
47
48static int psiconv_pixel_data_to_bytes(const psiconv_config config, psiconv_pixel_bytes *bytes, int xsize, 40static int psiconv_pixel_data_to_bytes(const psiconv_config config,
41 psiconv_pixel_bytes *bytes, int xsize,
49 int ysize, const psiconv_pixel_ints pixels, 42 int ysize, const psiconv_pixel_ints pixels,
50 int colordepth); 43 int colordepth);
44static int psiconv_encode_rle8(const psiconv_config config,
45 const psiconv_pixel_bytes plain_bytes,
46 psiconv_pixel_bytes *encoded_bytes);
47static int psiconv_encode_rle12(const psiconv_config config,
48 const psiconv_pixel_bytes plain_bytes,
49 psiconv_pixel_bytes *encoded_bytes);
50static int psiconv_encode_rle16(const psiconv_config config,
51 const psiconv_pixel_bytes plain_bytes,
52 psiconv_pixel_bytes *encoded_bytes);
53static int psiconv_encode_rle24(const psiconv_config config,
54 const psiconv_pixel_bytes plain_bytes,
55 psiconv_pixel_bytes *encoded_bytes);
51 56
52float palet_grey_2_rgb[4] = {0.0/3, 1.0/3, 2.0/3, 3.0/3};
53float palet_grey_4_rgb[16] = { 0.0/15, 1.0/15, 2.0/15, 3.0/15,
54 4.0/15, 5.0/15, 6.0/15, 7.0/15,
55 8.0/15, 9.0/15, 10.0/15, 11.0/15,
56 12.0/15, 13.0/15, 14.0/15, 15.0/15};
57
58psiconv_pixel_floats_t palet_grey_2 =
59 {
60 (float *) palet_grey_2_rgb,
61 (float *) palet_grey_2_rgb,
62 (float *) palet_grey_2_rgb
63 };
64
65psiconv_pixel_floats_t palet_grey_4 =
66 {
67 (float *) palet_grey_4_rgb,
68 (float *) palet_grey_4_rgb,
69 (float *) palet_grey_4_rgb
70 };
71
72
73/* For now, we only write 2-bit non-RLE-encoded stuff */
74int psiconv_write_paint_data_section(const psiconv_config config, 57int psiconv_write_paint_data_section(const psiconv_config config,
75 psiconv_buffer buf, 58 psiconv_buffer buf,
76 const psiconv_paint_data_section value) 59 const psiconv_paint_data_section value,
60 int is_clipart)
77{ 61{
78 int res; 62 int res,colordepth,i;
79 psiconv_buffer pix_buf; 63 psiconv_pixel_ints ints;
64 psiconv_pixel_floats_t floats,palet;
65 psiconv_list bytes,bytes_rle;
66 psiconv_u8 *byteptr,encoding;
67
68 /* 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
80 106
81 if (!value) { 107 if (!value) {
82 psiconv_warn(config,0,psiconv_buffer_length(buf),"Null paint data section"); 108 psiconv_warn(config,0,psiconv_buffer_length(buf),"Null paint data section");
83 res = -PSICONV_E_GENERATE; 109 res = -PSICONV_E_GENERATE;
84 goto ERROR1; 110 goto ERROR1;
85 } 111 }
86 112
87 if (!(pix_buf = psiconv_buffer_new())) { 113 floats.red = value->red;
88 res = -PSICONV_E_NOMEM; 114 floats.green = value->green;
115 floats.blue = value->blue;
116 floats.length = value->xsize * value->ysize;
117
118 palet = psiconv_palet_none;
119 if ((config->color) && (config->redbits == 0) && (config->greenbits == 0) &&\
120 (config->bluebits == 0))
121 switch (config->colordepth) {
122 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 }
126
127 if ((res = psiconv_collect_pixel_data(&ints,value->xsize,
128 value->ysize,floats,
129 config->colordepth,config->color,
130 config->redbits,config->greenbits,
131 config->bluebits,palet)))
132 goto ERROR1;
133
134 if ((res = psiconv_pixel_data_to_bytes(config,&bytes,value->xsize,value->ysize,
135 ints,config->colordepth)))
89 goto ERROR1; 136 goto ERROR2;
137
138
139 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 }
165 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;
90 } 172 }
173 }
91 174
92 return 0; 175 if ((res = psiconv_write_u32(config,buf,
176 0x28+psiconv_list_length(bytes))))
177 goto ERROR3;
178 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 if ((res = psiconv_write_u32(config,buf,encoding)))
196 goto ERROR3;
197 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 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 }
93 209
210ERROR3:
211 psiconv_list_free(bytes);
94ERROR2: 212ERROR2:
95 psiconv_buffer_free(pix_buf); 213 psiconv_list_free(ints);
96ERROR1: 214ERROR1:
97 return res; 215 return res;
98} 216}
99 217
100/* Translate the floating point RGB information into pixel values. 218/* Translate the floating point RGB information into pixel values.
101 The palet is optional; without it, we just use the 219 The palet is optional; without it, we just use the
102 colordepth. With a large palet this is not very fast, but it will do for 220 colordepth. With a large palet this is not very fast, but it will do for
103 now. For greyscale pictures, just use the palet. */ 221 now. For greyscale pictures, just use the palet. */
104int psiconv_collect_pixel_data(const psiconv_config config, 222int psiconv_collect_pixel_data(psiconv_pixel_ints *pixels,int xsize,int ysize,
105 psiconv_pixel_ints *pixels,int xsize,int ysize,
106 const psiconv_pixel_floats_t data, 223 const psiconv_pixel_floats_t data,
107 int colordepth, int palet_len, 224 int colordepth,int color,
225 int redbits,int bluebits,int greenbits,
108 const psiconv_pixel_floats_t palet) 226 const psiconv_pixel_floats_t palet)
109{ 227{
110 int res,x,y,i; 228 int res,x,y,i;
111 psiconv_u32 index,mask,pixel; 229 psiconv_u32 index,pixel;
112 float p_red,p_green,p_blue,mult,dist,new_dist; 230 float p_red,p_green,p_blue,dist,new_dist;
113 231
114 if (!(*pixels = psiconv_list_new(sizeof(psiconv_u32)))) { 232 if (!(*pixels = psiconv_list_new(sizeof(psiconv_u32)))) {
115 res = -PSICONV_E_NOMEM; 233 res = -PSICONV_E_NOMEM;
116 goto ERROR1; 234 goto ERROR1;
117 } 235 }
118 236
119 mult = 1 << colordepth;
120 mask = mult -1;
121 for (y = 0; y < ysize; y++) { 237 for (y = 0; y < ysize; y++) {
122 for (x = 0; x < xsize; x++) { 238 for (x = 0; x < xsize; x++) {
123 index = y*ysize+x; 239 index = y*xsize+x;
124 p_red = data.red[index]; 240 p_red = data.red[index];
125 p_green = data.green[index]; 241 p_green = data.green[index];
126 p_blue = data.blue[index]; 242 p_blue = data.blue[index];
127 if (! palet_len) { 243 if (!palet.length) {
128 pixel = (((psiconv_u32) (p_red*mult) & mask) << (2*colordepth)) + 244 if (color)
129 (((psiconv_u32) (p_green*mult) & mask) << colordepth) + 245 pixel = (((psiconv_u32) (p_red * (1 << redbits) + 0.5))
130 ((psiconv_u32) (p_blue*mult) & mask); 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);
131 } else { 252 } else {
132 dist = 4; /* Max distance is 3, so this is safe */ 253 dist = 4; /* Max distance is 3, so this is safe */
133 pixel = -1; 254 pixel = -1;
134 for (i = 0; i < palet_len; i++) { 255 for (i = 0; i < palet.length; i++) {
135 new_dist = (p_red - palet.red[i]) * (p_red - palet.red[i]) + 256 new_dist = (p_red - palet.red[i]) * (p_red - palet.red[i]) +
136 (p_green - palet.green[i]) * (p_green - palet.green[i]) + 257 (p_green - palet.green[i]) * (p_green - palet.green[i]) +
137 (p_blue - palet.blue[i]) * (p_blue - palet.blue[i]); 258 (p_blue - palet.blue[i]) * (p_blue - palet.blue[i]);
138 if (new_dist < dist) { 259 if (new_dist < dist) {
139 pixel = i; 260 pixel = i;
151 psiconv_list_free(*pixels); 272 psiconv_list_free(*pixels);
152ERROR1: 273ERROR1:
153 return res; 274 return res;
154} 275}
155 276
156int psiconv_pixel_data_to_bytes(const psiconv_config config, psiconv_pixel_bytes *bytes, int xsize, 277int psiconv_pixel_data_to_bytes(const psiconv_config config,
278 psiconv_pixel_bytes *bytes, int xsize,
157 int ysize, const psiconv_pixel_ints pixels, 279 int ysize, const psiconv_pixel_ints pixels,
158 int colordepth) 280 int colordepth)
159{ 281{
160 int res; 282 int res;
161 int x,y; 283 int x,y;
162 284
163 psiconv_u32 inputdata; 285 psiconv_u32 inputdata;
164 psiconv_u8 outputbyte; 286 psiconv_u8 outputbyte;
165 psiconv_u32 *pixelptr; 287 psiconv_u32 *pixelptr;
166 int inputbitsleft,outputbitnr,bitsfit; 288 int inputbitsleft,outputbitnr,bitsfit,outputbytenr;
167 289
168 290
169 if (!bytes) { 291 if (!bytes) {
170 psiconv_warn(config,0,0,"NULL pixel data"); 292 psiconv_warn(config,0,0,"NULL pixel data");
171 res = -PSICONV_E_GENERATE; 293 res = -PSICONV_E_GENERATE;
189 311
190 312
191 outputbitnr = 0; 313 outputbitnr = 0;
192 outputbyte = 0; 314 outputbyte = 0;
193 for (y = 0; y < ysize; y++) { 315 for (y = 0; y < ysize; y++) {
316 outputbytenr = 0;
194 for (x = 0; x < xsize; x++) { 317 for (x = 0; x < xsize; x++) {
195 if (!(pixelptr = psiconv_list_get(pixels,y*xsize+x))) { 318 if (!(pixelptr = psiconv_list_get(pixels,y*xsize+x))) {
196 psiconv_warn(config,0,0,"Massive internal corruption"); 319 psiconv_warn(config,0,0,"Massive internal corruption");
197 res = -PSICONV_E_NOMEM; 320 res = -PSICONV_E_NOMEM;
198 goto ERROR2; 321 goto ERROR2;
208 if (outputbitnr == 8) { 331 if (outputbitnr == 8) {
209 if ((res = psiconv_list_add(*bytes,&outputbyte))) 332 if ((res = psiconv_list_add(*bytes,&outputbyte)))
210 goto ERROR2; 333 goto ERROR2;
211 outputbitnr = 0; 334 outputbitnr = 0;
212 outputbyte = 0; 335 outputbyte = 0;
336 outputbytenr ++;
213 } 337 }
214 } 338 }
215 } 339 }
216 /* Always end lines on a byte border */ 340 /* Always end lines on a long border */
217 if (outputbitnr != 0) { 341 if (outputbitnr != 0) {
218 if ((res = psiconv_list_add(*bytes,&outputbyte))) 342 if ((res = psiconv_list_add(*bytes,&outputbyte)))
219 goto ERROR2; 343 goto ERROR2;
220 outputbitnr = 0; 344 outputbitnr = 0;
221 outputbyte = 0; 345 outputbyte = 0;
346 outputbytenr ++;
347 }
348
349 while (outputbytenr % 0x04) {
350 if ((res = psiconv_list_add(*bytes,&outputbyte)))
351 goto ERROR2;
352 outputbytenr ++;
222 } 353 }
223 } 354 }
224 355
225 return 0; 356 return 0;
226 357
227ERROR2: 358ERROR2:
228 psiconv_list_free(*bytes); 359 psiconv_list_free(*bytes);
229ERROR1: 360ERROR1:
230 return res; 361 return res;
231} 362}
363
364/* 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 */
368int 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
445ERROR2:
446 psiconv_list_free(*encoded_bytes);
447ERROR1:
448 return res;
449}
450
451/* 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 */
454int 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
548ERROR3:
549 psiconv_list_free(*encoded_bytes);
550ERROR2:
551 psiconv_list_free(data);
552ERROR1:
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 */
560int 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
666ERROR2:
667 psiconv_list_free(*encoded_bytes);
668ERROR1:
669 return res;
670}
671
672/* 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 */
676int 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
814ERROR2:
815 psiconv_list_free(*encoded_bytes);
816ERROR1:
817 return res;
818}
819
820
821int psiconv_write_sketch_section(const psiconv_config config,
822 psiconv_buffer buf,
823 const psiconv_sketch_section value)
824{
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 if ((res = psiconv_write_paint_data_section(config,buf,value->picture,0)))
852 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
870ERROR1:
871 return res;
872}
873
874int 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
900ERROR:
901 return res;
902}
903
904int 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
931ERROR:
932 return res;
933}
934

Legend:
Removed from v.168  
changed lines
  Added in v.178

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