1 | /* |
1 | /* |
2 | parse_image.c - Part of psiconv, a PSION 5 file formats converter |
2 | parse_image.c - Part of psiconv, a PSION 5 file formats converter |
3 | Copyright (c) 1999-2004 Frodo Looijaard <frodol@dds.nl> |
3 | Copyright (c) 1999-2005 Frodo Looijaard <frodo@frodo.looijaard.name> |
4 | |
4 | |
5 | This program is free software; you can redistribute it and/or modify |
5 | This program is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published by |
6 | it under the terms of the GNU General Public License as published by |
7 | the Free Software Foundation; either version 2 of the License, or |
7 | the Free Software Foundation; either version 2 of the License, or |
8 | (at your option) any later version. |
8 | (at your option) any later version. |
… | |
… | |
27 | #include "image.h" |
27 | #include "image.h" |
28 | |
28 | |
29 | #ifdef DMALLOC |
29 | #ifdef DMALLOC |
30 | #include <dmalloc.h> |
30 | #include <dmalloc.h> |
31 | #endif |
31 | #endif |
|
|
32 | |
|
|
33 | /* Extreme debugging info */ |
|
|
34 | #undef LOUD |
32 | |
35 | |
33 | static int psiconv_decode_rle8 (const psiconv_config config, int lev, |
36 | static int psiconv_decode_rle8 (const psiconv_config config, int lev, |
34 | psiconv_u32 off, |
37 | psiconv_u32 off, |
35 | const psiconv_pixel_bytes encoded, |
38 | const psiconv_pixel_bytes encoded, |
36 | psiconv_pixel_bytes *decoded); |
39 | psiconv_pixel_bytes *decoded); |
… | |
… | |
123 | psiconv_u32 off, int *length,int isclipart, |
126 | psiconv_u32 off, int *length,int isclipart, |
124 | psiconv_paint_data_section *result) |
127 | psiconv_paint_data_section *result) |
125 | { |
128 | { |
126 | int res = 0; |
129 | int res = 0; |
127 | int len = 0; |
130 | int len = 0; |
128 | psiconv_u32 size,offset,picsize,temp,datasize,color, |
131 | psiconv_u32 size,offset,temp,datasize,color, |
129 | redbits,bluebits,greenbits; |
132 | redbits,bluebits,greenbits; |
130 | psiconv_u8 byte; |
133 | psiconv_u8 byte; |
131 | int leng,i; |
134 | int leng,i; |
132 | psiconv_u32 bits_per_pixel,compression; |
135 | psiconv_u32 bits_per_pixel,compression; |
133 | psiconv_pixel_bytes bytes,decoded; |
136 | psiconv_pixel_bytes bytes,decoded; |
… | |
… | |
172 | (*result)->ysize = psiconv_read_u32(config,buf,lev+2,off+len,&res); |
175 | (*result)->ysize = psiconv_read_u32(config,buf,lev+2,off+len,&res); |
173 | if (res) |
176 | if (res) |
174 | goto ERROR3; |
177 | goto ERROR3; |
175 | psiconv_debug(config,lev+2,off+len,"Picture Y size: %08x:",(*result)->ysize); |
178 | psiconv_debug(config,lev+2,off+len,"Picture Y size: %08x:",(*result)->ysize); |
176 | len += 4; |
179 | len += 4; |
177 | |
|
|
178 | picsize = (*result)->ysize * (*result)->xsize; |
|
|
179 | |
180 | |
180 | psiconv_progress(config,lev+2,off+len,"Going to read the real picture x size"); |
181 | psiconv_progress(config,lev+2,off+len,"Going to read the real picture x size"); |
181 | (*result)->pic_xsize = psiconv_read_length(config,buf,lev+2,off+len,&leng,&res); |
182 | (*result)->pic_xsize = psiconv_read_length(config,buf,lev+2,off+len,&leng,&res); |
182 | if (res) |
183 | if (res) |
183 | goto ERROR3; |
184 | goto ERROR3; |
… | |
… | |
277 | "All image types except 2-bit greyscale are experimental!"); |
278 | "All image types except 2-bit greyscale are experimental!"); |
278 | |
279 | |
279 | psiconv_progress(config,lev+2,off+len,"Going to read the pixel data"); |
280 | psiconv_progress(config,lev+2,off+len,"Going to read the pixel data"); |
280 | for (i = 0; i < datasize; i++) { |
281 | for (i = 0; i < datasize; i++) { |
281 | byte = psiconv_read_u8(config,buf,lev+2,off+len+i,&res); |
282 | byte = psiconv_read_u8(config,buf,lev+2,off+len+i,&res); |
|
|
283 | #ifdef LOUD |
282 | psiconv_debug(config,lev+2,off+len+i, |
284 | psiconv_debug(config,lev+2,off+len+i, |
283 | "Pixel byte %04x of %04x has value %02x", |
285 | "Pixel byte %04x of %04x has value %02x", |
284 | i,datasize,byte); |
286 | i,datasize,byte); |
|
|
287 | #endif |
285 | if (res) |
288 | if (res) |
286 | goto ERROR3; |
289 | goto ERROR3; |
287 | psiconv_list_add(bytes,&byte); |
290 | psiconv_list_add(bytes,&byte); |
288 | } |
291 | } |
289 | len += datasize; |
292 | len += datasize; |
… | |
… | |
650 | psiconv_progress(config,lev+1,off,"Going to decode the RLE8 encoding"); |
653 | psiconv_progress(config,lev+1,off,"Going to decode the RLE8 encoding"); |
651 | if (!(*decoded = psiconv_list_new(sizeof(psiconv_u8)))) |
654 | if (!(*decoded = psiconv_list_new(sizeof(psiconv_u8)))) |
652 | goto ERROR1; |
655 | goto ERROR1; |
653 | |
656 | |
654 | for (i = 0; i < psiconv_list_length(encoded);) { |
657 | for (i = 0; i < psiconv_list_length(encoded);) { |
|
|
658 | #ifdef LOUD |
655 | psiconv_progress(config,lev+2,off,"Going to read marker byte at %04x",i); |
659 | psiconv_progress(config,lev+2,off,"Going to read marker byte at %04x",i); |
|
|
660 | #endif |
656 | if (!(marker = psiconv_list_get(encoded,i))) |
661 | if (!(marker = psiconv_list_get(encoded,i))) |
657 | goto ERROR2; |
662 | goto ERROR2; |
|
|
663 | #ifdef LOUD |
658 | psiconv_debug(config,lev+2,off,"Marker byte: %02x",*marker); |
664 | psiconv_debug(config,lev+2,off,"Marker byte: %02x",*marker); |
|
|
665 | #endif |
659 | if (*marker < 0x80) { |
666 | if (*marker < 0x80) { |
|
|
667 | #ifdef LOUD |
660 | psiconv_debug(config,lev+2,off,"Marker: repeat value byte %02x times", |
668 | psiconv_debug(config,lev+2,off,"Marker: repeat value byte %02x times", |
661 | *marker+1); |
669 | *marker+1); */ |
662 | psiconv_progress(config,lev+2,off,"Going to read value byte at %04x",i+1); |
670 | psiconv_progress(config,lev+2,off,"Going to read value byte at %04x",i+1); |
|
|
671 | #endif |
663 | if (!(value = psiconv_list_get(encoded,i+1))) |
672 | if (!(value = psiconv_list_get(encoded,i+1))) |
664 | goto ERROR2; |
673 | goto ERROR2; |
|
|
674 | #ifdef LOUD |
665 | psiconv_debug(config,lev+2,off,"Value byte: %02x",*value); |
675 | psiconv_debug(config,lev+2,off,"Value byte: %02x",*value); |
666 | psiconv_progress(config,lev+2,off,"Adding %02x pixels %02x", |
676 | psiconv_progress(config,lev+2,off,"Adding %02x pixels %02x", |
667 | *marker+1,*value); |
677 | *marker+1,*value); |
|
|
678 | #endif |
668 | for (j = 0; j < *marker + 1; j++) |
679 | for (j = 0; j < *marker + 1; j++) |
669 | if ((res = psiconv_list_add(*decoded,value))) |
680 | if ((res = psiconv_list_add(*decoded,value))) |
670 | goto ERROR2; |
681 | goto ERROR2; |
671 | i += 2; |
682 | i += 2; |
672 | } else { |
683 | } else { |
|
|
684 | #ifdef LOUD |
673 | psiconv_debug(config,lev+2,off,"Marker: %02x value bytes follow", |
685 | psiconv_debug(config,lev+2,off,"Marker: %02x value bytes follow", |
674 | 0x100 - *marker); |
686 | 0x100 - *marker); |
|
|
687 | #endif |
675 | for (j = 0; j < (0x100 - *marker); j++) { |
688 | for (j = 0; j < (0x100 - *marker); j++) { |
|
|
689 | #ifdef LOUD |
676 | psiconv_progress(config,lev+2,off,"Going to read value byte at %04x", |
690 | psiconv_progress(config,lev+2,off,"Going to read value byte at %04x", |
677 | i+j+1); |
691 | i+j+1); |
|
|
692 | #endif |
678 | if (!(value = psiconv_list_get(encoded,i+j+1))) |
693 | if (!(value = psiconv_list_get(encoded,i+j+1))) |
679 | goto ERROR2; |
694 | goto ERROR2; |
|
|
695 | #ifdef LOUD |
680 | psiconv_debug(config,lev+2,off,"Value: %02x",*value); |
696 | psiconv_debug(config,lev+2,off,"Value: %02x",*value); |
|
|
697 | #endif |
681 | if ((res = psiconv_list_add(*decoded,value))) |
698 | if ((res = psiconv_list_add(*decoded,value))) |
682 | goto ERROR2; |
699 | goto ERROR2; |
683 | } |
700 | } |
684 | i += (0x100 - *marker) + 1; |
701 | i += (0x100 - *marker) + 1; |
685 | } |
702 | } |
… | |
… | |
899 | while (nr % 4) |
916 | while (nr % 4) |
900 | nr ++; |
917 | nr ++; |
901 | input = 0; |
918 | input = 0; |
902 | ibits = 0; |
919 | ibits = 0; |
903 | for (x= 0; x < xsize; x++) { |
920 | for (x= 0; x < xsize; x++) { |
|
|
921 | #ifdef LOUD |
904 | psiconv_progress(config,lev+2,off, |
922 | psiconv_progress(config,lev+2,off, |
905 | "Processing pixel at (x,y) = (%04x,%04x)",x,y); |
923 | "Processing pixel at (x,y) = (%04x,%04x)",x,y); |
|
|
924 | #endif |
906 | output = 0; |
925 | output = 0; |
907 | obits = 0; |
926 | obits = 0; |
908 | while (obits < colordepth) { |
927 | while (obits < colordepth) { |
909 | if (ibits == 0) { |
928 | if (ibits == 0) { |
|
|
929 | #ifdef LOUD |
910 | psiconv_progress(config,lev+3,off, |
930 | psiconv_progress(config,lev+3,off, |
911 | "Going to read byte %08x",nr); |
931 | "Going to read byte %08x",nr); |
|
|
932 | #endif |
912 | if (!(ientry = psiconv_list_get(bytes,nr))) |
933 | if (!(ientry = psiconv_list_get(bytes,nr))) |
913 | goto ERROR2; |
934 | goto ERROR2; |
|
|
935 | #ifdef LOUD |
914 | psiconv_debug(config,lev+3,off,"Byte value: %02x",*ientry); |
936 | psiconv_debug(config,lev+3,off,"Byte value: %02x",*ientry); |
|
|
937 | #endif |
915 | input = *ientry; |
938 | input = *ientry; |
916 | ibits = 8; |
939 | ibits = 8; |
917 | nr ++; |
940 | nr ++; |
918 | } |
941 | } |
919 | bits = ibits + obits > colordepth?colordepth-obits:ibits; |
942 | bits = ibits + obits > colordepth?colordepth-obits:ibits; |
… | |
… | |
921 | output |= input & ((1 << bits) - 1); |
944 | output |= input & ((1 << bits) - 1); |
922 | input = input >> bits; |
945 | input = input >> bits; |
923 | ibits -= bits; |
946 | ibits -= bits; |
924 | obits += bits; |
947 | obits += bits; |
925 | } |
948 | } |
|
|
949 | #ifdef LOUD |
926 | psiconv_debug(config,lev+2,off,"Pixel value: %08x",output); |
950 | psiconv_debug(config,lev+2,off,"Pixel value: %08x",output); |
|
|
951 | #endif |
927 | if ((res = psiconv_list_add(*pixels,&output))) |
952 | if ((res = psiconv_list_add(*pixels,&output))) |
928 | goto ERROR2; |
953 | goto ERROR2; |
929 | } |
954 | } |
930 | } |
955 | } |
931 | |
956 | |
… | |
… | |
969 | (*floats).length = psiconv_list_length(pixels); |
994 | (*floats).length = psiconv_list_length(pixels); |
970 | |
995 | |
971 | for (i = 0; i < psiconv_list_length(pixels); i++) { |
996 | for (i = 0; i < psiconv_list_length(pixels); i++) { |
972 | if (!(pixel = psiconv_list_get(pixels,i))) |
997 | if (!(pixel = psiconv_list_get(pixels,i))) |
973 | goto ERROR4; |
998 | goto ERROR4; |
|
|
999 | #ifdef LOUD |
974 | psiconv_progress(config,lev+2,off, "Handling pixel %04x (%04x)",i,*pixel); |
1000 | psiconv_progress(config,lev+2,off, "Handling pixel %04x (%04x)",i,*pixel); |
|
|
1001 | #endif |
975 | if (!palet.length) { |
1002 | if (!palet.length) { |
976 | if (color) { |
1003 | if (color) { |
977 | (*floats).blue[i] = ((float) (*pixel & ((1 << bluebits) - 1))) / |
1004 | (*floats).blue[i] = ((float) (*pixel & ((1 << bluebits) - 1))) / |
978 | (1 << bluebits); |
1005 | ((1 << bluebits) - 1); |
979 | (*floats).green[i] = ((float) ((*pixel >> bluebits) & |
1006 | (*floats).green[i] = ((float) ((*pixel >> bluebits) & |
980 | ((1 << greenbits) - 1))) / (1 << greenbits); |
1007 | ((1 << greenbits) - 1))) / ((1 << greenbits) - 1); |
981 | (*floats).red[i] = ((float) ((*pixel >> (bluebits+greenbits)) & |
1008 | (*floats).red[i] = ((float) ((*pixel >> (bluebits+greenbits)) & |
982 | ((1 << redbits) - 1))) / (1 << redbits); |
1009 | ((1 << redbits) - 1))) / ((1 << redbits) - 1); |
983 | } else { |
1010 | } else { |
984 | (*floats).red[i] = (*floats).green[i] = |
1011 | (*floats).red[i] = (*floats).green[i] = |
985 | (*floats).blue[i] = ((float) *pixel) / |
1012 | (*floats).blue[i] = ((float) *pixel) / |
986 | (1 << colordepth); |
1013 | ((1 << colordepth) - 1); |
987 | } |
1014 | } |
988 | } else { |
1015 | } else { |
989 | if (*pixel >= palet.length) { |
1016 | if (*pixel >= palet.length) { |
990 | psiconv_warn(config,lev+2,off, |
1017 | psiconv_warn(config,lev+2,off, |
991 | "Invalid palet color found (using color 0x00)"); |
1018 | "Invalid palet color found (using color 0x00)"); |
… | |
… | |
996 | (*floats).red[i] = palet.red[*pixel]; |
1023 | (*floats).red[i] = palet.red[*pixel]; |
997 | (*floats).green[i] = palet.green[*pixel]; |
1024 | (*floats).green[i] = palet.green[*pixel]; |
998 | (*floats).blue[i] = palet.blue[*pixel]; |
1025 | (*floats).blue[i] = palet.blue[*pixel]; |
999 | } |
1026 | } |
1000 | } |
1027 | } |
|
|
1028 | #ifdef LOUD |
1001 | psiconv_debug(config,lev+2,off, "Pixel: Red (%f), green (%f), blue (%f)", |
1029 | psiconv_debug(config,lev+2,off, "Pixel: Red (%f), green (%f), blue (%f)", |
1002 | (*floats).red[i],(*floats).green[i],(*floats).blue[i]); |
1030 | (*floats).red[i],(*floats).green[i],(*floats).blue[i]); |
|
|
1031 | #endif |
1003 | } |
1032 | } |
1004 | psiconv_progress(config,lev+1,off,"Finished converting pixels to floats"); |
1033 | psiconv_progress(config,lev+1,off,"Finished converting pixels to floats"); |
1005 | return 0; |
1034 | return 0; |
1006 | |
1035 | |
1007 | ERROR4: |
1036 | ERROR4: |