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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 142 Revision 168
25 25
26#ifdef DMALLOC 26#ifdef DMALLOC
27#include <dmalloc.h> 27#include <dmalloc.h>
28#endif 28#endif
29 29
30typedef psiconv_list psiconv_pixel_bytes; /* psiconv_u8 */
30 31
32typedef psiconv_list psiconv_pixel_ints; /* of psiconv_u32 */
33
34typedef struct psiconv_pixel_float_s
35{
36 float *red;
37 float *green;
38 float *blue;
39} psiconv_pixel_floats_t;
40
41static 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
48static 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
52float palet_grey_2_rgb[4] = {0.0/3, 1.0/3, 2.0/3, 3.0/3};
53float 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
58psiconv_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
65psiconv_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 */
74int 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
94ERROR2:
95 psiconv_buffer_free(pix_buf);
96ERROR1:
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. */
104int 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
150ERROR2:
151 psiconv_list_free(*pixels);
152ERROR1:
153 return res;
154}
155
156int 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
227ERROR2:
228 psiconv_list_free(*bytes);
229ERROR1:
230 return res;
231}

Legend:
Removed from v.142  
changed lines
  Added in v.168

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