--- psiconv/trunk/lib/psiconv/parse_image.c 1999/10/29 21:14:58 24 +++ psiconv/trunk/lib/psiconv/parse_image.c 1999/10/30 22:28:54 25 @@ -57,6 +57,40 @@ return res; } +static int decode_byte(int lev, psiconv_u32 off, + psiconv_paint_data_section data, int *pixelnr, + psiconv_u8 byte, int bits_per_pixel, int linelen, + int *linepos,int picsize) +{ + int mask = (bits_per_pixel << 1) -1; + int i; + if (*linepos < (data->xsize + (8/bits_per_pixel) - 1) / (8/bits_per_pixel)) + for (i = 0; i < 8/bits_per_pixel; i ++) { + if ((i != 0) && ((*pixelnr % (data->xsize)) == 0)) { + psiconv_debug(lev+1,off,"Skipping padding: %02x",byte); + i = 8; + } else if (*pixelnr >= picsize) { + psiconv_warn(lev+1,off,"Corrupted picture data!"); + psiconv_debug(lev+1,off,"Trying to write a pixel too far"); + return -1; + } else { + data->red[*pixelnr] = data->green[*pixelnr] = data->blue[*pixelnr] = + ((float) (byte & mask)) / ((1 << bits_per_pixel) -1); + psiconv_debug(lev+1,off,"Pixel %04x: (%04x,%04x) value %02x, color %f", + *pixelnr,*pixelnr % data->xsize,*pixelnr / data->xsize, byte&mask, data->red[*pixelnr]); + byte = byte >> bits_per_pixel; + (*pixelnr) ++; + } + } + else + psiconv_debug(lev+1,off,"Skipping padding byte"); + (*linepos) ++; + if (*linepos == linelen) + *linepos = 0; + return 0; +} + + int psiconv_parse_paint_data_section(const psiconv_buffer buf,int lev, psiconv_u32 off, int *length, psiconv_paint_data_section *result) @@ -66,7 +100,9 @@ int read_err = 0; psiconv_u32 size,offset,picsize,temp,datasize,pixelnr,datanr,linelen; psiconv_u8 marker; - int i; + int i,leng; + psiconv_u32 bits_per_pixel,compression; + int linepos = 0; psiconv_progress(lev+1,off,"Going to read a paint data section"); (*result) = malloc(sizeof(**result)); @@ -97,22 +133,51 @@ psiconv_debug(lev+2,off+len,"Picture Y size: %08x:",(*result)->ysize); len += 4; - picsize = (*result)->ysize * (*result)->xsize * 2; - linelen = (*result)->xsize; + picsize = (*result)->ysize * (*result)->xsize; + + psiconv_progress(lev+2,off+len,"Going to read the real picture x size"); + (*result)->pic_xsize = psiconv_read_length(buf,lev+2,off+len,&leng); + psiconv_debug(lev+2,off+len,"Picture x size: %f",(*result)->pic_xsize); + len += leng; + + psiconv_progress(lev+2,off+len,"Going to read the real picture y size"); + (*result)->pic_ysize = psiconv_read_length(buf,lev+2,off+len,&leng); + psiconv_debug(lev+2,off+len,"Picture y size: %f",(*result)->pic_ysize); + len += leng; + + psiconv_progress(lev+2,off+len,"Going to read the number of bits per pixel"); + bits_per_pixel=psiconv_read_u32(buf,lev+2,off+len); + if (bits_per_pixel > 8) { + psiconv_warn(lev+2,off+len,"Picture has too many colors"); + psiconv_debug(lev+2,off+len,"Read %d colorbits",bits_per_pixel); + res = -1; + bits_per_pixel = 2; + } + psiconv_debug(lev+2,off+len,"Bits per pixel: %d",bits_per_pixel); + len += 4; - psiconv_progress(lev+2,off+len,"Going to read 6 unknown longs"); - for (i = 0 ; i < 6; i++) { + for (i = 0 ; i < 2; i++) { temp = psiconv_read_u32(buf,lev+2,off+len); - if (temp != (i==2?0x02:i==5?0x01:0x00)) { + if (temp != 00) { psiconv_warn(lev+2,off+len, "Paint data section prologue has unknown values"); psiconv_debug(lev+2,off+len, - "offset %02x: read %08x, expected %08x",i,temp, - i==2?0x02:i==5?0x01:0x00); + "offset %02x: read %08x, expected %08x",i,temp, 0x00); res = -1; } len += 4; } + + psiconv_progress(lev+2,off+len, + "Going to read whether RLE compression is used"); + compression=psiconv_read_u32(buf,lev+2,off+len); + if (compression > 1) { + psiconv_warn(lev+2,off+len,"Paint data section has unknown " + "compression type, assuming RLE"); + psiconv_debug(lev+2,off+len,"Read compression type %d",compression); + compression = 1; + } + psiconv_debug(lev+2,off+len,"Compression: %s",compression?"RLE":"none"); (*result)->red = malloc(sizeof(float) * picsize); (*result)->green = malloc(sizeof(float) * picsize); @@ -123,65 +188,46 @@ psiconv_progress(lev+2,off+len,"Going to read the pixel data"); pixelnr = 0; datanr = 0; - while ((datanr < datasize) && (pixelnr < picsize)) { - marker = psiconv_read_u8(buf,lev+3,off+len+datanr); - psiconv_debug(lev+3,off+len+datanr, - "Pixelnr %08x, Datanr %08x: Read marker %02x", - pixelnr,datanr,marker); - datanr ++; - if (marker >= 0x80) { - /* 0x100 - marker bytes of data follow */ - for (i = 0; i < 0x100-marker; i++,datanr++) { - if ((picsize == pixelnr) || (datasize == datanr)) { - psiconv_warn(lev+3,off+len+datanr,"Corrupted picture data"); - psiconv_debug(lev+3,off+len+datanr, - "Picsize: %08x, Datasize: %08x, Pixelnr: %08x," - "Datanr: %08x, marker: %02x",picsize,datasize,pixelnr, - datanr,marker); - read_err = 1; - res = -1; - break; - } - temp = psiconv_read_u8(buf,lev+3,off+len+datanr); - (*result)->red[pixelnr] = - (*result)->green[pixelnr] = - (*result)->blue[pixelnr] = - (temp & 0x03) * (1.0/3.0); - pixelnr ++; - if (pixelnr % linelen == 0) - continue; - (*result)->red[pixelnr] = - (*result)->green[pixelnr] = - (*result)->blue[pixelnr] = - ((temp >> 2) & 0x03) * (1.0/3.0); - pixelnr ++; - if (pixelnr % linelen == 0) - continue; - (*result)->red[pixelnr] = - (*result)->green[pixelnr] = - (*result)->blue[pixelnr] = - ((temp >> 4) & 0x03) * (1.0/3.0); - pixelnr ++; - if (pixelnr % linelen == 0) - continue; - (*result)->red[pixelnr] = - (*result)->green[pixelnr] = - (*result)->blue[pixelnr] = - ((temp >> 6) & 0x03) * (1.0/3.0); - } - } else { /* marker < 0x080 */ - if (datasize == datanr) { - psiconv_warn(lev+3,off+len+datanr,"Corrupted picture data"); - psiconv_debug(lev+3,off+len+datanr, - "Picsize: %08x, Datasize: %08x, Pixelnr: %08x," - "Datanr: %08x, marker: %02x",picsize,datasize,pixelnr, - datanr,marker); + if (!compression) { + linelen = datasize / (*result)->ysize; + psiconv_debug(lev+3,off+len,"Line length: %04x bytes",linelen); + while((datanr < datasize)) { + temp = psiconv_read_u8(buf,lev+2,off+len+datanr); + if (decode_byte(lev+3,off+len+datanr,*result,&pixelnr,temp,bits_per_pixel, + linelen,&linepos,picsize)) { read_err = 1; res = -1; + break; + } + datanr++; + } + } else { + psiconv_progress(lev+2,off+len,"First pass: determining line length"); + datanr = 0; + i = 0; + while (datanr < datasize) { + marker = psiconv_read_u8(buf,lev+3,off+len+datanr); + if (marker >= 0x80) { + datanr += 0x100 - marker + 1; + i += 0x100 - marker; } else { - temp = psiconv_read_u8(buf,lev+3,off+len+datanr); - for (i = 0; i <= marker; i++) { - if (picsize == pixelnr) { + datanr += 2; + i += marker + 1; + } + } + linelen = i / (*result)->ysize; + datanr=0; + psiconv_debug(lev+2,off+len,"Linelen: %04x bytes",linelen); + while((datanr < datasize)) { + marker = psiconv_read_u8(buf,lev+3,off+len+datanr); + psiconv_debug(lev+3,off+len+datanr, + "Pixelnr %08x, Datanr %08x: Read marker %02x", + pixelnr,datanr,marker); + datanr ++; + if (marker >= 0x80) { + /* 0x100 - marker bytes of data follow */ + for (i = 0; i < 0x100-marker; i++,datanr++) { + if (datanr >= datasize) { psiconv_warn(lev+3,off+len+datanr,"Corrupted picture data"); psiconv_debug(lev+3,off+len+datanr, "Picsize: %08x, Datasize: %08x, Pixelnr: %08x," @@ -189,39 +235,45 @@ datanr,marker); read_err = 1; res = -1; - break; + break; + } + temp = psiconv_read_u8(buf,lev+2,off+len+datanr); + if (decode_byte(lev+2,off+len+datanr,*result,&pixelnr,temp, + bits_per_pixel,linelen,&linepos,picsize)) { + res = -1; + read_err = 1; + break; } - (*result)->red[pixelnr] = - (*result)->green[pixelnr] = - (*result)->blue[pixelnr] = - (temp & 0x03) * (1.0/3.0); - pixelnr ++; - if (pixelnr % linelen == 0) - continue; - (*result)->red[pixelnr] = - (*result)->green[pixelnr] = - (*result)->blue[pixelnr] = - ((temp >> 2) & 0x03) * (1.0/3.0); - pixelnr ++; - if (pixelnr % linelen == 0) - continue; - (*result)->red[pixelnr] = - (*result)->green[pixelnr] = - (*result)->blue[pixelnr] = - ((temp >> 4) & 0x03) * (1.0/3.0); - pixelnr ++; - if (pixelnr % linelen == 0) - continue; - (*result)->red[pixelnr] = - (*result)->green[pixelnr] = - (*result)->blue[pixelnr] = - ((temp >> 6) & 0x03) * (1.0/3.0); - pixelnr ++; - } + } + } else { + if (datanr >= datasize) { + psiconv_warn(lev+3,off+len+datanr,"Corrupted picture data"); + psiconv_debug(lev+3,off+len+datanr, + "Picsize: %08x, Datasize: %08x, Pixelnr: %08x," + "Datanr: %08x, marker: %02x",picsize,datasize,pixelnr, + datanr,marker); + read_err = 1; + res = -1; + } else { + temp = psiconv_read_u8(buf,lev+3,off+len+datanr); + for (i = 0; i <= marker; i++) { + if (decode_byte(lev+2,off+len+datanr,*result,&pixelnr,temp, + bits_per_pixel,linelen,&linepos,picsize)) { + read_err = 1; + res = -1; + break; + } + } + datanr ++; + } } - datanr += 1; } } + + if (linepos >= ((*result)->xsize + (8/bits_per_pixel) - 1) / + (8/bits_per_pixel)) + datanr += (linelen - linepos); + if (!read_err && ((datanr != datasize) || (pixelnr != picsize))) { psiconv_warn(lev+2,off+len,"Corrupted picture data!"); psiconv_debug(lev+3,off+len+datanr, @@ -241,9 +293,6 @@ return res; } - - - int psiconv_parse_sketch_section(const psiconv_buffer buf, int lev, psiconv_u32 off, int *length, int is_object, psiconv_sketch_section *result)