comparison tools/gfxconv.c @ 828:c20a99411a1a

Fix a silly segfault.
author Matti Hamalainen <ccr@tnsp.org>
date Sat, 17 May 2014 01:56:04 +0300
parents c8beac5313c3
children 97700378ecd8
comparison
equal deleted inserted replaced
827:c8beac5313c3 828:c20a99411a1a
138 static DMOptArg optList[] = 138 static DMOptArg optList[] =
139 { 139 {
140 { 0, '?', "help", "Show this help", OPT_NONE }, 140 { 0, '?', "help", "Show this help", OPT_NONE },
141 { 15, 'v', "verbose", "Increase verbosity", OPT_NONE }, 141 { 15, 'v', "verbose", "Increase verbosity", OPT_NONE },
142 { 3, 'o', "output", "Output filename", OPT_ARGREQ }, 142 { 3, 'o', "output", "Output filename", OPT_ARGREQ },
143 { 1, 'i', "informat", "Set input format ([s]prite, [c]har, [b]itmap, [i]mage)", OPT_ARGREQ }, 143 { 1, 'i', "informat", "Set input format (sprite[:mc:sc], char[:mc|sc], bitmap[:<bformat>], image)", OPT_ARGREQ },
144 { 2, 'm', "multicolor", "Input is multicolor / output in multicolor", OPT_NONE }, 144 { 2, 'm', "multicolor", "Input is multicolor / output in multicolor", OPT_NONE },
145 { 4, 's', "skip", "Skip bytes in input", OPT_ARGREQ }, 145 { 4, 's', "skip", "Skip bytes in input", OPT_ARGREQ },
146 { 5, 'f', "format", "Output format (see --formats)", OPT_ARGREQ }, 146 { 5, 'f', "format", "Output format (see --formats)", OPT_ARGREQ },
147 { 17, 0 , "formats", "List available input/output formats", OPT_NONE }, 147 { 17, 0 , "formats", "List available input/output formats", OPT_NONE },
148 { 8, 'q', "sequential", "Output sequential files (image output only)", OPT_NONE }, 148 { 8, 'q', "sequential", "Output sequential files (image output only)", OPT_NONE },
149 { 6, 'c', "colormap", "Color mappings (see below for information)", OPT_ARGREQ }, 149 { 6, 'c', "colormap", "Color mappings (see below for information)", OPT_ARGREQ },
150 { 7, 'n', "numitems", "How many 'items' to view (default: all)", OPT_ARGREQ }, 150 { 7, 'n', "numitems", "How many 'items' to view (default: all)", OPT_ARGREQ },
151 { 9, 'S', "scale", "Scale output by x (image output only)", OPT_ARGREQ }, 151 { 9, 'S', "scale", "Scale output by x (image output only)", OPT_ARGREQ },
152 { 10, 'b', "bformat", "Force input bitmap format (see below)", OPT_ARGREQ },
153 { 11, 'w', "width", "Item width (number of items per row, min 1)", OPT_ARGREQ }, 152 { 11, 'w', "width", "Item width (number of items per row, min 1)", OPT_ARGREQ },
154 { 12, 'P', "paletted", "Use indexed/paletted output (png, pcx output only)", OPT_NONE }, 153 { 12, 'P', "paletted", "Use indexed/paletted output (png, pcx output only)", OPT_NONE },
155 { 13, 'B', "bplanes", "Bits per pixel OR # of bitplanes (certain output formats)", OPT_ARGREQ }, 154 { 13, 'B', "bplanes", "Bits per pixel OR # of bitplanes (certain output formats)", OPT_ARGREQ },
156 { 14, 'I', "interleave", "Interleave scanlines (default: output whole planes)", OPT_NONE }, 155 { 14, 'I', "interleave", "Interleave scanlines (default: output whole planes)", OPT_NONE },
157 { 16, 'R', "remap", "Remap output image colors (-R <(#RRGGBB|index):index>[,<..>][+remove] | -R @map.txt[+remove])", OPT_ARGREQ }, 156 { 16, 'R', "remap", "Remap output image colors (-R <(#RRGGBB|index):index>[,<..>][+remove] | -R @map.txt[+remove])", OPT_ARGREQ },
157 { 19, 'C', "crop", "Crop intermediate -C auto|<x0>:<y0>-<x1>:<y1>|<x0>:<y0>:<w>:<h>", OPT_ARGREQ },
158 }; 158 };
159 159
160 static const int optListN = sizeof(optList) / sizeof(optList[0]); 160 static const int optListN = sizeof(optList) / sizeof(optList[0]);
161 161
162 162
182 182
183 printf( 183 printf(
184 "\n" 184 "\n"
185 "(Not all input->output combinations are actually supported.)\n" 185 "(Not all input->output combinations are actually supported.)\n"
186 "\n" 186 "\n"
187 "Available bitmap formats:\n" 187 "Available bitmap formats (-f bitmap:<bformat>):\n"
188 " Ext | Type | Description\n" 188 " Ext | Type | Description\n"
189 "------+-----------------+-------------------------------------\n" 189 "------+-----------------+-------------------------------------\n"
190 ); 190 );
191 191
192 for (i = 0; i < ndmC64ImageFormats; i++) 192 for (i = 0; i < ndmC64ImageFormats; i++)
514 case 'i': optInFormat = FFMT_IMAGE; break; 514 case 'i': optInFormat = FFMT_IMAGE; break;
515 default: 515 default:
516 dmError("Invalid input format '%s'.\n", optArg); 516 dmError("Invalid input format '%s'.\n", optArg);
517 return FALSE; 517 return FALSE;
518 } 518 }
519
520 char *tmp = strchr(optArg, ':');
521 if (tmp != NULL)
522 {
523 tmp++;
524 switch (optInFormat)
525 {
526 case FFMT_SPRITE:
527 case FFMT_CHAR:
528 if (strcasecmp(tmp, "mc") == 0)
529 optInMulticolor = TRUE;
530 else
531 if (strcasecmp(tmp, "sc") == 0)
532 optInMulticolor = FALSE;
533 else
534 {
535 dmError("Invalid input subformat for sprite/char: '%s', should be 'mc' or 'sc'.\n",
536 tmp);
537 return FALSE;
538 }
539 break;
540
541 case FFMT_BITMAP:
542 if (!dmGetC64FormatByExt(tmp, &optInFormat, &optInSubFormat))
543 {
544 dmError("Invalid bitmap subformat '%s', see format list for valid bformats.\n",
545 tmp);
546 return FALSE;
547 }
548 break;
549 }
550 }
519 } 551 }
520 break; 552 break;
521 553
522 case 2: 554 case 2:
523 optInMulticolor = TRUE; 555 optInMulticolor = TRUE;
650 return FALSE; 682 return FALSE;
651 } 683 }
652 } 684 }
653 685
654 optRemapColors = TRUE; 686 optRemapColors = TRUE;
687 break;
688
689 case 19:
690 {
691 if (strcasecmp(optArg, "auto") == 0)
692 {
693 }
694 else
695 if (sscanf(optArg, "%d:%d-%d:%d", ) == 4)
696 {
697 }
698 else
699 if (sscanf(optArg, "%d:%d
700 }
655 break; 701 break;
656 702
657 default: 703 default:
658 dmError("Unknown option '%s'.\n", currArg); 704 dmError("Unknown option '%s'.\n", currArg);
659 return FALSE; 705 return FALSE;
1154 } 1200 }
1155 1201
1156 1202
1157 int dmWriteSpritesAndChars(const char *filename, DMImage *image, int outFormat, BOOL multicolor) 1203 int dmWriteSpritesAndChars(const char *filename, DMImage *image, int outFormat, BOOL multicolor)
1158 { 1204 {
1159 int outBlockW, outBlockH, bx, by; 1205 int ret = DMERR_OK;
1206 int outBlockW, outBlockH, bx, by, index;
1160 FILE *outFile = NULL; 1207 FILE *outFile = NULL;
1161 Uint8 *buf = NULL; 1208 Uint8 **outBuf = NULL;
1162 size_t bufSize; 1209 int *outScreen = NULL;
1163 char *outType; 1210 size_t outBufSize;
1211 char *outType, *tmpFilename;
1164 1212
1165 switch (outFormat) 1213 switch (outFormat)
1166 { 1214 {
1167 case FFMT_CHAR: 1215 case FFMT_CHAR:
1168 bufSize = C64_CHR_SIZE; 1216 outBufSize = C64_CHR_SIZE;
1169 outBlockW = image->width / C64_CHR_WIDTH_PX; 1217 outBlockW = image->width / C64_CHR_WIDTH_PX;
1170 outBlockH = image->height / C64_CHR_HEIGHT; 1218 outBlockH = image->height / C64_CHR_HEIGHT;
1171 outType = "char"; 1219 outType = "char";
1172 break; 1220 break;
1173 1221
1174 case FFMT_SPRITE: 1222 case FFMT_SPRITE:
1175 bufSize = C64_SPR_SIZE; 1223 outBufSize = C64_SPR_SIZE;
1176 outBlockW = image->width / C64_SPR_WIDTH_PX; 1224 outBlockW = image->width / C64_SPR_WIDTH_PX;
1177 outBlockH = image->height / C64_SPR_HEIGHT; 1225 outBlockH = image->height / C64_SPR_HEIGHT;
1178 outType = "sprite"; 1226 outType = "sprite";
1179 break; 1227 break;
1180 1228
1181 default: 1229 default:
1182 dmError("Invalid output format %d, internal error.\n", outFormat); 1230 dmError("Invalid output format %d, internal error.\n", outFormat);
1183 goto error; 1231 goto error;
1184 } 1232 }
1185 1233
1186 if (outBlockW <= 0 || outBlockH <= 0) 1234 if (outBlockW < 1 || outBlockH < 1)
1187 { 1235 {
1236 ret = DMERR_INVALID_ARGS;
1188 dmError("Source image dimensions too small for conversion, block dimensions %d x %d.\n", 1237 dmError("Source image dimensions too small for conversion, block dimensions %d x %d.\n",
1189 outBlockW, outBlockH); 1238 outBlockW, outBlockH);
1190 goto error; 1239 goto error;
1191 } 1240 }
1192 1241
1193 if ((outFile = fopen(filename, "wb")) == NULL) 1242 dmMsg(1, "Converting %d x %d = %d blocks of %s data...\n",
1194 { 1243 outBlockW, outBlockH, outBlockW * outBlockH, outType);
1195 int err = dmGetErrno(); 1244
1196 dmError("Could not open '%s' for writing, %d: %s.\n", 1245
1197 filename, err, dmErrorStr(err)); 1246 // Allocate screen buffer
1247 if ((outScreen = dmMalloc(outBlockW * outBlockH * sizeof(int))) == NULL)
1248 {
1249 ret = DMERR_MALLOC;
1250 dmError("Could not allocate %d bytes for screen conversion buffer.\n",
1251 outBlockW * outBlockH * sizeof(int));
1198 goto error; 1252 goto error;
1199 } 1253 }
1200 1254
1201 if ((buf = dmMalloc(bufSize)) == NULL) 1255 // Allocate char buffers
1202 { 1256 if ((outBuf = dmMalloc0(outBlockW * outBlockH * sizeof(Uint8 *))) == NULL)
1203 dmError("Could not allocate %d bytes for conversion buffer.\n", 1257 {
1204 bufSize); 1258 ret = DMERR_MALLOC;
1259 dmError("Could not allocate character data index.\n");
1205 goto error; 1260 goto error;
1206 } 1261 }
1207 1262
1208 dmMsg(1, "Writing %d x %d = %d blocks of %s data...\n", 1263 for (index = 0; index < outBlockW * outBlockH; index++)
1209 outBlockW, outBlockH, outBlockW * outBlockH, outType); 1264 {
1210 1265 if ((outBuf[index] = dmMalloc(outBufSize)) == NULL)
1266 {
1267 ret = DMERR_MALLOC;
1268 dmError("Could not allocate %d bytes for character data buffer.\n",
1269 outBufSize);
1270 goto error;
1271 }
1272 }
1273
1274 if ((tmpBuf = dmMalloc(outBufSize)) == NULL)
1275 {
1276 err = DMERR_MALLOC;
1277 dmError("Could not allocate %d bytes for character data buffer.\n",
1278 outBufSize);
1279 goto error;
1280 }
1281
1282 // Chop input image into char blocks
1283 index = 0;
1211 for (by = 0; by < outBlockH; by++) 1284 for (by = 0; by < outBlockH; by++)
1212 for (bx = 0; bx < outBlockW; bx++) 1285 for (bx = 0; bx < outBlockW; bx++)
1213 { 1286 {
1287 outScreen[index] = index;
1214 switch (outFormat) 1288 switch (outFormat)
1215 { 1289 {
1216 case FFMT_CHAR: 1290 case FFMT_CHAR:
1217 if (!dmConvertImage2Char(buf, image, 1291 if (!dmConvertImage2Char(tmpBuf, image,
1218 bx * C64_CHR_WIDTH_PX, by * C64_CHR_HEIGHT, 1292 bx * C64_CHR_WIDTH_PX, by * C64_CHR_HEIGHT,
1219 multicolor)) 1293 multicolor))
1220 goto error; 1294 goto error;
1221 break; 1295 break;
1222 1296
1223 case FFMT_SPRITE: 1297 case FFMT_SPRITE:
1224 if (!dmConvertImage2Sprite(buf, image, 1298 if (!dmConvertImage2Sprite(tmpBuf, image,
1225 bx * C64_SPR_WIDTH_PX, by * C64_SPR_HEIGHT, 1299 bx * C64_SPR_WIDTH_PX, by * C64_SPR_HEIGHT,
1226 multicolor)) 1300 multicolor))
1227 goto error; 1301 goto error;
1228 } 1302 break;
1303 }
1304 index++;
1305 }
1306
1307 // Eliminate duplicates
1308
1309
1310
1311 // Write out character data
1312 tmpFilename = dm_strdup_fext(filename, "%s.chr");
1313 if ((outFile = fopen(filename, "wb")) == NULL)
1314 {
1315 err = dmGetErrno();
1316 dmError("Could not open '%s' for writing, %d: %s.\n",
1317 filename, err, dmErrorStr(err));
1318 goto error;
1319 }
1320
1229 1321
1230 if (!dm_fwrite_str(outFile, buf, bufSize)) 1322 if (!dm_fwrite_str(outFile, buf, bufSize))
1231 { 1323 {
1232 int err = dmGetErrno(); 1324 err = dmGetErrno();
1233 dmError("Error writing data block %d,%d to '%s', %d: %s\n", 1325 dmError("Error writing data block %d,%d to '%s', %d: %s\n",
1234 bx, by, filename, err, dmErrorStr(err)); 1326 bx, by, filename, err, dmErrorStr(err));
1235 goto error; 1327 goto error;
1236 } 1328 }
1237 }
1238
1239 fclose(outFile);
1240 dmFree(buf);
1241 return 0;
1242 1329
1243 error: 1330 error:
1331 // Cleanup
1244 if (outFile != NULL) 1332 if (outFile != NULL)
1245 fclose(outFile); 1333 fclose(outFile);
1246 dmFree(buf); 1334
1247 return -1; 1335 if (outBuf != NULL)
1336 {
1337 for (index = 0; index < outBlockW * outBlockH; index++)
1338 dmFree(outBuf[i]);
1339 }
1340
1341 dmFree(tmpFilename);
1342 dmFree(outBuf);
1343 dmFree(tmpBuf);
1344 dmFree(outScreen);
1345
1346 return err;
1248 } 1347 }
1249 1348
1250 1349
1251 int dmDumpSpritesAndChars(FILE *inFile) 1350 int dmDumpSpritesAndChars(FILE *inFile)
1252 { 1351 {