--- psiconv/trunk/lib/psiconv/generate_image.c 2003/11/26 20:56:17 171 +++ psiconv/trunk/lib/psiconv/generate_image.c 2003/11/27 20:55:01 175 @@ -1,4 +1,5 @@ /* + generate_image.c - Part of psiconv, a PSION 5 file formats converter Copyright (c) 1999, 2000 Frodo Looijaard @@ -22,6 +23,7 @@ #include "generate_routines.h" #include "error.h" +#include "list.h" #ifdef DMALLOC #include @@ -48,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}; @@ -86,13 +97,14 @@ int psiconv_write_paint_data_section(const psiconv_config config, psiconv_buffer buf, - const psiconv_paint_data_section value) + const psiconv_paint_data_section value, + int is_clipart) { 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"); @@ -122,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; @@ -143,9 +168,14 @@ 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))) + goto ERROR3; + if ((res = psiconv_write_u32(config,buf,0x00000044))) + goto ERROR3; + } for (i = 0; i < psiconv_list_length(bytes); i++) { if (!(byteptr = psiconv_list_get(bytes,i))) goto ERROR3; @@ -302,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) @@ -332,7 +702,7 @@ goto ERROR1; if ((res = psiconv_write_u16(config,buf,0x0000))) goto ERROR1; - if ((res = psiconv_write_paint_data_section(config,buf,value->picture))) + if ((res = psiconv_write_paint_data_section(config,buf,value->picture,0))) goto ERROR1; if ((res = psiconv_write_u16(config,buf,value->magnification_x * 0x03e8))) goto ERROR1; @@ -355,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) @@ -385,3 +785,4 @@ ERROR: return res; } +