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

Legend:
Removed from v.174  
changed lines
  Added in v.184

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