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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 174 - (hide annotations)
Thu Nov 27 12:08:13 2003 UTC (20 years, 5 months ago) by frodo
File MIME type: text/plain
File size: 12563 byte(s)
(Frodo) Clipart generation

1 frodo 86 /*
2 frodo 174
3 frodo 86 generate_image.c - Part of psiconv, a PSION 5 file formats converter
4     Copyright (c) 1999, 2000 Frodo Looijaard <frodol@dds.nl>
5    
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10    
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     GNU General Public License for more details.
15    
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19     */
20    
21     #include "config.h"
22     #include "compat.h"
23    
24     #include "generate_routines.h"
25     #include "error.h"
26    
27 frodo 142 #ifdef DMALLOC
28     #include <dmalloc.h>
29     #endif
30    
31 frodo 168 typedef psiconv_list psiconv_pixel_bytes; /* psiconv_u8 */
32 frodo 142
33 frodo 168 typedef psiconv_list psiconv_pixel_ints; /* of psiconv_u32 */
34    
35     typedef struct psiconv_pixel_float_s
36     {
37 frodo 170 psiconv_u32 length;
38 frodo 168 float *red;
39     float *green;
40     float *blue;
41     } psiconv_pixel_floats_t;
42    
43 frodo 170 static int psiconv_collect_pixel_data(psiconv_pixel_ints *pixels,
44     int xsize,int ysize,
45 frodo 168 const psiconv_pixel_floats_t data,
46 frodo 170 int colordepth,
47 frodo 168 const psiconv_pixel_floats_t palet);
48 frodo 170 static int psiconv_pixel_data_to_bytes(const psiconv_config config,
49     psiconv_pixel_bytes *bytes, int xsize,
50 frodo 168 int ysize, const psiconv_pixel_ints pixels,
51     int colordepth);
52    
53 frodo 170 #define PALET_GREY_2_LEN 4
54     float palet_grey_2_rgb[PALET_GREY_2_LEN] = {0.0/3, 1.0/3, 2.0/3, 3.0/3};
55     #define PALET_GREY_4_LEN 16
56     float palet_grey_4_rgb[PALET_GREY_4_LEN] =
57     { 0.0/15, 1.0/15, 2.0/15, 3.0/15,
58 frodo 168 4.0/15, 5.0/15, 6.0/15, 7.0/15,
59     8.0/15, 9.0/15, 10.0/15, 11.0/15,
60     12.0/15, 13.0/15, 14.0/15, 15.0/15};
61 frodo 170 #define PALET_NONE_LEN 0
62 frodo 168
63     psiconv_pixel_floats_t palet_grey_2 =
64     {
65 frodo 170 PALET_GREY_2_LEN,
66 frodo 168 (float *) palet_grey_2_rgb,
67     (float *) palet_grey_2_rgb,
68     (float *) palet_grey_2_rgb
69     };
70    
71     psiconv_pixel_floats_t palet_grey_4 =
72     {
73 frodo 170 PALET_GREY_4_LEN,
74 frodo 168 (float *) palet_grey_4_rgb,
75     (float *) palet_grey_4_rgb,
76     (float *) palet_grey_4_rgb
77     };
78    
79 frodo 170 psiconv_pixel_floats_t palet_none =
80     {
81     PALET_NONE_LEN,
82     NULL,
83     NULL,
84     NULL
85     };
86 frodo 168
87 frodo 170
88 frodo 168 int psiconv_write_paint_data_section(const psiconv_config config,
89 frodo 170 psiconv_buffer buf,
90 frodo 174 const psiconv_paint_data_section value,
91     int is_clipart)
92 frodo 168 {
93 frodo 170 int res,colordepth,i;
94     psiconv_pixel_ints ints;
95     psiconv_pixel_floats_t floats,palet;
96     psiconv_list bytes;
97     psiconv_u8 *byteptr;
98 frodo 168
99     if (!value) {
100     psiconv_warn(config,0,psiconv_buffer_length(buf),"Null paint data section");
101     res = -PSICONV_E_GENERATE;
102     goto ERROR1;
103     }
104    
105 frodo 170 floats.red = value->red;
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 frodo 168 goto ERROR1;
122 frodo 170
123     if ((res = psiconv_pixel_data_to_bytes(config,&bytes,value->xsize,value->ysize,
124     ints,config->colordepth)))
125     goto ERROR2;
126    
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 frodo 174 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 frodo 170 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 frodo 168 }
163    
164 frodo 170 ERROR3:
165     psiconv_list_free(bytes);
166 frodo 168 ERROR2:
167 frodo 170 psiconv_list_free(ints);
168 frodo 168 ERROR1:
169     return res;
170     }
171    
172     /* Translate the floating point RGB information into pixel values.
173     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
175     now. For greyscale pictures, just use the palet. */
176 frodo 170 int psiconv_collect_pixel_data(psiconv_pixel_ints *pixels,int xsize,int ysize,
177 frodo 168 const psiconv_pixel_floats_t data,
178 frodo 170 int colordepth,
179 frodo 168 const psiconv_pixel_floats_t palet)
180     {
181     int res,x,y,i;
182 frodo 170 psiconv_u32 index,pixel;
183 frodo 168 float p_red,p_green,p_blue,mult,dist,new_dist;
184    
185     if (!(*pixels = psiconv_list_new(sizeof(psiconv_u32)))) {
186     res = -PSICONV_E_NOMEM;
187     goto ERROR1;
188     }
189    
190     mult = 1 << colordepth;
191     for (y = 0; y < ysize; y++) {
192     for (x = 0; x < xsize; x++) {
193 frodo 170 index = y*xsize+x;
194 frodo 168 p_red = data.red[index];
195     p_green = data.green[index];
196     p_blue = data.blue[index];
197 frodo 170 if (!palet.length) {
198     pixel = (((psiconv_u32) (p_red*mult+0.5)) << (2*colordepth)) +
199     (((psiconv_u32) (p_green*mult+0.5)) << colordepth) +
200     ((psiconv_u32) (p_blue*mult+0.5));
201 frodo 168 } else {
202     dist = 4; /* Max distance is 3, so this is safe */
203     pixel = -1;
204 frodo 170 for (i = 0; i < palet.length; i++) {
205 frodo 168 new_dist = (p_red - palet.red[i]) * (p_red - palet.red[i]) +
206     (p_green - palet.green[i]) * (p_green - palet.green[i]) +
207     (p_blue - palet.blue[i]) * (p_blue - palet.blue[i]);
208     if (new_dist < dist) {
209     pixel = i;
210     dist = new_dist;
211     }
212     }
213     }
214     if ((res = psiconv_list_add(*pixels,&pixel)))
215     goto ERROR2;
216     }
217     }
218     return 0;
219    
220     ERROR2:
221     psiconv_list_free(*pixels);
222     ERROR1:
223     return res;
224     }
225    
226 frodo 170 int psiconv_pixel_data_to_bytes(const psiconv_config config,
227     psiconv_pixel_bytes *bytes, int xsize,
228 frodo 168 int ysize, const psiconv_pixel_ints pixels,
229     int colordepth)
230     {
231     int res;
232     int x,y;
233    
234     psiconv_u32 inputdata;
235     psiconv_u8 outputbyte;
236     psiconv_u32 *pixelptr;
237 frodo 170 int inputbitsleft,outputbitnr,bitsfit,outputbytenr;
238 frodo 168
239    
240     if (!bytes) {
241     psiconv_warn(config,0,0,"NULL pixel data");
242     res = -PSICONV_E_GENERATE;
243     goto ERROR1;
244     }
245     if (!pixels) {
246     psiconv_warn(config,0,0,"NULL pixel data");
247     res = -PSICONV_E_GENERATE;
248     goto ERROR1;
249     }
250     if (psiconv_list_length(pixels) != xsize * ysize) {
251     psiconv_warn(config,0,0,"Pixel number is not correct");
252     res = -PSICONV_E_GENERATE;
253     goto ERROR1;
254     }
255    
256     if (!(*bytes = psiconv_list_new(sizeof(psiconv_u8)))) {
257     res = -PSICONV_E_NOMEM;
258     goto ERROR1;
259     }
260    
261    
262     outputbitnr = 0;
263     outputbyte = 0;
264     for (y = 0; y < ysize; y++) {
265 frodo 170 outputbytenr = 0;
266 frodo 168 for (x = 0; x < xsize; x++) {
267     if (!(pixelptr = psiconv_list_get(pixels,y*xsize+x))) {
268     psiconv_warn(config,0,0,"Massive internal corruption");
269     res = -PSICONV_E_NOMEM;
270     goto ERROR2;
271     }
272     inputbitsleft = colordepth;
273     inputdata = *pixelptr;
274     while (inputbitsleft) {
275     bitsfit = (inputbitsleft+outputbitnr<=8?inputbitsleft:8-outputbitnr);
276     outputbyte |= (inputdata & ((1 << bitsfit) - 1)) << outputbitnr;
277     inputdata = inputdata >> bitsfit;
278     inputbitsleft -= bitsfit;
279     outputbitnr += bitsfit;
280     if (outputbitnr == 8) {
281     if ((res = psiconv_list_add(*bytes,&outputbyte)))
282     goto ERROR2;
283     outputbitnr = 0;
284     outputbyte = 0;
285 frodo 170 outputbytenr ++;
286 frodo 168 }
287     }
288     }
289 frodo 170 /* Always end lines on a long border */
290 frodo 168 if (outputbitnr != 0) {
291     if ((res = psiconv_list_add(*bytes,&outputbyte)))
292     goto ERROR2;
293     outputbitnr = 0;
294     outputbyte = 0;
295 frodo 170 outputbytenr ++;
296 frodo 168 }
297 frodo 170
298     while (outputbytenr % 0x04) {
299     if ((res = psiconv_list_add(*bytes,&outputbyte)))
300     goto ERROR2;
301     outputbytenr ++;
302     }
303 frodo 168 }
304    
305     return 0;
306    
307     ERROR2:
308     psiconv_list_free(*bytes);
309     ERROR1:
310     return res;
311     }
312 frodo 170
313     int psiconv_write_sketch_section(const psiconv_config config,
314     psiconv_buffer buf,
315 frodo 171 const psiconv_sketch_section value)
316 frodo 170 {
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 frodo 174 if ((res = psiconv_write_paint_data_section(config,buf,value->picture,0)))
344 frodo 170 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    
362     ERROR1:
363     return res;
364     }
365 frodo 171
366     int 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    
393     ERROR:
394     return res;
395     }
396 frodo 174
397     int 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    
423     ERROR:
424     return res;
425     }

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