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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

1 /*
2
3 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 #ifdef DMALLOC
28 #include <dmalloc.h>
29 #endif
30
31 typedef psiconv_list psiconv_pixel_bytes; /* psiconv_u8 */
32
33 typedef psiconv_list psiconv_pixel_ints; /* of psiconv_u32 */
34
35 typedef 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
43 static int psiconv_collect_pixel_data(psiconv_pixel_ints *pixels,
44 int xsize,int ysize,
45 const psiconv_pixel_floats_t data,
46 int colordepth,
47 const psiconv_pixel_floats_t palet);
48 static int psiconv_pixel_data_to_bytes(const psiconv_config config,
49 psiconv_pixel_bytes *bytes, int xsize,
50 int ysize, const psiconv_pixel_ints pixels,
51 int colordepth);
52
53 #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 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 #define PALET_NONE_LEN 0
62
63 psiconv_pixel_floats_t palet_grey_2 =
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
71 psiconv_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
79 psiconv_pixel_floats_t palet_none =
80 {
81 PALET_NONE_LEN,
82 NULL,
83 NULL,
84 NULL
85 };
86
87
88 int psiconv_write_paint_data_section(const psiconv_config config,
89 psiconv_buffer buf,
90 const psiconv_paint_data_section value,
91 int is_clipart)
92 {
93 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
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 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 goto ERROR1;
122
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 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 }
163
164 ERROR3:
165 psiconv_list_free(bytes);
166 ERROR2:
167 psiconv_list_free(ints);
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 int psiconv_collect_pixel_data(psiconv_pixel_ints *pixels,int xsize,int ysize,
177 const psiconv_pixel_floats_t data,
178 int colordepth,
179 const psiconv_pixel_floats_t palet)
180 {
181 int res,x,y,i;
182 psiconv_u32 index,pixel;
183 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 index = y*xsize+x;
194 p_red = data.red[index];
195 p_green = data.green[index];
196 p_blue = data.blue[index];
197 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 } else {
202 dist = 4; /* Max distance is 3, so this is safe */
203 pixel = -1;
204 for (i = 0; i < palet.length; i++) {
205 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 int psiconv_pixel_data_to_bytes(const psiconv_config config,
227 psiconv_pixel_bytes *bytes, int xsize,
228 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 int inputbitsleft,outputbitnr,bitsfit,outputbytenr;
238
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 outputbytenr = 0;
266 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 outputbytenr ++;
286 }
287 }
288 }
289 /* Always end lines on a long border */
290 if (outputbitnr != 0) {
291 if ((res = psiconv_list_add(*bytes,&outputbyte)))
292 goto ERROR2;
293 outputbitnr = 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 ++;
302 }
303 }
304
305 return 0;
306
307 ERROR2:
308 psiconv_list_free(*bytes);
309 ERROR1:
310 return res;
311 }
312
313 int 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
362 ERROR1:
363 return res;
364 }
365
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
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