/[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 170 - (show annotations)
Tue Nov 25 22:08:48 2003 UTC (20 years, 4 months ago) by frodo
File MIME type: text/plain
File size: 10704 byte(s)
(Frodo) Generating of Sketch files, both stand-alone and as objects, works!

No RLE encoding yet, we have to test higher colordepths.

1 /*
2 generate_image.c - Part of psiconv, a PSION 5 file formats converter
3 Copyright (c) 1999, 2000 Frodo Looijaard <frodol@dds.nl>
4
5 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 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include "config.h"
21 #include "compat.h"
22
23 #include "generate_routines.h"
24 #include "error.h"
25
26 #ifdef DMALLOC
27 #include <dmalloc.h>
28 #endif
29
30 typedef psiconv_list psiconv_pixel_bytes; /* psiconv_u8 */
31
32 typedef psiconv_list psiconv_pixel_ints; /* of psiconv_u32 */
33
34 typedef struct psiconv_pixel_float_s
35 {
36 psiconv_u32 length;
37 float *red;
38 float *green;
39 float *blue;
40 } psiconv_pixel_floats_t;
41
42 static int psiconv_collect_pixel_data(psiconv_pixel_ints *pixels,
43 int xsize,int ysize,
44 const psiconv_pixel_floats_t data,
45 int colordepth,
46 const psiconv_pixel_floats_t palet);
47 static int psiconv_pixel_data_to_bytes(const psiconv_config config,
48 psiconv_pixel_bytes *bytes, int xsize,
49 int ysize, const psiconv_pixel_ints pixels,
50 int colordepth);
51
52 #define PALET_GREY_2_LEN 4
53 float palet_grey_2_rgb[PALET_GREY_2_LEN] = {0.0/3, 1.0/3, 2.0/3, 3.0/3};
54 #define PALET_GREY_4_LEN 16
55 float palet_grey_4_rgb[PALET_GREY_4_LEN] =
56 { 0.0/15, 1.0/15, 2.0/15, 3.0/15,
57 4.0/15, 5.0/15, 6.0/15, 7.0/15,
58 8.0/15, 9.0/15, 10.0/15, 11.0/15,
59 12.0/15, 13.0/15, 14.0/15, 15.0/15};
60 #define PALET_NONE_LEN 0
61
62 psiconv_pixel_floats_t palet_grey_2 =
63 {
64 PALET_GREY_2_LEN,
65 (float *) palet_grey_2_rgb,
66 (float *) palet_grey_2_rgb,
67 (float *) palet_grey_2_rgb
68 };
69
70 psiconv_pixel_floats_t palet_grey_4 =
71 {
72 PALET_GREY_4_LEN,
73 (float *) palet_grey_4_rgb,
74 (float *) palet_grey_4_rgb,
75 (float *) palet_grey_4_rgb
76 };
77
78 psiconv_pixel_floats_t palet_none =
79 {
80 PALET_NONE_LEN,
81 NULL,
82 NULL,
83 NULL
84 };
85
86
87 int psiconv_write_paint_data_section(const psiconv_config config,
88 psiconv_buffer buf,
89 const psiconv_paint_data_section value)
90 {
91 int res,colordepth,i;
92 psiconv_pixel_ints ints;
93 psiconv_pixel_floats_t floats,palet;
94 psiconv_list bytes;
95 psiconv_u8 *byteptr;
96
97 if (!value) {
98 psiconv_warn(config,0,psiconv_buffer_length(buf),"Null paint data section");
99 res = -PSICONV_E_GENERATE;
100 goto ERROR1;
101 }
102
103 floats.red = value->red;
104 floats.green = value->green;
105 floats.blue = value->blue;
106 floats.length = value->xsize * value->ysize;
107
108 switch (config->colordepth) {
109 default:
110 case 2: palet = (config->color?palet_none:palet_grey_2);
111 break;
112 case 4: palet = (config->color?palet_none:palet_grey_4);
113 break;
114 }
115
116 if ((res = psiconv_collect_pixel_data(&ints,value->xsize,
117 value->ysize,floats,
118 config->colordepth,palet)))
119 goto ERROR1;
120
121 if ((res = psiconv_pixel_data_to_bytes(config,&bytes,value->xsize,value->ysize,
122 ints,config->colordepth)))
123 goto ERROR2;
124
125 if ((res = psiconv_write_u32(config,buf,0x28+psiconv_list_length(bytes))))
126 goto ERROR3;
127 if ((res = psiconv_write_u32(config,buf,0x28)))
128 goto ERROR3;
129 if ((res = psiconv_write_u32(config,buf,value->xsize)))
130 goto ERROR3;
131 if ((res = psiconv_write_u32(config,buf,value->ysize)))
132 goto ERROR3;
133 if ((res = psiconv_write_length(config,buf,value->pic_xsize)))
134 goto ERROR3;
135 if ((res = psiconv_write_length(config,buf,value->pic_ysize)))
136 goto ERROR3;
137 colordepth = config->colordepth;
138 if ((colordepth != 2) && colordepth != 4)
139 colordepth = 2;
140 if ((res = psiconv_write_u32(config,buf,colordepth)))
141 goto ERROR3;
142 if ((res = psiconv_write_u32(config,buf,(config->color?1:0))))
143 goto ERROR3;
144 if ((res = psiconv_write_u32(config,buf,0)))
145 goto ERROR3;
146 /* Encoding: no RLE for now */
147 if ((res = psiconv_write_u32(config,buf,0)))
148 goto ERROR3;
149 for (i = 0; i < psiconv_list_length(bytes); i++) {
150 if (!(byteptr = psiconv_list_get(bytes,i)))
151 goto ERROR3;
152 if ((res = psiconv_write_u8(config,buf,*byteptr)))
153 goto ERROR3;
154 }
155
156 ERROR3:
157 psiconv_list_free(bytes);
158 ERROR2:
159 psiconv_list_free(ints);
160 ERROR1:
161 return res;
162 }
163
164 /* Translate the floating point RGB information into pixel values.
165 The palet is optional; without it, we just use the
166 colordepth. With a large palet this is not very fast, but it will do for
167 now. For greyscale pictures, just use the palet. */
168 int psiconv_collect_pixel_data(psiconv_pixel_ints *pixels,int xsize,int ysize,
169 const psiconv_pixel_floats_t data,
170 int colordepth,
171 const psiconv_pixel_floats_t palet)
172 {
173 int res,x,y,i;
174 psiconv_u32 index,pixel;
175 float p_red,p_green,p_blue,mult,dist,new_dist;
176
177 if (!(*pixels = psiconv_list_new(sizeof(psiconv_u32)))) {
178 res = -PSICONV_E_NOMEM;
179 goto ERROR1;
180 }
181
182 mult = 1 << colordepth;
183 for (y = 0; y < ysize; y++) {
184 for (x = 0; x < xsize; x++) {
185 index = y*xsize+x;
186 p_red = data.red[index];
187 p_green = data.green[index];
188 p_blue = data.blue[index];
189 if (!palet.length) {
190 pixel = (((psiconv_u32) (p_red*mult+0.5)) << (2*colordepth)) +
191 (((psiconv_u32) (p_green*mult+0.5)) << colordepth) +
192 ((psiconv_u32) (p_blue*mult+0.5));
193 } else {
194 dist = 4; /* Max distance is 3, so this is safe */
195 pixel = -1;
196 for (i = 0; i < palet.length; i++) {
197 new_dist = (p_red - palet.red[i]) * (p_red - palet.red[i]) +
198 (p_green - palet.green[i]) * (p_green - palet.green[i]) +
199 (p_blue - palet.blue[i]) * (p_blue - palet.blue[i]);
200 if (new_dist < dist) {
201 pixel = i;
202 dist = new_dist;
203 }
204 }
205 }
206 if ((res = psiconv_list_add(*pixels,&pixel)))
207 goto ERROR2;
208 }
209 }
210 return 0;
211
212 ERROR2:
213 psiconv_list_free(*pixels);
214 ERROR1:
215 return res;
216 }
217
218 int psiconv_pixel_data_to_bytes(const psiconv_config config,
219 psiconv_pixel_bytes *bytes, int xsize,
220 int ysize, const psiconv_pixel_ints pixels,
221 int colordepth)
222 {
223 int res;
224 int x,y;
225
226 psiconv_u32 inputdata;
227 psiconv_u8 outputbyte;
228 psiconv_u32 *pixelptr;
229 int inputbitsleft,outputbitnr,bitsfit,outputbytenr;
230
231
232 if (!bytes) {
233 psiconv_warn(config,0,0,"NULL pixel data");
234 res = -PSICONV_E_GENERATE;
235 goto ERROR1;
236 }
237 if (!pixels) {
238 psiconv_warn(config,0,0,"NULL pixel data");
239 res = -PSICONV_E_GENERATE;
240 goto ERROR1;
241 }
242 if (psiconv_list_length(pixels) != xsize * ysize) {
243 psiconv_warn(config,0,0,"Pixel number is not correct");
244 res = -PSICONV_E_GENERATE;
245 goto ERROR1;
246 }
247
248 if (!(*bytes = psiconv_list_new(sizeof(psiconv_u8)))) {
249 res = -PSICONV_E_NOMEM;
250 goto ERROR1;
251 }
252
253
254 outputbitnr = 0;
255 outputbyte = 0;
256 for (y = 0; y < ysize; y++) {
257 outputbytenr = 0;
258 for (x = 0; x < xsize; x++) {
259 if (!(pixelptr = psiconv_list_get(pixels,y*xsize+x))) {
260 psiconv_warn(config,0,0,"Massive internal corruption");
261 res = -PSICONV_E_NOMEM;
262 goto ERROR2;
263 }
264 inputbitsleft = colordepth;
265 inputdata = *pixelptr;
266 while (inputbitsleft) {
267 bitsfit = (inputbitsleft+outputbitnr<=8?inputbitsleft:8-outputbitnr);
268 outputbyte |= (inputdata & ((1 << bitsfit) - 1)) << outputbitnr;
269 inputdata = inputdata >> bitsfit;
270 inputbitsleft -= bitsfit;
271 outputbitnr += bitsfit;
272 if (outputbitnr == 8) {
273 if ((res = psiconv_list_add(*bytes,&outputbyte)))
274 goto ERROR2;
275 outputbitnr = 0;
276 outputbyte = 0;
277 outputbytenr ++;
278 }
279 }
280 }
281 /* Always end lines on a long border */
282 if (outputbitnr != 0) {
283 if ((res = psiconv_list_add(*bytes,&outputbyte)))
284 goto ERROR2;
285 outputbitnr = 0;
286 outputbyte = 0;
287 outputbytenr ++;
288 }
289
290 while (outputbytenr % 0x04) {
291 if ((res = psiconv_list_add(*bytes,&outputbyte)))
292 goto ERROR2;
293 outputbytenr ++;
294 }
295 }
296
297 return 0;
298
299 ERROR2:
300 psiconv_list_free(*bytes);
301 ERROR1:
302 return res;
303 }
304
305 int psiconv_write_sketch_section(const psiconv_config config,
306 psiconv_buffer buf,
307 psiconv_sketch_section value)
308 {
309 int res;
310
311 if (!value) {
312 psiconv_warn(config,0,0,"NULL sketch section");
313 res = -PSICONV_E_GENERATE;
314 goto ERROR1;
315 }
316
317 if ((res = psiconv_write_u16(config,buf,value->displayed_xsize)))
318 goto ERROR1;
319 if ((res = psiconv_write_u16(config,buf,value->displayed_ysize)))
320 goto ERROR1;
321 if ((res = psiconv_write_u16(config,buf,value->picture_data_x_offset)))
322 goto ERROR1;
323 if ((res = psiconv_write_u16(config,buf,value->picture_data_y_offset)))
324 goto ERROR1;
325 if ((res = psiconv_write_u16(config,buf,value->displayed_size_x_offset)))
326 goto ERROR1;
327 if ((res = psiconv_write_u16(config,buf,value->displayed_size_y_offset)))
328 goto ERROR1;
329 if ((res = psiconv_write_u16(config,buf,value->form_xsize)))
330 goto ERROR1;
331 if ((res = psiconv_write_u16(config,buf,value->form_ysize)))
332 goto ERROR1;
333 if ((res = psiconv_write_u16(config,buf,0x0000)))
334 goto ERROR1;
335 if ((res = psiconv_write_paint_data_section(config,buf,value->picture)))
336 goto ERROR1;
337 if ((res = psiconv_write_u16(config,buf,value->magnification_x * 0x03e8)))
338 goto ERROR1;
339 if ((res = psiconv_write_u16(config,buf,value->magnification_y * 0x03e8)))
340 goto ERROR1;
341 if ((res = psiconv_write_u32(config,buf,value->cut_left * 0x0c *
342 value->displayed_xsize)))
343 goto ERROR1;
344 if ((res = psiconv_write_u32(config,buf,value->cut_right * 0x0c *
345 value->displayed_xsize)))
346 goto ERROR1;
347 if ((res = psiconv_write_u32(config,buf,value->cut_top * 0x0c *
348 value->displayed_ysize)))
349 goto ERROR1;
350 if ((res = psiconv_write_u32(config,buf,value->cut_bottom * 0x0c *
351 value->displayed_ysize)))
352 goto ERROR1;
353
354 ERROR1:
355 return res;
356 }

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