/[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 168 - (show annotations)
Tue Nov 25 17:57:05 2003 UTC (16 years, 6 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 /*
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 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