--- psiconv/trunk/lib/psiconv/generate_image.c 2003/11/27 12:08:13 174 +++ psiconv/trunk/lib/psiconv/generate_image.c 2003/11/27 20:55:01 175 @@ -23,6 +23,7 @@ #include "generate_routines.h" #include "error.h" +#include "list.h" #ifdef DMALLOC #include @@ -49,6 +50,15 @@ psiconv_pixel_bytes *bytes, int xsize, int ysize, const psiconv_pixel_ints pixels, int colordepth); +static int psiconv_encode_rle8(const psiconv_config config, + const psiconv_pixel_bytes plain_bytes, + psiconv_pixel_bytes *encoded_bytes); +static int psiconv_encode_rle16(const psiconv_config config, + const psiconv_pixel_bytes plain_bytes, + psiconv_pixel_bytes *encoded_bytes); +static int psiconv_encode_rle24(const psiconv_config config, + const psiconv_pixel_bytes plain_bytes, + psiconv_pixel_bytes *encoded_bytes); #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}; @@ -93,8 +103,8 @@ int res,colordepth,i; psiconv_pixel_ints ints; psiconv_pixel_floats_t floats,palet; - psiconv_list bytes; - psiconv_u8 *byteptr; + psiconv_list bytes,bytes_rle; + psiconv_u8 *byteptr,encoding; if (!value) { psiconv_warn(config,0,psiconv_buffer_length(buf),"Null paint data section"); @@ -124,7 +134,20 @@ ints,config->colordepth))) goto ERROR2; - if ((res = psiconv_write_u32(config,buf,0x28+psiconv_list_length(bytes)))) + + encoding = 0x00; + if ((res = psiconv_encode_rle8(config,bytes,&bytes_rle))) + goto ERROR3; + if (psiconv_list_length(bytes_rle) < psiconv_list_length(bytes)) { + encoding = 0x01; + psiconv_list_free(bytes); + bytes = bytes_rle; + } else { + bytes_rle = NULL; + } + + if ((res = psiconv_write_u32(config,buf, + 0x28+psiconv_list_length(bytes)))) goto ERROR3; if ((res = psiconv_write_u32(config,buf,0x28))) goto ERROR3; @@ -145,8 +168,7 @@ 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))) + if ((res = psiconv_write_u32(config,buf,encoding))) goto ERROR3; if (is_clipart) { if ((res = psiconv_write_u32(config,buf,0xffffffff))) @@ -310,6 +332,346 @@ return res; } +int psiconv_encode_rle8(const psiconv_config config, + const psiconv_pixel_bytes plain_bytes, + psiconv_pixel_bytes *encoded_bytes) +{ + int res,i,j,len; + psiconv_u8 *entry,*next; + psiconv_u8 temp; + + if (!(*encoded_bytes = psiconv_list_new(sizeof(*entry)))) { + res = -PSICONV_E_NOMEM; + goto ERROR1; + } + + for (i = 0; i < psiconv_list_length(plain_bytes);) { + if (!(entry = psiconv_list_get(plain_bytes,i))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + if (!(next = psiconv_list_get(plain_bytes,i+1))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + if (i == psiconv_list_length(plain_bytes) - 2) { + temp = 0xfe; + if ((res = psiconv_list_add(*encoded_bytes,&temp))) + goto ERROR2; + if ((res = psiconv_list_add(*encoded_bytes,entry))) + goto ERROR2; + if ((res = psiconv_list_add(*encoded_bytes,next))) + goto ERROR2; + i +=2; + } else if (*next == *entry) { + len = 0; + while ((*next == *entry) && + (i+len + 1 < psiconv_list_length(plain_bytes)) && + len < 0x80) { + len ++; + if (!(next = psiconv_list_get(plain_bytes,i+len))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + } + temp = len - 1; + if ((res = psiconv_list_add(*encoded_bytes,&temp))) + goto ERROR2; + if ((res = psiconv_list_add(*encoded_bytes,entry))) + goto ERROR2; + i += len; + } else { + len = 1; + while ((*next != *entry) && + (i+len+1 < psiconv_list_length(plain_bytes)) && + len < 0x80) { + len ++; + entry = next; + if (!(next = psiconv_list_get(plain_bytes,i+len))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + } + len --; + temp = 0x100 - len; + if ((res = psiconv_list_add(*encoded_bytes,&temp))) + goto ERROR2; + for (j = 0; j < len; j++) { + if (!(next = psiconv_list_get(plain_bytes,i+j))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + if ((res = psiconv_list_add(*encoded_bytes,next))) + goto ERROR2; + } + i += len; + } + } + return 0; + +ERROR2: + psiconv_list_free(*encoded_bytes); +ERROR1: + return res; +} + +int psiconv_encode_rle16(const psiconv_config config, + const psiconv_pixel_bytes plain_bytes, + psiconv_pixel_bytes *encoded_bytes) +{ + int res,i,j,len; + psiconv_u8 *entry1,*entry2,*next1,*next2; + psiconv_u8 temp; + + if (!(*encoded_bytes = psiconv_list_new(sizeof(*entry1)))) { + res = -PSICONV_E_NOMEM; + goto ERROR1; + } + + for (i = 0; i < psiconv_list_length(plain_bytes);) { + if (!(entry1 = psiconv_list_get(plain_bytes,i))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + if (!(entry2 = psiconv_list_get(plain_bytes,i+1))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + if (!(next1 = psiconv_list_get(plain_bytes,i+2))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + if (!(next2 = psiconv_list_get(plain_bytes,i+3))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + if (i == psiconv_list_length(plain_bytes) - 4) { + temp = 0xfe; + if ((res = psiconv_list_add(*encoded_bytes,&temp))) + goto ERROR2; + if ((res = psiconv_list_add(*encoded_bytes,entry1))) + goto ERROR2; + if ((res = psiconv_list_add(*encoded_bytes,entry2))) + goto ERROR2; + if ((res = psiconv_list_add(*encoded_bytes,next1))) + goto ERROR2; + if ((res = psiconv_list_add(*encoded_bytes,next2))) + goto ERROR2; + i +=4; + } else if ((*next1 == *entry1) && (*next2 == *entry2)) { + len = 0; + while (((*next1 == *entry1) && (*next2 == *entry2)) && + (i+2*len + 4 < psiconv_list_length(plain_bytes)) && + len < 0x80) { + len ++; + if (!(next1 = psiconv_list_get(plain_bytes,i+len*2))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + if (!(next2 = psiconv_list_get(plain_bytes,i+len*2+1))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + } + temp = len - 1; + if ((res = psiconv_list_add(*encoded_bytes,&temp))) + goto ERROR2; + if ((res = psiconv_list_add(*encoded_bytes,entry1))) + goto ERROR2; + if ((res = psiconv_list_add(*encoded_bytes,entry2))) + goto ERROR2; + i += len*2; + } else { + len = 1; + while (((*next1 != *entry1) || (*next2 != *entry2))&& + (i+len*2+4 < psiconv_list_length(plain_bytes)) && + len < 0x80) { + len ++; + entry1 = next1; + entry2 = next2; + if (!(next1 = psiconv_list_get(plain_bytes,i+len*2))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + if (!(next2 = psiconv_list_get(plain_bytes,i+len*2+1))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + } + len --; + temp = 0x100 - len; + if ((res = psiconv_list_add(*encoded_bytes,&temp))) + goto ERROR2; + for (j = 0; j < len; j++) { + if (!(next1 = psiconv_list_get(plain_bytes,i+j*2))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + if (!(next2 = psiconv_list_get(plain_bytes,i+j*2+1))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + if ((res = psiconv_list_add(*encoded_bytes,next1))) + goto ERROR2; + if ((res = psiconv_list_add(*encoded_bytes,next2))) + goto ERROR2; + } + i += len*2; + } + } + return 0; + +ERROR2: + psiconv_list_free(*encoded_bytes); +ERROR1: + return res; +} + +int psiconv_encode_rle24(const psiconv_config config, + const psiconv_pixel_bytes plain_bytes, + psiconv_pixel_bytes *encoded_bytes) +{ + int res,i,j,len; + psiconv_u8 *entry1,*entry2,*entry3,*next1,*next2,*next3; + psiconv_u8 temp; + + if (!(*encoded_bytes = psiconv_list_new(sizeof(*entry1)))) { + res = -PSICONV_E_NOMEM; + goto ERROR1; + } + + for (i = 0; i < psiconv_list_length(plain_bytes);) { + if (!(entry1 = psiconv_list_get(plain_bytes,i))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + if (!(entry2 = psiconv_list_get(plain_bytes,i+1))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + if (!(entry3 = psiconv_list_get(plain_bytes,i+2))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + if (!(next1 = psiconv_list_get(plain_bytes,i+3))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + if (!(next2 = psiconv_list_get(plain_bytes,i+4))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + if (!(next3 = psiconv_list_get(plain_bytes,i+5))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + if (i == psiconv_list_length(plain_bytes) - 6) { + temp = 0xfe; + if ((res = psiconv_list_add(*encoded_bytes,&temp))) + goto ERROR2; + if ((res = psiconv_list_add(*encoded_bytes,entry1))) + goto ERROR2; + if ((res = psiconv_list_add(*encoded_bytes,entry2))) + goto ERROR2; + if ((res = psiconv_list_add(*encoded_bytes,entry3))) + goto ERROR2; + if ((res = psiconv_list_add(*encoded_bytes,next1))) + goto ERROR2; + if ((res = psiconv_list_add(*encoded_bytes,next2))) + goto ERROR2; + if ((res = psiconv_list_add(*encoded_bytes,next3))) + goto ERROR2; + i +=4; + } else if ((*next1 == *entry1) && (*next2 == *entry2) && + (*next3 == *entry3)) { + len = 0; + while (((*next1 == *entry1) && (*next2 == *entry2) && + (*next3 == *entry3)) && + (i+3*len + 6 < psiconv_list_length(plain_bytes)) && + len < 0x80) { + len ++; + if (!(next1 = psiconv_list_get(plain_bytes,i+len*3))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + if (!(next2 = psiconv_list_get(plain_bytes,i+len*3+1))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + if (!(next3 = psiconv_list_get(plain_bytes,i+len*3+2))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + } + temp = len - 1; + if ((res = psiconv_list_add(*encoded_bytes,&temp))) + goto ERROR2; + if ((res = psiconv_list_add(*encoded_bytes,entry1))) + goto ERROR2; + if ((res = psiconv_list_add(*encoded_bytes,entry2))) + goto ERROR2; + if ((res = psiconv_list_add(*encoded_bytes,entry3))) + goto ERROR2; + i += len*3; + } else { + len = 1; + while (((*next1 != *entry1) || (*next2 != *entry2) || + (*next3 != *entry3)) && + (i+len*3+6 < psiconv_list_length(plain_bytes)) && + len < 0x80) { + len ++; + entry1 = next1; + entry2 = next2; + entry3 = next3; + if (!(next1 = psiconv_list_get(plain_bytes,i+len*3))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + if (!(next2 = psiconv_list_get(plain_bytes,i+len*3+1))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + if (!(next3 = psiconv_list_get(plain_bytes,i+len*3+2))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + } + len --; + temp = 0x100 - len; + if ((res = psiconv_list_add(*encoded_bytes,&temp))) + goto ERROR2; + for (j = 0; j < len; j++) { + if (!(next1 = psiconv_list_get(plain_bytes,i+j*3))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + if (!(next2 = psiconv_list_get(plain_bytes,i+j*3+1))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + if (!(next2 = psiconv_list_get(plain_bytes,i+j*3+2))) { + res = -PSICONV_E_NOMEM; + goto ERROR2; + } + if ((res = psiconv_list_add(*encoded_bytes,next1))) + goto ERROR2; + if ((res = psiconv_list_add(*encoded_bytes,next2))) + goto ERROR2; + if ((res = psiconv_list_add(*encoded_bytes,next3))) + goto ERROR2; + } + i += len*3; + } + } + return 0; + +ERROR2: + psiconv_list_free(*encoded_bytes); +ERROR1: + return res; +} + + int psiconv_write_sketch_section(const psiconv_config config, psiconv_buffer buf, const psiconv_sketch_section value) @@ -363,6 +725,36 @@ return res; } +int psiconv_write_clipart_section(const psiconv_config config, + psiconv_buffer buf, + const psiconv_clipart_section value) +{ + int res; + + + if (!value) { + psiconv_warn(config,0,psiconv_buffer_length(buf), + "NULL Clipart Section"); + res = -PSICONV_E_GENERATE; + goto ERROR; + } + if ((res = psiconv_write_u32(config,buf,PSICONV_ID_CLIPART_ITEM))) + goto ERROR; + if ((res = psiconv_write_u32(config,buf,0x00000002))) + goto ERROR; + if ((res = psiconv_write_u32(config,buf,0x00000000))) + goto ERROR; + if ((res = psiconv_write_u32(config,buf,0x00000000))) + goto ERROR; + if ((res = psiconv_write_u32(config,buf,0x0000000C))) + goto ERROR; + if ((res = psiconv_write_paint_data_section(config,buf,value->picture,1))) + goto ERROR; + +ERROR: + return res; +} + int psiconv_write_jumptable_section(const psiconv_config config, psiconv_buffer buf, const psiconv_jumptable_section value) @@ -394,32 +786,3 @@ return res; } -int psiconv_write_clipart_section(const psiconv_config config, - psiconv_buffer buf, - const psiconv_clipart_section value) -{ - int res; - - - if (!value) { - psiconv_warn(config,0,psiconv_buffer_length(buf), - "NULL Clipart Section"); - res = -PSICONV_E_GENERATE; - goto ERROR; - } - if ((res = psiconv_write_u32(config,buf,PSICONV_ID_CLIPART_ITEM))) - goto ERROR; - if ((res = psiconv_write_u32(config,buf,0x00000002))) - goto ERROR; - if ((res = psiconv_write_u32(config,buf,0x00000000))) - goto ERROR; - if ((res = psiconv_write_u32(config,buf,0x00000000))) - goto ERROR; - if ((res = psiconv_write_u32(config,buf,0x0000000C))) - goto ERROR; - if ((res = psiconv_write_paint_data_section(config,buf,value->picture,1))) - goto ERROR; - -ERROR: - return res; -}