--- psiconv/trunk/lib/psiconv/generate_image.c 2003/11/25 17:57:05 168 +++ psiconv/trunk/lib/psiconv/generate_image.c 2003/11/25 22:08:48 170 @@ -33,30 +33,35 @@ typedef struct psiconv_pixel_float_s { + psiconv_u32 length; float *red; float *green; float *blue; } psiconv_pixel_floats_t; -static int psiconv_collect_pixel_data(const psiconv_config config, - psiconv_pixel_ints *pixels,int xsize, - int ysize, +static int psiconv_collect_pixel_data(psiconv_pixel_ints *pixels, + int xsize,int ysize, const psiconv_pixel_floats_t data, - int colordepth, int palet_len, + int colordepth, const psiconv_pixel_floats_t palet); - -static int psiconv_pixel_data_to_bytes(const psiconv_config config, psiconv_pixel_bytes *bytes, int xsize, +static int psiconv_pixel_data_to_bytes(const psiconv_config config, + psiconv_pixel_bytes *bytes, int xsize, int ysize, const psiconv_pixel_ints pixels, int colordepth); -float palet_grey_2_rgb[4] = {0.0/3, 1.0/3, 2.0/3, 3.0/3}; -float palet_grey_4_rgb[16] = { 0.0/15, 1.0/15, 2.0/15, 3.0/15, +#define PALET_GREY_2_LEN 4 +float palet_grey_2_rgb[PALET_GREY_2_LEN] = {0.0/3, 1.0/3, 2.0/3, 3.0/3}; +#define PALET_GREY_4_LEN 16 +float palet_grey_4_rgb[PALET_GREY_4_LEN] = + { 0.0/15, 1.0/15, 2.0/15, 3.0/15, 4.0/15, 5.0/15, 6.0/15, 7.0/15, 8.0/15, 9.0/15, 10.0/15, 11.0/15, 12.0/15, 13.0/15, 14.0/15, 15.0/15}; +#define PALET_NONE_LEN 0 psiconv_pixel_floats_t palet_grey_2 = { + PALET_GREY_2_LEN, (float *) palet_grey_2_rgb, (float *) palet_grey_2_rgb, (float *) palet_grey_2_rgb @@ -64,19 +69,30 @@ psiconv_pixel_floats_t palet_grey_4 = { + PALET_GREY_4_LEN, (float *) palet_grey_4_rgb, (float *) palet_grey_4_rgb, (float *) palet_grey_4_rgb }; +psiconv_pixel_floats_t palet_none = + { + PALET_NONE_LEN, + NULL, + NULL, + NULL + }; + -/* For now, we only write 2-bit non-RLE-encoded stuff */ int psiconv_write_paint_data_section(const psiconv_config config, - psiconv_buffer buf, + psiconv_buffer buf, const psiconv_paint_data_section value) { - int res; - psiconv_buffer pix_buf; + int res,colordepth,i; + psiconv_pixel_ints ints; + psiconv_pixel_floats_t floats,palet; + psiconv_list bytes; + psiconv_u8 *byteptr; if (!value) { psiconv_warn(config,0,psiconv_buffer_length(buf),"Null paint data section"); @@ -84,15 +100,63 @@ goto ERROR1; } - if (!(pix_buf = psiconv_buffer_new())) { - res = -PSICONV_E_NOMEM; - goto ERROR1; + floats.red = value->red; + floats.green = value->green; + floats.blue = value->blue; + floats.length = value->xsize * value->ysize; + + switch (config->colordepth) { + default: + case 2: palet = (config->color?palet_none:palet_grey_2); + break; + case 4: palet = (config->color?palet_none:palet_grey_4); + break; } - return 0; + if ((res = psiconv_collect_pixel_data(&ints,value->xsize, + value->ysize,floats, + config->colordepth,palet))) + goto ERROR1; + + if ((res = psiconv_pixel_data_to_bytes(config,&bytes,value->xsize,value->ysize, + ints,config->colordepth))) + goto ERROR2; + + if ((res = psiconv_write_u32(config,buf,0x28+psiconv_list_length(bytes)))) + goto ERROR3; + if ((res = psiconv_write_u32(config,buf,0x28))) + goto ERROR3; + if ((res = psiconv_write_u32(config,buf,value->xsize))) + goto ERROR3; + if ((res = psiconv_write_u32(config,buf,value->ysize))) + goto ERROR3; + if ((res = psiconv_write_length(config,buf,value->pic_xsize))) + goto ERROR3; + if ((res = psiconv_write_length(config,buf,value->pic_ysize))) + goto ERROR3; + colordepth = config->colordepth; + if ((colordepth != 2) && colordepth != 4) + colordepth = 2; + if ((res = psiconv_write_u32(config,buf,colordepth))) + goto ERROR3; + if ((res = psiconv_write_u32(config,buf,(config->color?1:0)))) + goto ERROR3; + if ((res = psiconv_write_u32(config,buf,0))) + goto ERROR3; + /* Encoding: no RLE for now */ + if ((res = psiconv_write_u32(config,buf,0))) + goto ERROR3; + for (i = 0; i < psiconv_list_length(bytes); i++) { + if (!(byteptr = psiconv_list_get(bytes,i))) + goto ERROR3; + if ((res = psiconv_write_u8(config,buf,*byteptr))) + goto ERROR3; + } +ERROR3: + psiconv_list_free(bytes); ERROR2: - psiconv_buffer_free(pix_buf); + psiconv_list_free(ints); ERROR1: return res; } @@ -101,14 +165,13 @@ The palet is optional; without it, we just use the colordepth. With a large palet this is not very fast, but it will do for now. For greyscale pictures, just use the palet. */ -int psiconv_collect_pixel_data(const psiconv_config config, - psiconv_pixel_ints *pixels,int xsize,int ysize, +int psiconv_collect_pixel_data(psiconv_pixel_ints *pixels,int xsize,int ysize, const psiconv_pixel_floats_t data, - int colordepth, int palet_len, + int colordepth, const psiconv_pixel_floats_t palet) { int res,x,y,i; - psiconv_u32 index,mask,pixel; + psiconv_u32 index,pixel; float p_red,p_green,p_blue,mult,dist,new_dist; if (!(*pixels = psiconv_list_new(sizeof(psiconv_u32)))) { @@ -117,21 +180,20 @@ } mult = 1 << colordepth; - mask = mult -1; for (y = 0; y < ysize; y++) { for (x = 0; x < xsize; x++) { - index = y*ysize+x; + index = y*xsize+x; p_red = data.red[index]; p_green = data.green[index]; p_blue = data.blue[index]; - if (! palet_len) { - pixel = (((psiconv_u32) (p_red*mult) & mask) << (2*colordepth)) + - (((psiconv_u32) (p_green*mult) & mask) << colordepth) + - ((psiconv_u32) (p_blue*mult) & mask); + if (!palet.length) { + pixel = (((psiconv_u32) (p_red*mult+0.5)) << (2*colordepth)) + + (((psiconv_u32) (p_green*mult+0.5)) << colordepth) + + ((psiconv_u32) (p_blue*mult+0.5)); } else { dist = 4; /* Max distance is 3, so this is safe */ pixel = -1; - for (i = 0; i < palet_len; i++) { + for (i = 0; i < palet.length; i++) { new_dist = (p_red - palet.red[i]) * (p_red - palet.red[i]) + (p_green - palet.green[i]) * (p_green - palet.green[i]) + (p_blue - palet.blue[i]) * (p_blue - palet.blue[i]); @@ -153,7 +215,8 @@ return res; } -int psiconv_pixel_data_to_bytes(const psiconv_config config, psiconv_pixel_bytes *bytes, int xsize, +int psiconv_pixel_data_to_bytes(const psiconv_config config, + psiconv_pixel_bytes *bytes, int xsize, int ysize, const psiconv_pixel_ints pixels, int colordepth) { @@ -163,7 +226,7 @@ psiconv_u32 inputdata; psiconv_u8 outputbyte; psiconv_u32 *pixelptr; - int inputbitsleft,outputbitnr,bitsfit; + int inputbitsleft,outputbitnr,bitsfit,outputbytenr; if (!bytes) { @@ -191,6 +254,7 @@ outputbitnr = 0; outputbyte = 0; for (y = 0; y < ysize; y++) { + outputbytenr = 0; for (x = 0; x < xsize; x++) { if (!(pixelptr = psiconv_list_get(pixels,y*xsize+x))) { psiconv_warn(config,0,0,"Massive internal corruption"); @@ -210,15 +274,23 @@ goto ERROR2; outputbitnr = 0; outputbyte = 0; + outputbytenr ++; } } } - /* Always end lines on a byte border */ + /* Always end lines on a long border */ if (outputbitnr != 0) { if ((res = psiconv_list_add(*bytes,&outputbyte))) goto ERROR2; outputbitnr = 0; outputbyte = 0; + outputbytenr ++; + } + + while (outputbytenr % 0x04) { + if ((res = psiconv_list_add(*bytes,&outputbyte))) + goto ERROR2; + outputbytenr ++; } } @@ -229,3 +301,56 @@ ERROR1: return res; } + +int psiconv_write_sketch_section(const psiconv_config config, + psiconv_buffer buf, + psiconv_sketch_section value) +{ + int res; + + if (!value) { + psiconv_warn(config,0,0,"NULL sketch section"); + res = -PSICONV_E_GENERATE; + goto ERROR1; + } + + if ((res = psiconv_write_u16(config,buf,value->displayed_xsize))) + goto ERROR1; + if ((res = psiconv_write_u16(config,buf,value->displayed_ysize))) + goto ERROR1; + if ((res = psiconv_write_u16(config,buf,value->picture_data_x_offset))) + goto ERROR1; + if ((res = psiconv_write_u16(config,buf,value->picture_data_y_offset))) + goto ERROR1; + if ((res = psiconv_write_u16(config,buf,value->displayed_size_x_offset))) + goto ERROR1; + if ((res = psiconv_write_u16(config,buf,value->displayed_size_y_offset))) + goto ERROR1; + if ((res = psiconv_write_u16(config,buf,value->form_xsize))) + goto ERROR1; + if ((res = psiconv_write_u16(config,buf,value->form_ysize))) + goto ERROR1; + if ((res = psiconv_write_u16(config,buf,0x0000))) + goto ERROR1; + if ((res = psiconv_write_paint_data_section(config,buf,value->picture))) + goto ERROR1; + if ((res = psiconv_write_u16(config,buf,value->magnification_x * 0x03e8))) + goto ERROR1; + if ((res = psiconv_write_u16(config,buf,value->magnification_y * 0x03e8))) + goto ERROR1; + if ((res = psiconv_write_u32(config,buf,value->cut_left * 0x0c * + value->displayed_xsize))) + goto ERROR1; + if ((res = psiconv_write_u32(config,buf,value->cut_right * 0x0c * + value->displayed_xsize))) + goto ERROR1; + if ((res = psiconv_write_u32(config,buf,value->cut_top * 0x0c * + value->displayed_ysize))) + goto ERROR1; + if ((res = psiconv_write_u32(config,buf,value->cut_bottom * 0x0c * + value->displayed_ysize))) + goto ERROR1; + +ERROR1: + return res; +}