/[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 174
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
31 32
32typedef psiconv_list psiconv_pixel_ints; /* of psiconv_u32 */ 33typedef psiconv_list psiconv_pixel_ints; /* of psiconv_u32 */
33 34
34typedef struct psiconv_pixel_float_s 35typedef struct psiconv_pixel_float_s
35{ 36{
37 psiconv_u32 length;
36 float *red; 38 float *red;
37 float *green; 39 float *green;
38 float *blue; 40 float *blue;
39} psiconv_pixel_floats_t; 41} psiconv_pixel_floats_t;
40 42
41static int psiconv_collect_pixel_data(const psiconv_config config, 43static int psiconv_collect_pixel_data(psiconv_pixel_ints *pixels,
42 psiconv_pixel_ints *pixels,int xsize,
43 int ysize, 44 int xsize,int ysize,
44 const psiconv_pixel_floats_t data, 45 const psiconv_pixel_floats_t data,
45 int colordepth, int palet_len, 46 int colordepth,
46 const psiconv_pixel_floats_t palet); 47 const psiconv_pixel_floats_t palet);
47
48static int psiconv_pixel_data_to_bytes(const psiconv_config config, psiconv_pixel_bytes *bytes, int xsize, 48static int psiconv_pixel_data_to_bytes(const psiconv_config config,
49 psiconv_pixel_bytes *bytes, int xsize,
49 int ysize, const psiconv_pixel_ints pixels, 50 int ysize, const psiconv_pixel_ints pixels,
50 int colordepth); 51 int colordepth);
51 52
53#define PALET_GREY_2_LEN 4
52float palet_grey_2_rgb[4] = {0.0/3, 1.0/3, 2.0/3, 3.0/3}; 54float palet_grey_2_rgb[PALET_GREY_2_LEN] = {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, 55#define PALET_GREY_4_LEN 16
56float palet_grey_4_rgb[PALET_GREY_4_LEN] =
57 { 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, 58 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, 59 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}; 60 12.0/15, 13.0/15, 14.0/15, 15.0/15};
61#define PALET_NONE_LEN 0
57 62
58psiconv_pixel_floats_t palet_grey_2 = 63psiconv_pixel_floats_t palet_grey_2 =
59 { 64 {
65 PALET_GREY_2_LEN,
60 (float *) palet_grey_2_rgb, 66 (float *) palet_grey_2_rgb,
61 (float *) palet_grey_2_rgb, 67 (float *) palet_grey_2_rgb,
62 (float *) palet_grey_2_rgb 68 (float *) palet_grey_2_rgb
63 }; 69 };
64 70
65psiconv_pixel_floats_t palet_grey_4 = 71psiconv_pixel_floats_t palet_grey_4 =
66 { 72 {
73 PALET_GREY_4_LEN,
67 (float *) palet_grey_4_rgb, 74 (float *) palet_grey_4_rgb,
68 (float *) palet_grey_4_rgb, 75 (float *) palet_grey_4_rgb,
69 (float *) palet_grey_4_rgb 76 (float *) palet_grey_4_rgb
70 }; 77 };
71 78
79psiconv_pixel_floats_t palet_none =
80 {
81 PALET_NONE_LEN,
82 NULL,
83 NULL,
84 NULL
85 };
72 86
73/* For now, we only write 2-bit non-RLE-encoded stuff */ 87
74int psiconv_write_paint_data_section(const psiconv_config config, 88int psiconv_write_paint_data_section(const psiconv_config config,
75 psiconv_buffer buf, 89 psiconv_buffer buf,
76 const psiconv_paint_data_section value) 90 const psiconv_paint_data_section value,
91 int is_clipart)
77{ 92{
78 int res; 93 int res,colordepth,i;
79 psiconv_buffer pix_buf; 94 psiconv_pixel_ints ints;
95 psiconv_pixel_floats_t floats,palet;
96 psiconv_list bytes;
97 psiconv_u8 *byteptr;
80 98
81 if (!value) { 99 if (!value) {
82 psiconv_warn(config,0,psiconv_buffer_length(buf),"Null paint data section"); 100 psiconv_warn(config,0,psiconv_buffer_length(buf),"Null paint data section");
83 res = -PSICONV_E_GENERATE; 101 res = -PSICONV_E_GENERATE;
84 goto ERROR1; 102 goto ERROR1;
85 } 103 }
86 104
87 if (!(pix_buf = psiconv_buffer_new())) { 105 floats.red = value->red;
88 res = -PSICONV_E_NOMEM; 106 floats.green = value->green;
107 floats.blue = value->blue;
108 floats.length = value->xsize * value->ysize;
109
110 switch (config->colordepth) {
111 default:
112 case 2: palet = (config->color?palet_none:palet_grey_2);
113 break;
114 case 4: palet = (config->color?palet_none:palet_grey_4);
115 break;
116 }
117
118 if ((res = psiconv_collect_pixel_data(&ints,value->xsize,
119 value->ysize,floats,
120 config->colordepth,palet)))
121 goto ERROR1;
122
123 if ((res = psiconv_pixel_data_to_bytes(config,&bytes,value->xsize,value->ysize,
124 ints,config->colordepth)))
89 goto ERROR1; 125 goto ERROR2;
90 }
91 126
92 return 0; 127 if ((res = psiconv_write_u32(config,buf,0x28+psiconv_list_length(bytes))))
128 goto ERROR3;
129 if ((res = psiconv_write_u32(config,buf,0x28)))
130 goto ERROR3;
131 if ((res = psiconv_write_u32(config,buf,value->xsize)))
132 goto ERROR3;
133 if ((res = psiconv_write_u32(config,buf,value->ysize)))
134 goto ERROR3;
135 if ((res = psiconv_write_length(config,buf,value->pic_xsize)))
136 goto ERROR3;
137 if ((res = psiconv_write_length(config,buf,value->pic_ysize)))
138 goto ERROR3;
139 colordepth = config->colordepth;
140 if ((colordepth != 2) && colordepth != 4)
141 colordepth = 2;
142 if ((res = psiconv_write_u32(config,buf,colordepth)))
143 goto ERROR3;
144 if ((res = psiconv_write_u32(config,buf,(config->color?1:0))))
145 goto ERROR3;
146 if ((res = psiconv_write_u32(config,buf,0)))
147 goto ERROR3;
148 /* Encoding: no RLE for now */
149 if ((res = psiconv_write_u32(config,buf,0)))
150 goto ERROR3;
151 if (is_clipart) {
152 if ((res = psiconv_write_u32(config,buf,0xffffffff)))
153 goto ERROR3;
154 if ((res = psiconv_write_u32(config,buf,0x00000044)))
155 goto ERROR3;
156 }
157 for (i = 0; i < psiconv_list_length(bytes); i++) {
158 if (!(byteptr = psiconv_list_get(bytes,i)))
159 goto ERROR3;
160 if ((res = psiconv_write_u8(config,buf,*byteptr)))
161 goto ERROR3;
162 }
93 163
164ERROR3:
165 psiconv_list_free(bytes);
94ERROR2: 166ERROR2:
95 psiconv_buffer_free(pix_buf); 167 psiconv_list_free(ints);
96ERROR1: 168ERROR1:
97 return res; 169 return res;
98} 170}
99 171
100/* Translate the floating point RGB information into pixel values. 172/* Translate the floating point RGB information into pixel values.
101 The palet is optional; without it, we just use the 173 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 174 colordepth. With a large palet this is not very fast, but it will do for
103 now. For greyscale pictures, just use the palet. */ 175 now. For greyscale pictures, just use the palet. */
104int psiconv_collect_pixel_data(const psiconv_config config, 176int 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, 177 const psiconv_pixel_floats_t data,
107 int colordepth, int palet_len, 178 int colordepth,
108 const psiconv_pixel_floats_t palet) 179 const psiconv_pixel_floats_t palet)
109{ 180{
110 int res,x,y,i; 181 int res,x,y,i;
111 psiconv_u32 index,mask,pixel; 182 psiconv_u32 index,pixel;
112 float p_red,p_green,p_blue,mult,dist,new_dist; 183 float p_red,p_green,p_blue,mult,dist,new_dist;
113 184
114 if (!(*pixels = psiconv_list_new(sizeof(psiconv_u32)))) { 185 if (!(*pixels = psiconv_list_new(sizeof(psiconv_u32)))) {
115 res = -PSICONV_E_NOMEM; 186 res = -PSICONV_E_NOMEM;
116 goto ERROR1; 187 goto ERROR1;
117 } 188 }
118 189
119 mult = 1 << colordepth; 190 mult = 1 << colordepth;
120 mask = mult -1;
121 for (y = 0; y < ysize; y++) { 191 for (y = 0; y < ysize; y++) {
122 for (x = 0; x < xsize; x++) { 192 for (x = 0; x < xsize; x++) {
123 index = y*ysize+x; 193 index = y*xsize+x;
124 p_red = data.red[index]; 194 p_red = data.red[index];
125 p_green = data.green[index]; 195 p_green = data.green[index];
126 p_blue = data.blue[index]; 196 p_blue = data.blue[index];
127 if (! palet_len) { 197 if (!palet.length) {
128 pixel = (((psiconv_u32) (p_red*mult) & mask) << (2*colordepth)) + 198 pixel = (((psiconv_u32) (p_red*mult+0.5)) << (2*colordepth)) +
129 (((psiconv_u32) (p_green*mult) & mask) << colordepth) + 199 (((psiconv_u32) (p_green*mult+0.5)) << colordepth) +
130 ((psiconv_u32) (p_blue*mult) & mask); 200 ((psiconv_u32) (p_blue*mult+0.5));
131 } else { 201 } else {
132 dist = 4; /* Max distance is 3, so this is safe */ 202 dist = 4; /* Max distance is 3, so this is safe */
133 pixel = -1; 203 pixel = -1;
134 for (i = 0; i < palet_len; i++) { 204 for (i = 0; i < palet.length; i++) {
135 new_dist = (p_red - palet.red[i]) * (p_red - palet.red[i]) + 205 new_dist = (p_red - palet.red[i]) * (p_red - palet.red[i]) +
136 (p_green - palet.green[i]) * (p_green - palet.green[i]) + 206 (p_green - palet.green[i]) * (p_green - palet.green[i]) +
137 (p_blue - palet.blue[i]) * (p_blue - palet.blue[i]); 207 (p_blue - palet.blue[i]) * (p_blue - palet.blue[i]);
138 if (new_dist < dist) { 208 if (new_dist < dist) {
139 pixel = i; 209 pixel = i;
151 psiconv_list_free(*pixels); 221 psiconv_list_free(*pixels);
152ERROR1: 222ERROR1:
153 return res; 223 return res;
154} 224}
155 225
156int psiconv_pixel_data_to_bytes(const psiconv_config config, psiconv_pixel_bytes *bytes, int xsize, 226int psiconv_pixel_data_to_bytes(const psiconv_config config,
227 psiconv_pixel_bytes *bytes, int xsize,
157 int ysize, const psiconv_pixel_ints pixels, 228 int ysize, const psiconv_pixel_ints pixels,
158 int colordepth) 229 int colordepth)
159{ 230{
160 int res; 231 int res;
161 int x,y; 232 int x,y;
162 233
163 psiconv_u32 inputdata; 234 psiconv_u32 inputdata;
164 psiconv_u8 outputbyte; 235 psiconv_u8 outputbyte;
165 psiconv_u32 *pixelptr; 236 psiconv_u32 *pixelptr;
166 int inputbitsleft,outputbitnr,bitsfit; 237 int inputbitsleft,outputbitnr,bitsfit,outputbytenr;
167 238
168 239
169 if (!bytes) { 240 if (!bytes) {
170 psiconv_warn(config,0,0,"NULL pixel data"); 241 psiconv_warn(config,0,0,"NULL pixel data");
171 res = -PSICONV_E_GENERATE; 242 res = -PSICONV_E_GENERATE;
189 260
190 261
191 outputbitnr = 0; 262 outputbitnr = 0;
192 outputbyte = 0; 263 outputbyte = 0;
193 for (y = 0; y < ysize; y++) { 264 for (y = 0; y < ysize; y++) {
265 outputbytenr = 0;
194 for (x = 0; x < xsize; x++) { 266 for (x = 0; x < xsize; x++) {
195 if (!(pixelptr = psiconv_list_get(pixels,y*xsize+x))) { 267 if (!(pixelptr = psiconv_list_get(pixels,y*xsize+x))) {
196 psiconv_warn(config,0,0,"Massive internal corruption"); 268 psiconv_warn(config,0,0,"Massive internal corruption");
197 res = -PSICONV_E_NOMEM; 269 res = -PSICONV_E_NOMEM;
198 goto ERROR2; 270 goto ERROR2;
208 if (outputbitnr == 8) { 280 if (outputbitnr == 8) {
209 if ((res = psiconv_list_add(*bytes,&outputbyte))) 281 if ((res = psiconv_list_add(*bytes,&outputbyte)))
210 goto ERROR2; 282 goto ERROR2;
211 outputbitnr = 0; 283 outputbitnr = 0;
212 outputbyte = 0; 284 outputbyte = 0;
285 outputbytenr ++;
213 } 286 }
214 } 287 }
215 } 288 }
216 /* Always end lines on a byte border */ 289 /* Always end lines on a long border */
217 if (outputbitnr != 0) { 290 if (outputbitnr != 0) {
218 if ((res = psiconv_list_add(*bytes,&outputbyte))) 291 if ((res = psiconv_list_add(*bytes,&outputbyte)))
219 goto ERROR2; 292 goto ERROR2;
220 outputbitnr = 0; 293 outputbitnr = 0;
221 outputbyte = 0; 294 outputbyte = 0;
295 outputbytenr ++;
296 }
297
298 while (outputbytenr % 0x04) {
299 if ((res = psiconv_list_add(*bytes,&outputbyte)))
300 goto ERROR2;
301 outputbytenr ++;
222 } 302 }
223 } 303 }
224 304
225 return 0; 305 return 0;
226 306
227ERROR2: 307ERROR2:
228 psiconv_list_free(*bytes); 308 psiconv_list_free(*bytes);
229ERROR1: 309ERROR1:
230 return res; 310 return res;
231} 311}
312
313int psiconv_write_sketch_section(const psiconv_config config,
314 psiconv_buffer buf,
315 const psiconv_sketch_section value)
316{
317 int res;
318
319 if (!value) {
320 psiconv_warn(config,0,0,"NULL sketch section");
321 res = -PSICONV_E_GENERATE;
322 goto ERROR1;
323 }
324
325 if ((res = psiconv_write_u16(config,buf,value->displayed_xsize)))
326 goto ERROR1;
327 if ((res = psiconv_write_u16(config,buf,value->displayed_ysize)))
328 goto ERROR1;
329 if ((res = psiconv_write_u16(config,buf,value->picture_data_x_offset)))
330 goto ERROR1;
331 if ((res = psiconv_write_u16(config,buf,value->picture_data_y_offset)))
332 goto ERROR1;
333 if ((res = psiconv_write_u16(config,buf,value->displayed_size_x_offset)))
334 goto ERROR1;
335 if ((res = psiconv_write_u16(config,buf,value->displayed_size_y_offset)))
336 goto ERROR1;
337 if ((res = psiconv_write_u16(config,buf,value->form_xsize)))
338 goto ERROR1;
339 if ((res = psiconv_write_u16(config,buf,value->form_ysize)))
340 goto ERROR1;
341 if ((res = psiconv_write_u16(config,buf,0x0000)))
342 goto ERROR1;
343 if ((res = psiconv_write_paint_data_section(config,buf,value->picture,0)))
344 goto ERROR1;
345 if ((res = psiconv_write_u16(config,buf,value->magnification_x * 0x03e8)))
346 goto ERROR1;
347 if ((res = psiconv_write_u16(config,buf,value->magnification_y * 0x03e8)))
348 goto ERROR1;
349 if ((res = psiconv_write_u32(config,buf,value->cut_left * 0x0c *
350 value->displayed_xsize)))
351 goto ERROR1;
352 if ((res = psiconv_write_u32(config,buf,value->cut_right * 0x0c *
353 value->displayed_xsize)))
354 goto ERROR1;
355 if ((res = psiconv_write_u32(config,buf,value->cut_top * 0x0c *
356 value->displayed_ysize)))
357 goto ERROR1;
358 if ((res = psiconv_write_u32(config,buf,value->cut_bottom * 0x0c *
359 value->displayed_ysize)))
360 goto ERROR1;
361
362ERROR1:
363 return res;
364}
365
366int psiconv_write_jumptable_section(const psiconv_config config,
367 psiconv_buffer buf,
368 const psiconv_jumptable_section value)
369{
370 int res,i;
371 psiconv_u32 *offset_ptr;
372
373
374 if (!value) {
375 psiconv_warn(config,0,psiconv_buffer_length(buf),
376 "NULL Jumptable Section");
377 res = -PSICONV_E_GENERATE;
378 goto ERROR;
379 }
380 if ((res = psiconv_write_u32(config,buf,psiconv_list_length(value))))
381 goto ERROR;
382 for (i = 0; i < psiconv_list_length(value); i++) {
383 if (!(offset_ptr = psiconv_list_get(value,i))) {
384 psiconv_warn(config,0,psiconv_buffer_length(buf),
385 "Massive memory corruption");
386 res = -PSICONV_E_NOMEM;
387 goto ERROR;
388 }
389 if ((res = psiconv_write_offset(config,buf,*offset_ptr)))
390 goto ERROR;
391 }
392
393ERROR:
394 return res;
395}
396
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.168  
changed lines
  Added in v.174

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