comparison libgfx.c @ 444:7d588807f91d

Clean up the IFF parser a bit.
author Matti Hamalainen <ccr@tnsp.org>
date Sun, 04 Nov 2012 06:52:42 +0200
parents f7c9d1619c74
children 1d65efb29986
comparison
equal deleted inserted replaced
443:f7c9d1619c74 444:7d588807f91d
955 Uint8 xasp, yasp; 955 Uint8 xasp, yasp;
956 Sint16 pagew, pageh; 956 Sint16 pagew, pageh;
957 } DMIFFBMHD; 957 } DMIFFBMHD;
958 958
959 959
960 typedef struct
961 {
962 DMIFFChunk chBMHD, chCMAP, chBODY;
963 DMIFFBMHD bmhd;
964 int ncolors;
965 DMColor *pal;
966 DMImage *img;
967 BOOL paletted;
968 } DMIFF;
969
970
960 static BOOL dmReadIFFChunk(FILE *fp, DMIFFChunk *chunk) 971 static BOOL dmReadIFFChunk(FILE *fp, DMIFFChunk *chunk)
961 { 972 {
962 if (!dm_fread_be32(fp, &chunk->id) || 973 if (!dm_fread_be32(fp, &chunk->id) ||
963 !dm_fread_be32(fp, &chunk->size)) 974 !dm_fread_be32(fp, &chunk->size))
964 { 975 {
967 } 978 }
968 else 979 else
969 return TRUE; 980 return TRUE;
970 } 981 }
971 982
972 static char * dmGetIFFChunkID(DMIFFChunk *chunk, char *buf) 983 static char * dmGetIFFChunkID(const DMIFFChunk *chunk, char *buf)
973 { 984 {
974 buf[0] = (chunk->id >> 24) & 0xff; 985 buf[0] = (chunk->id >> 24) & 0xff;
975 buf[1] = (chunk->id >> 16) & 0xff; 986 buf[1] = (chunk->id >> 16) & 0xff;
976 buf[2] = (chunk->id >> 8) & 0xff; 987 buf[2] = (chunk->id >> 8) & 0xff;
977 buf[3] = (chunk->id) & 0xff; 988 buf[3] = (chunk->id) & 0xff;
978 buf[4] = 0; 989 buf[4] = 0;
979 return buf; 990 return buf;
980 } 991 }
981 992
982 static BOOL dmCheckIFFChunk(DMIFFChunk *dest, DMIFFChunk *chunk, BOOL multi, Uint32 minSize) 993 static BOOL dmSkipIFFChunkRest(FILE *fp, const DMIFFChunk *chunk, const Uint32 used)
994 {
995 if (chunk->size > used)
996 return fseeko(fp, chunk->size - used, SEEK_CUR) == 0;
997 else
998 return TRUE;
999 }
1000
1001 static BOOL dmCheckIFFChunk(DMIFFChunk *dest, const DMIFFChunk *chunk, const BOOL multi, const Uint32 minSize)
983 { 1002 {
984 if (dest->count > 0 && !multi) 1003 if (dest->count > 0 && !multi)
985 { 1004 {
986 char buf[6]; 1005 char buf[6];
987 dmError("ILBM: Multiple instances of chunk %s found.\n", 1006 dmError("ILBM: Multiple instances of chunk %s found.\n",
996 1015
997 return TRUE; 1016 return TRUE;
998 } 1017 }
999 1018
1000 1019
1020 int dmDecodeILBMBody(FILE *fp, DMIFF *iff)
1021 {
1022 return DMERR_OK;
1023 }
1024
1025
1001 int dmReadILBMImageFILE(FILE *fp, DMImage **pimg) 1026 int dmReadILBMImageFILE(FILE *fp, DMImage **pimg)
1002 { 1027 {
1003 Uint32 idILBM; 1028 Uint32 idILBM;
1004 DMIFFChunk chunk, chBMHD, chCMAP, chBODY; 1029 DMIFFChunk chunk;
1005 DMIFFBMHD bmhd; 1030 DMIFF iff;
1006 int ncolors, i; 1031 BOOL parsed = FALSE;
1007 DMColor *pal = NULL; 1032 int i, res = DMERR_OK;
1008 DMImage *img = NULL; 1033
1009 BOOL paletted = FALSE, parsed = FALSE; 1034 memset(&iff, 0, sizeof(iff));
1010 int res = DMERR_OK;
1011
1012 memset(&chBMHD, 0, sizeof(DMIFFChunk));
1013 memset(&chCMAP, 0, sizeof(DMIFFChunk));
1014 memset(&chBODY, 0, sizeof(DMIFFChunk));
1015 memset(&bmhd, 0, sizeof(bmhd));
1016 1035
1017 // Read IFF FORM header 1036 // Read IFF FORM header
1018 if (!dmReadIFFChunk(fp, &chunk) || 1037 if (!dmReadIFFChunk(fp, &chunk) ||
1019 chunk.id != IFF_ID_FORM || 1038 chunk.id != IFF_ID_FORM ||
1020 chunk.size < 32) 1039 chunk.size < 32)
1040 } 1059 }
1041 1060
1042 switch (chunk.id) 1061 switch (chunk.id)
1043 { 1062 {
1044 case IFF_ID_BMHD: 1063 case IFF_ID_BMHD:
1045 if (!dmCheckIFFChunk(&chBMHD, &chunk, FALSE, sizeof(bmhd))) 1064 if (!dmCheckIFFChunk(&iff.chBMHD, &chunk, FALSE, sizeof(iff.bmhd)))
1046 return DMERR_FREAD; 1065 return DMERR_FREAD;
1047 1066
1048 if (!dm_fread_be16(fp, &bmhd.w) || 1067 if (!dm_fread_be16(fp, &iff.bmhd.w) ||
1049 !dm_fread_be16(fp, &bmhd.h) || 1068 !dm_fread_be16(fp, &iff.bmhd.h) ||
1050 !dm_fread_be16(fp, (Uint16 *) &bmhd.x) || 1069 !dm_fread_be16(fp, (Uint16 *) &iff.bmhd.x) ||
1051 !dm_fread_be16(fp, (Uint16 *) &bmhd.y) || 1070 !dm_fread_be16(fp, (Uint16 *) &iff.bmhd.y) ||
1052 !dm_fread_byte(fp, &bmhd.nplanes) || 1071 !dm_fread_byte(fp, &iff.bmhd.nplanes) ||
1053 !dm_fread_byte(fp, &bmhd.masking) || 1072 !dm_fread_byte(fp, &iff.bmhd.masking) ||
1054 !dm_fread_byte(fp, &bmhd.compression) || 1073 !dm_fread_byte(fp, &iff.bmhd.compression) ||
1055 !dm_fread_byte(fp, &bmhd.pad1) || 1074 !dm_fread_byte(fp, &iff.bmhd.pad1) ||
1056 !dm_fread_be16(fp, &bmhd.transp) || 1075 !dm_fread_be16(fp, &iff.bmhd.transp) ||
1057 !dm_fread_byte(fp, &bmhd.xasp) || 1076 !dm_fread_byte(fp, &iff.bmhd.xasp) ||
1058 !dm_fread_byte(fp, &bmhd.yasp) || 1077 !dm_fread_byte(fp, &iff.bmhd.yasp) ||
1059 !dm_fread_be16(fp, (Uint16 *) &bmhd.pagew) || 1078 !dm_fread_be16(fp, (Uint16 *) &iff.bmhd.pagew) ||
1060 !dm_fread_be16(fp, (Uint16 *) &bmhd.pageh)) 1079 !dm_fread_be16(fp, (Uint16 *) &iff.bmhd.pageh))
1061 { 1080 {
1062 dmError("ILBM: Error reading BMHD chunk.\n"); 1081 dmError("ILBM: Error reading BMHD chunk.\n");
1063 return DMERR_FREAD; 1082 return DMERR_FREAD;
1064 } 1083 }
1065 dmMsg(2, "ILBM: BMHD %d x %d @ %d, %d : nplanes=%d, comp=%d, mask=%d\n", 1084 dmMsg(2, "ILBM: BMHD %d x %d @ %d, %d : nplanes=%d, comp=%d, mask=%d\n",
1066 bmhd.w, bmhd.h, bmhd.x, bmhd.y, bmhd.nplanes, bmhd.compression, bmhd.masking); 1085 iff.bmhd.w, iff.bmhd.h, iff.bmhd.x, iff.bmhd.y, iff.bmhd.nplanes, iff.bmhd.compression, iff.bmhd.masking);
1086
1087 if (!dmSkipIFFChunkRest(fp, &chunk, sizeof(iff.bmhd)))
1088 return DMERR_FREAD;
1067 break; 1089 break;
1068 1090
1069 1091
1070 case IFF_ID_CMAP: 1092 case IFF_ID_CMAP:
1071 // Check for multiple occurences of CMAP 1093 // Check for multiple occurences of CMAP
1072 if (!dmCheckIFFChunk(&chCMAP, &chunk, FALSE, 3)) 1094 if (!dmCheckIFFChunk(&iff.chCMAP, &chunk, FALSE, 3))
1073 return DMERR_FREAD; 1095 return DMERR_FREAD;
1074 1096
1075 // Check for sanity 1097 // Check for sanity
1076 if (chunk.size % 3 != 0) 1098 if (chunk.size % 3 != 0)
1077 dmError("ILBM: CMAP chunk size not divisible by 3, possibly broken file.\n"); 1099 dmError("ILBM: CMAP chunk size not divisible by 3, possibly broken file.\n");
1078 1100
1079 ncolors = chunk.size / 3; 1101 iff.ncolors = chunk.size / 3;
1080 dmMsg(2, "ILBM: CMAP %d entries (%d bytes)\n", 1102 dmMsg(2, "ILBM: CMAP %d entries (%d bytes)\n",
1081 ncolors, chunk.size, 1 << bmhd.nplanes); 1103 iff.ncolors, chunk.size, 1 << iff.bmhd.nplanes);
1082 1104
1083 if (bmhd.nplanes > 0 && ncolors != 1 << bmhd.nplanes) 1105 if (iff.bmhd.nplanes > 0 && iff.ncolors != 1 << iff.bmhd.nplanes)
1084 dmMsg(2, "ILBM: Expected %d entries in CMAP.\n", 1 << bmhd.nplanes); 1106 dmMsg(2, "ILBM: Expected %d entries in CMAP.\n", 1 << iff.bmhd.nplanes);
1085 1107
1086 if (ncolors == 0) 1108 if (iff.ncolors == 0)
1087 break; 1109 break;
1088 1110
1089 // Allocate palette 1111 // Allocate palette
1090 if ((pal = dmMalloc(sizeof(DMColor) * ncolors)) == NULL) 1112 if ((iff.pal = dmMalloc(sizeof(DMColor) * iff.ncolors)) == NULL)
1091 { 1113 {
1092 dmError("ILBM: Could not allocate memory for palette.\n"); 1114 dmError("ILBM: Could not allocate memory for palette.\n");
1093 return DMERR_MALLOC; 1115 return DMERR_MALLOC;
1094 } 1116 }
1095 1117
1096 // Read palette 1118 // Read palette
1097 for (i = 0; i < ncolors; i++) 1119 for (i = 0; i < iff.ncolors; i++)
1098 { 1120 {
1099 Uint8 colR, colG, colB; 1121 Uint8 colR, colG, colB;
1100 if (!dm_fread_byte(fp, &colR) || 1122 if (!dm_fread_byte(fp, &colR) ||
1101 !dm_fread_byte(fp, &colG) || 1123 !dm_fread_byte(fp, &colG) ||
1102 !dm_fread_byte(fp, &colB)) 1124 !dm_fread_byte(fp, &colB))
1103 { 1125 {
1104 dmError("ILBM: Error reading CMAP entry #%d, broken file.\n", i); 1126 dmError("ILBM: Error reading CMAP entry #%d, broken file.\n", i);
1105 return DMERR_FREAD; 1127 return DMERR_FREAD;
1106 } 1128 }
1107 1129
1108 pal[i].r = colR; 1130 iff.pal[i].r = colR;
1109 pal[i].g = colG; 1131 iff.pal[i].g = colG;
1110 pal[i].b = colB; 1132 iff.pal[i].b = colB;
1111 } 1133 }
1112 1134
1113 if (chBMHD.count && chBODY.count) 1135 if (iff.chBMHD.count && iff.chBODY.count)
1114 parsed = TRUE; 1136 parsed = TRUE;
1115 break; 1137 break;
1116 1138
1117 case IFF_ID_BODY: 1139 case IFF_ID_BODY:
1118 if (!dmCheckIFFChunk(&chBODY, &chunk, FALSE, 1)) 1140 if (!dmCheckIFFChunk(&iff.chBODY, &chunk, FALSE, 1))
1119 return DMERR_FREAD; 1141 return DMERR_FREAD;
1120 1142
1121 if (!chBMHD.count) 1143 if (!iff.chBMHD.count)
1122 { 1144 {
1123 dmError("ILBM: BODY chunk before BMHD?\n"); 1145 dmError("ILBM: BODY chunk before BMHD?\n");
1124 return DMERR_INVALID_DATA; 1146 return DMERR_INVALID_DATA;
1125 } 1147 }
1126 1148
1127 dmMsg(2, "ILBM: BODY chunk size %d bytes\n", chunk.size); 1149 dmMsg(2, "ILBM: BODY chunk size %d bytes\n", chunk.size);
1150
1128 if (fseeko(fp, chunk.size, SEEK_CUR) != 0) 1151 if (fseeko(fp, chunk.size, SEEK_CUR) != 0)
1129 { 1152 {
1130 dmError("ILBM: Error skipping in file."); 1153 dmError("ILBM: Error skipping in file.");
1131 return DMERR_FREAD; 1154 return DMERR_FREAD;
1132 } 1155 }
1133 1156
1134 if (chCMAP.count) 1157 if (iff.chCMAP.count)
1135 parsed = TRUE; 1158 parsed = TRUE;
1136 break; 1159 break;
1137 1160
1138 default: 1161 default:
1139 { 1162 {