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, 2000 Frodo Looijaard <frodol@dds.nl> |
3 | Copyright (c) 1999-2004 Frodo Looijaard <frodol@dds.nl> |
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); |
… | |
… | |
277 | "All image types except 2-bit greyscale are experimental!"); |
280 | "All image types except 2-bit greyscale are experimental!"); |
278 | |
281 | |
279 | psiconv_progress(config,lev+2,off+len,"Going to read the pixel data"); |
282 | psiconv_progress(config,lev+2,off+len,"Going to read the pixel data"); |
280 | for (i = 0; i < datasize; i++) { |
283 | for (i = 0; i < datasize; i++) { |
281 | byte = psiconv_read_u8(config,buf,lev+2,off+len+i,&res); |
284 | byte = psiconv_read_u8(config,buf,lev+2,off+len+i,&res); |
|
|
285 | #ifdef LOUD |
282 | psiconv_debug(config,lev+2,off+len+i, |
286 | psiconv_debug(config,lev+2,off+len+i, |
283 | "Pixel byte %04x of %04x has value %02x", |
287 | "Pixel byte %04x of %04x has value %02x", |
284 | i,datasize,byte); |
288 | i,datasize,byte); |
|
|
289 | #endif |
285 | if (res) |
290 | if (res) |
286 | goto ERROR3; |
291 | goto ERROR3; |
287 | psiconv_list_add(bytes,&byte); |
292 | psiconv_list_add(bytes,&byte); |
288 | } |
293 | } |
289 | len += datasize; |
294 | len += datasize; |
… | |
… | |
650 | psiconv_progress(config,lev+1,off,"Going to decode the RLE8 encoding"); |
655 | psiconv_progress(config,lev+1,off,"Going to decode the RLE8 encoding"); |
651 | if (!(*decoded = psiconv_list_new(sizeof(psiconv_u8)))) |
656 | if (!(*decoded = psiconv_list_new(sizeof(psiconv_u8)))) |
652 | goto ERROR1; |
657 | goto ERROR1; |
653 | |
658 | |
654 | for (i = 0; i < psiconv_list_length(encoded);) { |
659 | for (i = 0; i < psiconv_list_length(encoded);) { |
|
|
660 | #ifdef LOUD |
655 | psiconv_progress(config,lev+2,off,"Going to read marker byte at %04x",i); |
661 | psiconv_progress(config,lev+2,off,"Going to read marker byte at %04x",i); |
|
|
662 | #endif |
656 | if (!(marker = psiconv_list_get(encoded,i))) |
663 | if (!(marker = psiconv_list_get(encoded,i))) |
657 | goto ERROR2; |
664 | goto ERROR2; |
|
|
665 | #ifdef LOUD |
658 | psiconv_debug(config,lev+2,off,"Marker byte: %02x",*marker); |
666 | psiconv_debug(config,lev+2,off,"Marker byte: %02x",*marker); |
|
|
667 | #endif |
659 | if (*marker < 0x80) { |
668 | if (*marker < 0x80) { |
|
|
669 | #ifdef LOUD |
660 | psiconv_debug(config,lev+2,off,"Marker: repeat value byte %02x times", |
670 | psiconv_debug(config,lev+2,off,"Marker: repeat value byte %02x times", |
661 | *marker+1); |
671 | *marker+1); */ |
662 | psiconv_progress(config,lev+2,off,"Going to read value byte at %04x",i+1); |
672 | psiconv_progress(config,lev+2,off,"Going to read value byte at %04x",i+1); |
|
|
673 | #endif |
663 | if (!(value = psiconv_list_get(encoded,i+1))) |
674 | if (!(value = psiconv_list_get(encoded,i+1))) |
664 | goto ERROR2; |
675 | goto ERROR2; |
|
|
676 | #ifdef LOUD |
665 | psiconv_debug(config,lev+2,off,"Value byte: %02x",*value); |
677 | psiconv_debug(config,lev+2,off,"Value byte: %02x",*value); |
666 | psiconv_progress(config,lev+2,off,"Adding %02x pixels %02x", |
678 | psiconv_progress(config,lev+2,off,"Adding %02x pixels %02x", |
667 | *marker+1,*value); |
679 | *marker+1,*value); |
|
|
680 | #endif |
668 | for (j = 0; j < *marker + 1; j++) |
681 | for (j = 0; j < *marker + 1; j++) |
669 | if ((res = psiconv_list_add(*decoded,value))) |
682 | if ((res = psiconv_list_add(*decoded,value))) |
670 | goto ERROR2; |
683 | goto ERROR2; |
671 | i += 2; |
684 | i += 2; |
672 | } else { |
685 | } else { |
|
|
686 | #ifdef LOUD |
673 | psiconv_debug(config,lev+2,off,"Marker: %02x value bytes follow", |
687 | psiconv_debug(config,lev+2,off,"Marker: %02x value bytes follow", |
674 | 0x100 - *marker); |
688 | 0x100 - *marker); |
|
|
689 | #endif |
675 | for (j = 0; j < (0x100 - *marker); j++) { |
690 | for (j = 0; j < (0x100 - *marker); j++) { |
|
|
691 | #ifdef LOUD |
676 | psiconv_progress(config,lev+2,off,"Going to read value byte at %04x", |
692 | psiconv_progress(config,lev+2,off,"Going to read value byte at %04x", |
677 | i+j+1); |
693 | i+j+1); |
|
|
694 | #endif |
678 | if (!(value = psiconv_list_get(encoded,i+j+1))) |
695 | if (!(value = psiconv_list_get(encoded,i+j+1))) |
679 | goto ERROR2; |
696 | goto ERROR2; |
|
|
697 | #ifdef LOUD |
680 | psiconv_debug(config,lev+2,off,"Value: %02x",*value); |
698 | psiconv_debug(config,lev+2,off,"Value: %02x",*value); |
|
|
699 | #endif |
681 | if ((res = psiconv_list_add(*decoded,value))) |
700 | if ((res = psiconv_list_add(*decoded,value))) |
682 | goto ERROR2; |
701 | goto ERROR2; |
683 | } |
702 | } |
684 | i += (0x100 - *marker) + 1; |
703 | i += (0x100 - *marker) + 1; |
685 | } |
704 | } |
… | |
… | |
899 | while (nr % 4) |
918 | while (nr % 4) |
900 | nr ++; |
919 | nr ++; |
901 | input = 0; |
920 | input = 0; |
902 | ibits = 0; |
921 | ibits = 0; |
903 | for (x= 0; x < xsize; x++) { |
922 | for (x= 0; x < xsize; x++) { |
|
|
923 | #ifdef LOUD |
904 | psiconv_progress(config,lev+2,off, |
924 | psiconv_progress(config,lev+2,off, |
905 | "Processing pixel at (x,y) = (%04x,%04x)",x,y); |
925 | "Processing pixel at (x,y) = (%04x,%04x)",x,y); |
|
|
926 | #endif |
906 | output = 0; |
927 | output = 0; |
907 | obits = 0; |
928 | obits = 0; |
908 | while (obits < colordepth) { |
929 | while (obits < colordepth) { |
909 | if (ibits == 0) { |
930 | if (ibits == 0) { |
|
|
931 | #ifdef LOUD |
910 | psiconv_progress(config,lev+3,off, |
932 | psiconv_progress(config,lev+3,off, |
911 | "Going to read byte %08x",nr); |
933 | "Going to read byte %08x",nr); |
|
|
934 | #endif |
912 | if (!(ientry = psiconv_list_get(bytes,nr))) |
935 | if (!(ientry = psiconv_list_get(bytes,nr))) |
913 | goto ERROR2; |
936 | goto ERROR2; |
|
|
937 | #ifdef LOUD |
914 | psiconv_debug(config,lev+3,off,"Byte value: %02x",*ientry); |
938 | psiconv_debug(config,lev+3,off,"Byte value: %02x",*ientry); |
|
|
939 | #endif |
915 | input = *ientry; |
940 | input = *ientry; |
916 | ibits = 8; |
941 | ibits = 8; |
917 | nr ++; |
942 | nr ++; |
918 | } |
943 | } |
919 | bits = ibits + obits > colordepth?colordepth-obits:ibits; |
944 | bits = ibits + obits > colordepth?colordepth-obits:ibits; |
… | |
… | |
921 | output |= input & ((1 << bits) - 1); |
946 | output |= input & ((1 << bits) - 1); |
922 | input = input >> bits; |
947 | input = input >> bits; |
923 | ibits -= bits; |
948 | ibits -= bits; |
924 | obits += bits; |
949 | obits += bits; |
925 | } |
950 | } |
|
|
951 | #ifdef LOUD |
926 | psiconv_debug(config,lev+2,off,"Pixel value: %08x",output); |
952 | psiconv_debug(config,lev+2,off,"Pixel value: %08x",output); |
|
|
953 | #endif |
927 | if ((res = psiconv_list_add(*pixels,&output))) |
954 | if ((res = psiconv_list_add(*pixels,&output))) |
928 | goto ERROR2; |
955 | goto ERROR2; |
929 | } |
956 | } |
930 | } |
957 | } |
931 | |
958 | |
… | |
… | |
969 | (*floats).length = psiconv_list_length(pixels); |
996 | (*floats).length = psiconv_list_length(pixels); |
970 | |
997 | |
971 | for (i = 0; i < psiconv_list_length(pixels); i++) { |
998 | for (i = 0; i < psiconv_list_length(pixels); i++) { |
972 | if (!(pixel = psiconv_list_get(pixels,i))) |
999 | if (!(pixel = psiconv_list_get(pixels,i))) |
973 | goto ERROR4; |
1000 | goto ERROR4; |
|
|
1001 | #ifdef LOUD |
974 | psiconv_progress(config,lev+2,off, "Handling pixel %04x (%04x)",i,*pixel); |
1002 | psiconv_progress(config,lev+2,off, "Handling pixel %04x (%04x)",i,*pixel); |
|
|
1003 | #endif |
975 | if (!palet.length) { |
1004 | if (!palet.length) { |
976 | if (color) { |
1005 | if (color) { |
977 | (*floats).blue[i] = ((float) (*pixel & ((1 << bluebits) - 1))) / |
1006 | (*floats).blue[i] = ((float) (*pixel & ((1 << bluebits) - 1))) / |
978 | (1 << bluebits); |
1007 | (1 << bluebits); |
979 | (*floats).green[i] = ((float) ((*pixel >> bluebits) & |
1008 | (*floats).green[i] = ((float) ((*pixel >> bluebits) & |
… | |
… | |
996 | (*floats).red[i] = palet.red[*pixel]; |
1025 | (*floats).red[i] = palet.red[*pixel]; |
997 | (*floats).green[i] = palet.green[*pixel]; |
1026 | (*floats).green[i] = palet.green[*pixel]; |
998 | (*floats).blue[i] = palet.blue[*pixel]; |
1027 | (*floats).blue[i] = palet.blue[*pixel]; |
999 | } |
1028 | } |
1000 | } |
1029 | } |
|
|
1030 | #ifdef LOUD |
1001 | psiconv_debug(config,lev+2,off, "Pixel: Red (%f), green (%f), blue (%f)", |
1031 | psiconv_debug(config,lev+2,off, "Pixel: Red (%f), green (%f), blue (%f)", |
1002 | (*floats).red[i],(*floats).green[i],(*floats).blue[i]); |
1032 | (*floats).red[i],(*floats).green[i],(*floats).blue[i]); |
|
|
1033 | #endif |
1003 | } |
1034 | } |
1004 | psiconv_progress(config,lev+1,off,"Finished converting pixels to floats"); |
1035 | psiconv_progress(config,lev+1,off,"Finished converting pixels to floats"); |
1005 | return 0; |
1036 | return 0; |
1006 | |
1037 | |
1007 | ERROR4: |
1038 | ERROR4: |