--- psiconv/trunk/lib/psiconv/parse_image.c 2003/12/03 15:16:43 178 +++ psiconv/trunk/lib/psiconv/parse_image.c 2003/12/13 18:23:16 179 @@ -35,6 +35,21 @@ const psiconv_pixel_bytes encoded, psiconv_pixel_bytes *decoded); +static int psiconv_decode_rle12 (const psiconv_config config, int lev, + psiconv_u32 off, + const psiconv_pixel_bytes encoded, + psiconv_pixel_bytes *decoded); + +static int psiconv_decode_rle16 (const psiconv_config config, int lev, + psiconv_u32 off, + const psiconv_pixel_bytes encoded, + psiconv_pixel_bytes *decoded); + +static int psiconv_decode_rle24 (const psiconv_config config, int lev, + psiconv_u32 off, + const psiconv_pixel_bytes encoded, + psiconv_pixel_bytes *decoded); + static int psiconv_bytes_to_pixel_data(const psiconv_config config, int lev, psiconv_u32 off, const psiconv_pixel_bytes bytes, @@ -103,41 +118,6 @@ return res; } -static int decode_byte(const psiconv_config config, int lev, psiconv_u32 off, - psiconv_paint_data_section data, psiconv_u32 *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(config,lev+1,off,"Skipping padding: %02x",byte); - i = 8; - } else if (*pixelnr >= picsize) { - psiconv_warn(config,lev+1,off,"Corrupted picture data!"); - psiconv_debug(config,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(config,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(config,lev+1,off,"Skipping padding byte"); - (*linepos) ++; - if (*linepos == linelen) - *linepos = 0; - return 0; -} - - int psiconv_parse_paint_data_section(const psiconv_config config, const psiconv_buffer buf,int lev, psiconv_u32 off, int *length,int isclipart, @@ -145,27 +125,33 @@ { int res = 0; int len = 0; - psiconv_u32 size,offset,picsize,temp,datasize,pixelnr,datanr,linelen; - psiconv_u8 marker; - int i,leng; + psiconv_u32 size,offset,picsize,temp,datasize,color, + redbits,bluebits,greenbits; + psiconv_u8 byte; + int leng,i; psiconv_u32 bits_per_pixel,compression; - int linepos = 0; + psiconv_pixel_bytes bytes,decoded; + psiconv_pixel_ints pixels; + psiconv_pixel_floats_t floats,palet; psiconv_progress(config,lev+1,off,"Going to read a paint data section"); if (!((*result) = malloc(sizeof(**result)))) goto ERROR1; + if (!(bytes = psiconv_list_new(sizeof(psiconv_u8)))) + goto ERROR2; + psiconv_progress(config,lev+2,off+len,"Going to read section size"); size = psiconv_read_u32(config,buf,lev+2,off+len,&res); if (res) - goto ERROR2; + goto ERROR3; psiconv_debug(config,lev+2,off+len,"Section size: %08x",size); len += 4; psiconv_progress(config,lev+2,off+len,"Going to read pixel data offset"); offset = psiconv_read_u32(config,buf,lev+2,off+len,&res); if (res) - goto ERROR2; + goto ERROR3; if (offset != 0x28) { psiconv_warn(config,lev+2,off+len, "Paint data section data offset has unexpected value"); @@ -178,14 +164,14 @@ psiconv_progress(config,lev+2,off+len,"Going to read picture X size"); (*result)->xsize = psiconv_read_u32(config,buf,lev+2,off+len,&res); if (res) - goto ERROR2; + goto ERROR3; psiconv_debug(config,lev+2,off+len,"Picture X size: %08x:",(*result)->xsize); len += 4; psiconv_progress(config,lev+2,off+len,"Going to read picture Y size"); (*result)->ysize = psiconv_read_u32(config,buf,lev+2,off+len,&res); if (res) - goto ERROR2; + goto ERROR3; psiconv_debug(config,lev+2,off+len,"Picture Y size: %08x:",(*result)->ysize); len += 4; @@ -194,213 +180,187 @@ psiconv_progress(config,lev+2,off+len,"Going to read the real picture x size"); (*result)->pic_xsize = psiconv_read_length(config,buf,lev+2,off+len,&leng,&res); if (res) - goto ERROR2; + goto ERROR3; psiconv_debug(config,lev+2,off+len,"Picture x size: %f",(*result)->pic_xsize); len += leng; psiconv_progress(config,lev+2,off+len,"Going to read the real picture y size"); (*result)->pic_ysize = psiconv_read_length(config,buf,lev+2,off+len,&leng,&res); if (res) - goto ERROR2; + goto ERROR3; psiconv_debug(config,lev+2,off+len,"Picture y size: %f",(*result)->pic_ysize); len += leng; psiconv_progress(config,lev+2,off+len,"Going to read the number of bits per pixel"); bits_per_pixel=psiconv_read_u32(config,buf,lev+2,off+len,&res); if (res) - goto ERROR2; - if (bits_per_pixel > 8) { - psiconv_warn(config,lev+2,off+len,"Picture has too many colors"); - psiconv_debug(config,lev+2,off+len,"Read %d colorbits",bits_per_pixel); - res = -PSICONV_E_PARSE; - goto ERROR2; - } + goto ERROR3; psiconv_debug(config,lev+2,off+len,"Bits per pixel: %d",bits_per_pixel); len += 4; - for (i = 0 ; i < 2; i++) { - temp = psiconv_read_u32(config,buf,lev+2,off+len,&res); - if (res) - goto ERROR2; - if (temp != 00) { - psiconv_warn(config,lev+2,off+len, - "Paint data section prologue has unknown values (ignored)"); - psiconv_debug(config,lev+2,off+len, - "offset %02x: read %08x, expected %08x",i,temp, 0x00); - } - len += 4; + psiconv_progress(config,lev+2,off+len, + "Going to read whether this is a colour or greyscale picture"); + color = psiconv_read_u32(config,buf,lev+2,off+len,&res); + if (res) + goto ERROR3; + if ((color != 0) && (color != 1)) { + psiconv_warn(config,lev+2,off+len, + "Paint data section unknown color type (ignored)"); + psiconv_debug(config,lev+2,off+len, + "Color: read %08x, expected %08x or %08x",color,0,1); + color = 1; + } else { + psiconv_debug(config,lev+2,off+len,"Color: %08x (%s picture)", + color,(color?"color":"greyscale")); + } + len += 4; + + temp = psiconv_read_u32(config,buf,lev+2,off+len,&res); + if (res) + goto ERROR3; + if (temp != 00) { + psiconv_warn(config,lev+2,off+len, + "Paint data section prologue has unknown values (ignored)"); + psiconv_debug(config,lev+2,off+len, + "read %08x, expected %08x",temp, 0x00); } + len += 4; psiconv_progress(config,lev+2,off+len, "Going to read whether RLE compression is used"); compression=psiconv_read_u32(config,buf,lev+2,off+len,&res); if (res) - goto ERROR2; - if (compression > 1) { + goto ERROR3; + if (compression > 4) { psiconv_warn(config,lev+2,off+len,"Paint data section has unknown " "compression type, assuming RLE"); psiconv_debug(config,lev+2,off+len,"Read compression type %d",compression); - compression = 1; + compression = 0; } - psiconv_debug(config,lev+2,off+len,"Compression: %s",compression?"RLE8":"none"); + psiconv_debug(config,lev+2,off+len,"Compression: %s", + compression == 4?"RLE24":compression == 3?"RLE16": + compression == 2?"RLE12":compression == 1?"RLE8":"none"); len += 4; if (isclipart) { psiconv_progress(config,lev+2,off+len,"Going to read an unknown long"); temp = psiconv_read_u32(config,buf,lev+2,off+len,&res); if (res) - goto ERROR2; + goto ERROR3; if (temp != 0xffffffff) { psiconv_warn(config,lev+2,off+len, "Paint data section prologue has unknown values (ignoring)"); psiconv_debug(config,lev+2,off+len, - "offset %02x: read %08x, expected %08x",i,temp, 0xffffffff); + "Read %08x, expected %08x",temp, 0xffffffff); } len += 4; psiconv_progress(config,lev+2,off+len,"Going to read a second unknown long"); temp = psiconv_read_u32(config,buf,lev+2,off+len,&res); if (res) - goto ERROR2; + goto ERROR3; if (temp != 0x44) { psiconv_warn(config,lev+2,off+len, "Paint data section prologue has unknown values (ignoring)"); psiconv_debug(config,lev+2,off+len, - "offset %02x: read %08x, expected %08x",i,temp, 0x44); + "read %08x, expected %08x",temp, 0x44); } len += 4; } - if (!((*result)->red = malloc(sizeof(float) * picsize))) - goto ERROR2; - if (!((*result)->green = malloc(sizeof(float) * picsize))) - goto ERROR3; - if (!((*result)->blue = malloc(sizeof(float) * picsize))) - goto ERROR4; len = offset; datasize = size - len; if (isclipart) len += 8; + if (color || (bits_per_pixel != 2)) + psiconv_warn(config,lev+2,off+len, + "All image types except 2-bit greyscale are experimental!"); + psiconv_progress(config,lev+2,off+len,"Going to read the pixel data"); - pixelnr = 0; - datanr = 0; - if (!compression) { - linelen = datasize / (*result)->ysize; - psiconv_debug(config,lev+3,off+len,"Line length: %04x bytes",linelen); - while((datanr < datasize)) { - temp = psiconv_read_u8(config,buf,lev+2,off+len+datanr,&res); - if (res) - goto ERROR5; - if (decode_byte(config,lev+3,off+len+datanr,*result,&pixelnr,temp,bits_per_pixel, - linelen,&linepos,picsize)) { - res = -PSICONV_E_PARSE; - break; - } - datanr++; - } - } else { - psiconv_progress(config,lev+2,off+len,"First pass: determining line length"); - datanr = 0; - i = 0; - while (datanr < datasize) { - marker = psiconv_read_u8(config,buf,lev+3,off+len+datanr,&res); - if (res) - goto ERROR5; - if (marker >= 0x80) { - datanr += 0x100 - marker + 1; - i += 0x100 - marker; - } else { - datanr += 2; - i += marker + 1; - } - } - linelen = i / (*result)->ysize; - datanr=0; - psiconv_debug(config,lev+2,off+len,"Linelen: %04x bytes",linelen); - while((datanr < datasize)) { - marker = psiconv_read_u8(config,buf,lev+3,off+len+datanr,&res); - if (res) - goto ERROR5; - psiconv_debug(config,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(config,lev+3,off+len+datanr,"Corrupted picture data"); - psiconv_debug(config,lev+3,off+len+datanr, - "Picsize: %08x, Datasize: %08x, Pixelnr: %08x," - "Datanr: %08x, marker: %02x",picsize,datasize,pixelnr, - datanr,marker); - res = -PSICONV_E_PARSE; - break; - } - temp = psiconv_read_u8(config,buf,lev+2,off+len+datanr,&res); - if (res) - goto ERROR5; - if (decode_byte(config,lev+2,off+len+datanr,*result,&pixelnr,temp, - bits_per_pixel,linelen,&linepos,picsize)) { - res = -PSICONV_E_PARSE; - break; - } - } - } else { - if (datanr >= datasize) { - psiconv_warn(config,lev+3,off+len+datanr,"Corrupted picture data"); - psiconv_debug(config,lev+3,off+len+datanr, - "Picsize: %08x, Datasize: %08x, Pixelnr: %08x," - "Datanr: %08x, marker: %02x",picsize,datasize,pixelnr, - datanr,marker); - res = -PSICONV_E_PARSE; - } else { - temp = psiconv_read_u8(config,buf,lev+3,off+len+datanr,&res); - if (res) - goto ERROR5; - for (i = 0; i <= marker; i++) { - if (decode_byte(config,lev+2,off+len+datanr,*result,&pixelnr,temp, - bits_per_pixel,linelen,&linepos,picsize)) { - res = -PSICONV_E_PARSE; - break; - } - } - datanr ++; - } - } - } + for (i = 0; i < datasize; i++) { + byte = psiconv_read_u8(config,buf,lev+2,off+len+i,&res); + psiconv_debug(config,lev+2,off+len+i, + "Pixel byte %04x of %04x has value %02x", + i,datasize,byte); + if (res) + goto ERROR3; + psiconv_list_add(bytes,&byte); } + len += datasize; - if (linepos >= ((*result)->xsize + (8/bits_per_pixel) - 1) / - (8/bits_per_pixel)) - datanr += (linelen - linepos); - - if (res || (datanr != datasize) || (pixelnr != picsize)) { - psiconv_warn(config,lev+2,off+len,"Corrupted picture data!"); - psiconv_debug(config,lev+3,off+len+datanr, - "Picsize: %08x, Datasize: %08x, Pixelnr: %08x," - "Datanr: %08x",picsize,datasize,pixelnr,datanr); - goto ERROR5; + switch(compression) { + case 1: + if ((res = psiconv_decode_rle8(config,lev+2,off+len,bytes,&decoded))) + goto ERROR3; + psiconv_list_free(bytes); + bytes = decoded; + break; + case 2: + if ((psiconv_decode_rle12(config,lev+2,off+len,bytes,&decoded))) + goto ERROR3; + psiconv_list_free(bytes); + bytes = decoded; + break; + case 3: + if ((psiconv_decode_rle16(config,lev+2,off+len,bytes,&decoded))) + goto ERROR3; + psiconv_list_free(bytes); + bytes = decoded; + break; + case 4: + if ((psiconv_decode_rle24(config,lev+2,off+len,bytes,&decoded))) + goto ERROR3; + psiconv_list_free(bytes); + bytes = decoded; + break; + } + + if ((res = psiconv_bytes_to_pixel_data(config,lev+2,off+len,bytes, + &pixels,bits_per_pixel, + (*result)->xsize,(*result)->ysize))) + goto ERROR3; + + /* Use some heuristics; things may get unexpected around here */ + bluebits = redbits = greenbits = 0; + palet = psiconv_palet_none; + if (color) { + if (bits_per_pixel == 4) + palet = psiconv_palet_color_4; + else if (bits_per_pixel == 8) + palet = psiconv_palet_color_8; + else { + redbits = (bits_per_pixel+2) / 3; + greenbits = (bits_per_pixel+2) / 3; + bluebits = bits_per_pixel - redbits - greenbits; + } } + if ((res = psiconv_pixel_data_to_floats(config,lev+2,off+len,pixels, + &floats,bits_per_pixel,color, + redbits,greenbits,bluebits,palet))) + goto ERROR4; + + (*result)->red = floats.red; + (*result)->green = floats.green; + (*result)->blue = floats.blue; + + psiconv_list_free(bytes); + psiconv_list_free(pixels); - len += datanr; if (length) *length = len; - psiconv_progress(config,lev+1,off+len-1,"End of paint data section " - "(total length: %08x)", len); + psiconv_progress(config,lev,off+len-1, + "End of Paint Data Section (total length: %08x)", len); - return res; + return 0; -ERROR5: - free((*result)->blue); ERROR4: - free((*result)->green); + psiconv_list_free(pixels); ERROR3: - free((*result)->red); + psiconv_list_free(bytes); ERROR2: - free (*result); + free(*result); ERROR1: psiconv_warn(config,lev+1,off,"Reading of Paint Data Section failed"); if (length) @@ -703,7 +663,7 @@ if (!(value = psiconv_list_get(encoded,i+1))) goto ERROR2; psiconv_debug(config,lev+2,off,"Value byte: %02x",*value); - psiconv_progress(config,lev+2,off,"Adding %02x bytes %02x", + psiconv_progress(config,lev+2,off,"Adding %02x pixels %02x", *marker+1,*value); for (j = 0; j < *marker + 1; j++) if ((res = psiconv_list_add(*decoded,value))) @@ -736,6 +696,185 @@ return -PSICONV_E_NOMEM; else return res; +} + +int psiconv_decode_rle12 (const psiconv_config config, int lev, psiconv_u32 off, + const psiconv_pixel_bytes encoded, + psiconv_pixel_bytes *decoded) +{ + int res=0; + psiconv_u8 *value0,*value1; + psiconv_u32 value,repeat; + int i,j; + + psiconv_progress(config,lev+1,off,"Going to decode the RLE12 encoding"); + if (!(*decoded = psiconv_list_new(sizeof(psiconv_u8)))) + goto ERROR1; + + for (i = 0; i < psiconv_list_length(encoded);) { + psiconv_progress(config,lev+2,off,"Going to read data word at %04x",i); + if (!(value0 = psiconv_list_get(encoded,i))) + goto ERROR2; + if (!(value1 = psiconv_list_get(encoded,i+1))) + goto ERROR2; + psiconv_debug(config,lev+2,off,"Data Word: %04x",*value0 + (*value1 << 8)); + value = *value0 + ((*value1 & 0x0f) << 8); + repeat = (*value1 >> 4) + 1; + psiconv_progress(config,lev+2,off,"Adding %02x pixels %03x", + repeat,value); + for (j = 0; j < repeat; j ++) + if ((res = psiconv_list_add(*decoded,&value))) + goto ERROR2; + i += 2; + } + psiconv_progress(config,lev,off, + "End of RLE12 decoding process"); + return 0; + +ERROR2: + psiconv_list_free(*decoded); +ERROR1: + psiconv_warn(config,lev+1,off,"Decoding of RLE12 failed"); + if (!res) + return -PSICONV_E_NOMEM; + else + return res; +} + +int psiconv_decode_rle16 (const psiconv_config config, int lev, psiconv_u32 off, + const psiconv_pixel_bytes encoded, + psiconv_pixel_bytes *decoded) +{ + int res=0; + psiconv_u8 *marker,*value0,*value1; + psiconv_u32 value; + int i,j; + + psiconv_progress(config,lev+1,off,"Going to decode the RLE16 encoding"); + if (!(*decoded = psiconv_list_new(sizeof(psiconv_u8)))) + goto ERROR1; + + for (i = 0; i < psiconv_list_length(encoded);) { + psiconv_progress(config,lev+2,off,"Going to read marker byte at %04x",i); + if (!(marker = psiconv_list_get(encoded,i))) + goto ERROR2; + psiconv_debug(config,lev+2,off,"Marker byte: %02x",*marker); + if (*marker < 0x80) { + psiconv_debug(config,lev+2,off,"Marker: repeat value word %02x times", + *marker+1); + psiconv_progress(config,lev+2,off,"Going to read value word at %04x",i+1); + if (!(value0 = psiconv_list_get(encoded,i+1))) + goto ERROR2; + if (!(value1 = psiconv_list_get(encoded,i+2))) + goto ERROR2; + value = *value0 + (*value1 << 8); + psiconv_debug(config,lev+2,off,"Value word: %02x",value); + psiconv_progress(config,lev+2,off,"Adding %02x pixels %04x", + *marker+1,value); + for (j = 0; j < *marker + 1; j++) + if ((res = psiconv_list_add(*decoded,&value))) + goto ERROR2; + i += 3; + } else { + psiconv_debug(config,lev+2,off,"Marker: %02x value words follow", + 0x100 - *marker); + for (j = 0; j < (0x100 - *marker); j++) { + psiconv_progress(config,lev+2,off,"Going to read value word at %04x", + i+j*2+1); + if (!(value0 = psiconv_list_get(encoded,i+j*2+1))) + goto ERROR2; + if (!(value1 = psiconv_list_get(encoded,i+j*2+2))) + goto ERROR2; + value = *value0 + (*value1 << 8); + psiconv_debug(config,lev+2,off,"Value: %04x",value); + if ((res = psiconv_list_add(*decoded,&value))) + goto ERROR2; + } + i += (0x100 - *marker)*2 + 1; + } + } + psiconv_progress(config,lev,off, + "End of RLE16 decoding process"); + return 0; + +ERROR2: + psiconv_list_free(*decoded); +ERROR1: + psiconv_warn(config,lev+1,off,"Decoding of RLE16 failed"); + if (!res) + return -PSICONV_E_NOMEM; + else + return res; +} + +int psiconv_decode_rle24 (const psiconv_config config, int lev, psiconv_u32 off, + const psiconv_pixel_bytes encoded, + psiconv_pixel_bytes *decoded) +{ + int res=0; + psiconv_u8 *marker,*value0,*value1,*value2; + psiconv_u32 value; + int i,j; + + psiconv_progress(config,lev+1,off,"Going to decode the RLE24 encoding"); + if (!(*decoded = psiconv_list_new(sizeof(psiconv_u8)))) + goto ERROR1; + + for (i = 0; i < psiconv_list_length(encoded);) { + psiconv_progress(config,lev+2,off,"Going to read marker byte at %04x",i); + if (!(marker = psiconv_list_get(encoded,i))) + goto ERROR2; + psiconv_debug(config,lev+2,off,"Marker byte: %02x",*marker); + if (*marker < 0x80) { + psiconv_debug(config,lev+2,off,"Marker: repeat value byte triplet %02x times", + *marker+1); + psiconv_progress(config,lev+2,off,"Going to read value byte triplet at %04x",i+1); + if (!(value0 = psiconv_list_get(encoded,i+1))) + goto ERROR2; + if (!(value1 = psiconv_list_get(encoded,i+2))) + goto ERROR2; + if (!(value2 = psiconv_list_get(encoded,i+3))) + goto ERROR2; + value = *value0 + (*value1 << 8) + (*value2 << 16); + psiconv_debug(config,lev+2,off,"Value byte triplet: %06x",value); + psiconv_progress(config,lev+2,off,"Adding %02x pixels %06x", + *marker+1,value); + for (j = 0; j < *marker + 1; j++) + if ((res = psiconv_list_add(*decoded,&value))) + goto ERROR2; + i += 4; + } else { + psiconv_debug(config,lev+2,off,"Marker: %02x value byte triplets follow", + 0x100 - *marker); + for (j = 0; j < (0x100 - *marker); j++) { + psiconv_progress(config,lev+2,off,"Going to read value byte triplets at %04x", + i+j*3+1); + if (!(value0 = psiconv_list_get(encoded,i+j*3+1))) + goto ERROR2; + if (!(value1 = psiconv_list_get(encoded,i+j*3+2))) + goto ERROR2; + if (!(value2 = psiconv_list_get(encoded,i+j*3+3))) + goto ERROR2; + value = *value0 + (*value1 << 8) + (*value2 << 16); + psiconv_debug(config,lev+2,off,"Value: %06x",value); + if ((res = psiconv_list_add(*decoded,&value))) + goto ERROR2; + } + i += (0x100 - *marker)*3 + 1; + } + } + psiconv_progress(config,lev,off, + "End of RLE24 decoding process"); + return 0; + +ERROR2: + psiconv_list_free(*decoded); +ERROR1: + psiconv_warn(config,lev+1,off,"Decoding of RLE24 failed"); + if (!res) + return -PSICONV_E_NOMEM; + else + return res; } int psiconv_bytes_to_pixel_data(const psiconv_config config, @@ -835,15 +974,16 @@ psiconv_progress(config,lev+2,off, "Handling pixel %04x (%04x)",i,*pixel); if (!palet.length) { if (color) { - (*floats).blue[i] = (*pixel & ((1 << bluebits) - 1)) / + (*floats).blue[i] = ((float) (*pixel & ((1 << bluebits) - 1))) / (1 << bluebits); - (*floats).green[i] = ((*pixel >> bluebits) & ((1 << greenbits) - 1)) / - (1 << greenbits); - (*floats).red[i] = ((*pixel >> (bluebits+greenbits)) & - ((1 << redbits) - 1)) / (1 << redbits); + (*floats).green[i] = ((float) ((*pixel >> bluebits) & + ((1 << greenbits) - 1))) / (1 << greenbits); + (*floats).red[i] = ((float) ((*pixel >> (bluebits+greenbits)) & + ((1 << redbits) - 1))) / (1 << redbits); } else { (*floats).red[i] = (*floats).green[i] = - (*floats).blue[i] = *pixel / (1 << colordepth); + (*floats).blue[i] = ((float) *pixel) / + (1 << colordepth); } } else { if (*pixel >= palet.length) {