/[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 168 Revision 170
31 31
32typedef psiconv_list psiconv_pixel_ints; /* of psiconv_u32 */ 32typedef psiconv_list psiconv_pixel_ints; /* of psiconv_u32 */
33 33
34typedef struct psiconv_pixel_float_s 34typedef struct psiconv_pixel_float_s
35{ 35{
36 psiconv_u32 length;
36 float *red; 37 float *red;
37 float *green; 38 float *green;
38 float *blue; 39 float *blue;
39} psiconv_pixel_floats_t; 40} psiconv_pixel_floats_t;
40 41
41static int psiconv_collect_pixel_data(const psiconv_config config, 42static int psiconv_collect_pixel_data(psiconv_pixel_ints *pixels,
42 psiconv_pixel_ints *pixels,int xsize,
43 int ysize, 43 int xsize,int ysize,
44 const psiconv_pixel_floats_t data, 44 const psiconv_pixel_floats_t data,
45 int colordepth, int palet_len, 45 int colordepth,
46 const psiconv_pixel_floats_t palet); 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, 47static 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, 49 int ysize, const psiconv_pixel_ints pixels,
50 int colordepth); 50 int colordepth);
51 51
52#define PALET_GREY_2_LEN 4
52float palet_grey_2_rgb[4] = {0.0/3, 1.0/3, 2.0/3, 3.0/3}; 53float palet_grey_2_rgb[PALET_GREY_2_LEN] = {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#define PALET_GREY_4_LEN 16
55float palet_grey_4_rgb[PALET_GREY_4_LEN] =
56 { 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, 57 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, 58 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}; 59 12.0/15, 13.0/15, 14.0/15, 15.0/15};
60#define PALET_NONE_LEN 0
57 61
58psiconv_pixel_floats_t palet_grey_2 = 62psiconv_pixel_floats_t palet_grey_2 =
59 { 63 {
64 PALET_GREY_2_LEN,
60 (float *) palet_grey_2_rgb, 65 (float *) palet_grey_2_rgb,
61 (float *) palet_grey_2_rgb, 66 (float *) palet_grey_2_rgb,
62 (float *) palet_grey_2_rgb 67 (float *) palet_grey_2_rgb
63 }; 68 };
64 69
65psiconv_pixel_floats_t palet_grey_4 = 70psiconv_pixel_floats_t palet_grey_4 =
66 { 71 {
72 PALET_GREY_4_LEN,
67 (float *) palet_grey_4_rgb, 73 (float *) palet_grey_4_rgb,
68 (float *) palet_grey_4_rgb, 74 (float *) palet_grey_4_rgb,
69 (float *) palet_grey_4_rgb 75 (float *) palet_grey_4_rgb
70 }; 76 };
71 77
78psiconv_pixel_floats_t palet_none =
79 {
80 PALET_NONE_LEN,
81 NULL,
82 NULL,
83 NULL
84 };
72 85
73/* For now, we only write 2-bit non-RLE-encoded stuff */ 86
74int psiconv_write_paint_data_section(const psiconv_config config, 87int psiconv_write_paint_data_section(const psiconv_config config,
75 psiconv_buffer buf, 88 psiconv_buffer buf,
76 const psiconv_paint_data_section value) 89 const psiconv_paint_data_section value)
77{ 90{
78 int res; 91 int res,colordepth,i;
79 psiconv_buffer pix_buf; 92 psiconv_pixel_ints ints;
93 psiconv_pixel_floats_t floats,palet;
94 psiconv_list bytes;
95 psiconv_u8 *byteptr;
80 96
81 if (!value) { 97 if (!value) {
82 psiconv_warn(config,0,psiconv_buffer_length(buf),"Null paint data section"); 98 psiconv_warn(config,0,psiconv_buffer_length(buf),"Null paint data section");
83 res = -PSICONV_E_GENERATE; 99 res = -PSICONV_E_GENERATE;
84 goto ERROR1; 100 goto ERROR1;
85 } 101 }
86 102
87 if (!(pix_buf = psiconv_buffer_new())) { 103 floats.red = value->red;
88 res = -PSICONV_E_NOMEM; 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)))
89 goto ERROR1; 123 goto ERROR2;
90 }
91 124
92 return 0; 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 }
93 155
156ERROR3:
157 psiconv_list_free(bytes);
94ERROR2: 158ERROR2:
95 psiconv_buffer_free(pix_buf); 159 psiconv_list_free(ints);
96ERROR1: 160ERROR1:
97 return res; 161 return res;
98} 162}
99 163
100/* Translate the floating point RGB information into pixel values. 164/* Translate the floating point RGB information into pixel values.
101 The palet is optional; without it, we just use the 165 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 166 colordepth. With a large palet this is not very fast, but it will do for
103 now. For greyscale pictures, just use the palet. */ 167 now. For greyscale pictures, just use the palet. */
104int psiconv_collect_pixel_data(const psiconv_config config, 168int psiconv_collect_pixel_data(psiconv_pixel_ints *pixels,int xsize,int ysize,
105 psiconv_pixel_ints *pixels,int xsize,int ysize,
106 const psiconv_pixel_floats_t data, 169 const psiconv_pixel_floats_t data,
107 int colordepth, int palet_len, 170 int colordepth,
108 const psiconv_pixel_floats_t palet) 171 const psiconv_pixel_floats_t palet)
109{ 172{
110 int res,x,y,i; 173 int res,x,y,i;
111 psiconv_u32 index,mask,pixel; 174 psiconv_u32 index,pixel;
112 float p_red,p_green,p_blue,mult,dist,new_dist; 175 float p_red,p_green,p_blue,mult,dist,new_dist;
113 176
114 if (!(*pixels = psiconv_list_new(sizeof(psiconv_u32)))) { 177 if (!(*pixels = psiconv_list_new(sizeof(psiconv_u32)))) {
115 res = -PSICONV_E_NOMEM; 178 res = -PSICONV_E_NOMEM;
116 goto ERROR1; 179 goto ERROR1;
117 } 180 }
118 181
119 mult = 1 << colordepth; 182 mult = 1 << colordepth;
120 mask = mult -1;
121 for (y = 0; y < ysize; y++) { 183 for (y = 0; y < ysize; y++) {
122 for (x = 0; x < xsize; x++) { 184 for (x = 0; x < xsize; x++) {
123 index = y*ysize+x; 185 index = y*xsize+x;
124 p_red = data.red[index]; 186 p_red = data.red[index];
125 p_green = data.green[index]; 187 p_green = data.green[index];
126 p_blue = data.blue[index]; 188 p_blue = data.blue[index];
127 if (! palet_len) { 189 if (!palet.length) {
128 pixel = (((psiconv_u32) (p_red*mult) & mask) << (2*colordepth)) + 190 pixel = (((psiconv_u32) (p_red*mult+0.5)) << (2*colordepth)) +
129 (((psiconv_u32) (p_green*mult) & mask) << colordepth) + 191 (((psiconv_u32) (p_green*mult+0.5)) << colordepth) +
130 ((psiconv_u32) (p_blue*mult) & mask); 192 ((psiconv_u32) (p_blue*mult+0.5));
131 } else { 193 } else {
132 dist = 4; /* Max distance is 3, so this is safe */ 194 dist = 4; /* Max distance is 3, so this is safe */
133 pixel = -1; 195 pixel = -1;
134 for (i = 0; i < palet_len; i++) { 196 for (i = 0; i < palet.length; i++) {
135 new_dist = (p_red - palet.red[i]) * (p_red - palet.red[i]) + 197 new_dist = (p_red - palet.red[i]) * (p_red - palet.red[i]) +
136 (p_green - palet.green[i]) * (p_green - palet.green[i]) + 198 (p_green - palet.green[i]) * (p_green - palet.green[i]) +
137 (p_blue - palet.blue[i]) * (p_blue - palet.blue[i]); 199 (p_blue - palet.blue[i]) * (p_blue - palet.blue[i]);
138 if (new_dist < dist) { 200 if (new_dist < dist) {
139 pixel = i; 201 pixel = i;
151 psiconv_list_free(*pixels); 213 psiconv_list_free(*pixels);
152ERROR1: 214ERROR1:
153 return res; 215 return res;
154} 216}
155 217
156int psiconv_pixel_data_to_bytes(const psiconv_config config, psiconv_pixel_bytes *bytes, int xsize, 218int psiconv_pixel_data_to_bytes(const psiconv_config config,
219 psiconv_pixel_bytes *bytes, int xsize,
157 int ysize, const psiconv_pixel_ints pixels, 220 int ysize, const psiconv_pixel_ints pixels,
158 int colordepth) 221 int colordepth)
159{ 222{
160 int res; 223 int res;
161 int x,y; 224 int x,y;
162 225
163 psiconv_u32 inputdata; 226 psiconv_u32 inputdata;
164 psiconv_u8 outputbyte; 227 psiconv_u8 outputbyte;
165 psiconv_u32 *pixelptr; 228 psiconv_u32 *pixelptr;
166 int inputbitsleft,outputbitnr,bitsfit; 229 int inputbitsleft,outputbitnr,bitsfit,outputbytenr;
167 230
168 231
169 if (!bytes) { 232 if (!bytes) {
170 psiconv_warn(config,0,0,"NULL pixel data"); 233 psiconv_warn(config,0,0,"NULL pixel data");
171 res = -PSICONV_E_GENERATE; 234 res = -PSICONV_E_GENERATE;
189 252
190 253
191 outputbitnr = 0; 254 outputbitnr = 0;
192 outputbyte = 0; 255 outputbyte = 0;
193 for (y = 0; y < ysize; y++) { 256 for (y = 0; y < ysize; y++) {
257 outputbytenr = 0;
194 for (x = 0; x < xsize; x++) { 258 for (x = 0; x < xsize; x++) {
195 if (!(pixelptr = psiconv_list_get(pixels,y*xsize+x))) { 259 if (!(pixelptr = psiconv_list_get(pixels,y*xsize+x))) {
196 psiconv_warn(config,0,0,"Massive internal corruption"); 260 psiconv_warn(config,0,0,"Massive internal corruption");
197 res = -PSICONV_E_NOMEM; 261 res = -PSICONV_E_NOMEM;
198 goto ERROR2; 262 goto ERROR2;
208 if (outputbitnr == 8) { 272 if (outputbitnr == 8) {
209 if ((res = psiconv_list_add(*bytes,&outputbyte))) 273 if ((res = psiconv_list_add(*bytes,&outputbyte)))
210 goto ERROR2; 274 goto ERROR2;
211 outputbitnr = 0; 275 outputbitnr = 0;
212 outputbyte = 0; 276 outputbyte = 0;
277 outputbytenr ++;
213 } 278 }
214 } 279 }
215 } 280 }
216 /* Always end lines on a byte border */ 281 /* Always end lines on a long border */
217 if (outputbitnr != 0) { 282 if (outputbitnr != 0) {
218 if ((res = psiconv_list_add(*bytes,&outputbyte))) 283 if ((res = psiconv_list_add(*bytes,&outputbyte)))
219 goto ERROR2; 284 goto ERROR2;
220 outputbitnr = 0; 285 outputbitnr = 0;
221 outputbyte = 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 ++;
222 } 294 }
223 } 295 }
224 296
225 return 0; 297 return 0;
226 298
227ERROR2: 299ERROR2:
228 psiconv_list_free(*bytes); 300 psiconv_list_free(*bytes);
229ERROR1: 301ERROR1:
230 return res; 302 return res;
231} 303}
304
305int 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
354ERROR1:
355 return res;
356}

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

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