/[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 168 - (hide annotations)
Tue Nov 25 17:57:05 2003 UTC (20 years, 4 months ago) by frodo
File MIME type: text/plain
File size: 6638 byte(s)
(Frodo) config stuff and image generation stuff

* All parse and generate functions have a new config parameter
* New files configuration.[ch] in the psiconv lib
* Some image generation stuff (not ready, but won't do any harm)

1 frodo 86 /*
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 frodo 142 #ifdef DMALLOC
27     #include <dmalloc.h>
28     #endif
29    
30 frodo 168 typedef psiconv_list psiconv_pixel_bytes; /* psiconv_u8 */
31 frodo 142
32 frodo 168 typedef psiconv_list psiconv_pixel_ints; /* of psiconv_u32 */
33    
34     typedef struct psiconv_pixel_float_s
35     {
36     float *red;
37     float *green;
38     float *blue;
39     } psiconv_pixel_floats_t;
40    
41     static int psiconv_collect_pixel_data(const psiconv_config config,
42     psiconv_pixel_ints *pixels,int xsize,
43     int ysize,
44     const psiconv_pixel_floats_t data,
45     int colordepth, int palet_len,
46     const psiconv_pixel_floats_t palet);
47    
48     static int psiconv_pixel_data_to_bytes(const psiconv_config config, psiconv_pixel_bytes *bytes, int xsize,
49     int ysize, const psiconv_pixel_ints pixels,
50     int colordepth);
51    
52     float palet_grey_2_rgb[4] = {0.0/3, 1.0/3, 2.0/3, 3.0/3};
53     float palet_grey_4_rgb[16] = { 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,
55     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};
57    
58     psiconv_pixel_floats_t palet_grey_2 =
59     {
60     (float *) palet_grey_2_rgb,
61     (float *) palet_grey_2_rgb,
62     (float *) palet_grey_2_rgb
63     };
64    
65     psiconv_pixel_floats_t palet_grey_4 =
66     {
67     (float *) palet_grey_4_rgb,
68     (float *) palet_grey_4_rgb,
69     (float *) palet_grey_4_rgb
70     };
71    
72    
73     /* For now, we only write 2-bit non-RLE-encoded stuff */
74     int psiconv_write_paint_data_section(const psiconv_config config,
75     psiconv_buffer buf,
76     const psiconv_paint_data_section value)
77     {
78     int res;
79     psiconv_buffer pix_buf;
80    
81     if (!value) {
82     psiconv_warn(config,0,psiconv_buffer_length(buf),"Null paint data section");
83     res = -PSICONV_E_GENERATE;
84     goto ERROR1;
85     }
86    
87     if (!(pix_buf = psiconv_buffer_new())) {
88     res = -PSICONV_E_NOMEM;
89     goto ERROR1;
90     }
91    
92     return 0;
93    
94     ERROR2:
95     psiconv_buffer_free(pix_buf);
96     ERROR1:
97     return res;
98     }
99    
100     /* Translate the floating point RGB information into pixel values.
101     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
103     now. For greyscale pictures, just use the palet. */
104     int psiconv_collect_pixel_data(const psiconv_config config,
105     psiconv_pixel_ints *pixels,int xsize,int ysize,
106     const psiconv_pixel_floats_t data,
107     int colordepth, int palet_len,
108     const psiconv_pixel_floats_t palet)
109     {
110     int res,x,y,i;
111     psiconv_u32 index,mask,pixel;
112     float p_red,p_green,p_blue,mult,dist,new_dist;
113    
114     if (!(*pixels = psiconv_list_new(sizeof(psiconv_u32)))) {
115     res = -PSICONV_E_NOMEM;
116     goto ERROR1;
117     }
118    
119     mult = 1 << colordepth;
120     mask = mult -1;
121     for (y = 0; y < ysize; y++) {
122     for (x = 0; x < xsize; x++) {
123     index = y*ysize+x;
124     p_red = data.red[index];
125     p_green = data.green[index];
126     p_blue = data.blue[index];
127     if (! palet_len) {
128     pixel = (((psiconv_u32) (p_red*mult) & mask) << (2*colordepth)) +
129     (((psiconv_u32) (p_green*mult) & mask) << colordepth) +
130     ((psiconv_u32) (p_blue*mult) & mask);
131     } else {
132     dist = 4; /* Max distance is 3, so this is safe */
133     pixel = -1;
134     for (i = 0; i < palet_len; i++) {
135     new_dist = (p_red - palet.red[i]) * (p_red - palet.red[i]) +
136     (p_green - palet.green[i]) * (p_green - palet.green[i]) +
137     (p_blue - palet.blue[i]) * (p_blue - palet.blue[i]);
138     if (new_dist < dist) {
139     pixel = i;
140     dist = new_dist;
141     }
142     }
143     }
144     if ((res = psiconv_list_add(*pixels,&pixel)))
145     goto ERROR2;
146     }
147     }
148     return 0;
149    
150     ERROR2:
151     psiconv_list_free(*pixels);
152     ERROR1:
153     return res;
154     }
155    
156     int psiconv_pixel_data_to_bytes(const psiconv_config config, psiconv_pixel_bytes *bytes, int xsize,
157     int ysize, const psiconv_pixel_ints pixels,
158     int colordepth)
159     {
160     int res;
161     int x,y;
162    
163     psiconv_u32 inputdata;
164     psiconv_u8 outputbyte;
165     psiconv_u32 *pixelptr;
166     int inputbitsleft,outputbitnr,bitsfit;
167    
168    
169     if (!bytes) {
170     psiconv_warn(config,0,0,"NULL pixel data");
171     res = -PSICONV_E_GENERATE;
172     goto ERROR1;
173     }
174     if (!pixels) {
175     psiconv_warn(config,0,0,"NULL pixel data");
176     res = -PSICONV_E_GENERATE;
177     goto ERROR1;
178     }
179     if (psiconv_list_length(pixels) != xsize * ysize) {
180     psiconv_warn(config,0,0,"Pixel number is not correct");
181     res = -PSICONV_E_GENERATE;
182     goto ERROR1;
183     }
184    
185     if (!(*bytes = psiconv_list_new(sizeof(psiconv_u8)))) {
186     res = -PSICONV_E_NOMEM;
187     goto ERROR1;
188     }
189    
190    
191     outputbitnr = 0;
192     outputbyte = 0;
193     for (y = 0; y < ysize; y++) {
194     for (x = 0; x < xsize; x++) {
195     if (!(pixelptr = psiconv_list_get(pixels,y*xsize+x))) {
196     psiconv_warn(config,0,0,"Massive internal corruption");
197     res = -PSICONV_E_NOMEM;
198     goto ERROR2;
199     }
200     inputbitsleft = colordepth;
201     inputdata = *pixelptr;
202     while (inputbitsleft) {
203     bitsfit = (inputbitsleft+outputbitnr<=8?inputbitsleft:8-outputbitnr);
204     outputbyte |= (inputdata & ((1 << bitsfit) - 1)) << outputbitnr;
205     inputdata = inputdata >> bitsfit;
206     inputbitsleft -= bitsfit;
207     outputbitnr += bitsfit;
208     if (outputbitnr == 8) {
209     if ((res = psiconv_list_add(*bytes,&outputbyte)))
210     goto ERROR2;
211     outputbitnr = 0;
212     outputbyte = 0;
213     }
214     }
215     }
216     /* Always end lines on a byte border */
217     if (outputbitnr != 0) {
218     if ((res = psiconv_list_add(*bytes,&outputbyte)))
219     goto ERROR2;
220     outputbitnr = 0;
221     outputbyte = 0;
222     }
223     }
224    
225     return 0;
226    
227     ERROR2:
228     psiconv_list_free(*bytes);
229     ERROR1:
230     return res;
231     }

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