comparison gfxconv.c @ 419:936bc27a79d6

Modularize some functions to lib64gfx, fix bitmap -> image conversion, and implement various cleanups.
author Matti Hamalainen <ccr@tnsp.org>
date Sat, 03 Nov 2012 07:53:38 +0200
parents 9ace8a5c58d9
children 066d93830743
comparison
equal deleted inserted replaced
418:b6a1dc3bd2c3 419:936bc27a79d6
13 #include "dmmutex.h" 13 #include "dmmutex.h"
14 #include "lib64gfx.h" 14 #include "lib64gfx.h"
15 15
16 //#define UNFINISHED 1 16 //#define UNFINISHED 1
17 17
18 #ifdef HAVE_LIBPNG 18 #ifdef DM_USE_LIBPNG
19 #include <png.h> 19 #include <png.h>
20 #endif 20 #endif
21 21
22 enum 22 enum
23 { 23 {
24 INFMT_AUTO = 0, 24 IMGFMT_PNG,
25 INFMT_CHAR, 25 IMGFMT_PPM,
26 INFMT_SPRITE, 26 IMGFMT_PCX,
27 INFMT_BITMAP, 27 IMGFMT_ARAW,
28 INFMT_IMAGE, 28
29 IMGFMT_LAST
29 }; 30 };
30 31
32 static const char *imageFormatList[IMGFMT_LAST] =
33 {
34 "PNG",
35 "PPM",
36 "PCX",
37 "ARAW",
38 };
39
31 enum 40 enum
32 { 41 {
33 OUTFMT_ASCII, 42 FFMT_AUTO = 0,
34 OUTFMT_ANSI, 43
35 OUTFMT_PNG, 44 FFMT_ASCII,
36 OUTFMT_PPM, 45 FFMT_ANSI,
37 OUTFMT_PCX, 46 FFMT_IMAGE,
38 OUTFMT_ARAW, 47
39 48 FFMT_CHAR,
40 #ifdef UNFINISHED 49 FFMT_SPRITE,
41 OUTFMT_SPRITE, 50 FFMT_BITMAP,
42 OUTFMT_CHAR, 51
43 #endif 52 FFMT_LAST
44
45 OUTFMT_LAST
46 }; 53 };
47 54
48 char * outFormatList[OUTFMT_LAST] = 55
49 { 56 typedef struct
50 "ascii", 57 {
51 "ansi", 58 char *name;
52 "png", 59 char *fext;
53 "ppm", 60 BOOL in, out;
54 "pcx", 61 int format;
55 "araw", 62 int subformat;
56 #ifdef UNFINISHED 63 } DMConvFormat;
57 "spr", 64
58 "char", 65
59 #endif 66 static DMConvFormat convFormatList[] =
67 {
68 {
69 "ASCII text", "asc", FALSE, TRUE,
70 FFMT_ASCII , 0,
71 },
72 {
73 "ANSI colored text", "ansi", FALSE, TRUE,
74 FFMT_ANSI , 0,
75 },
76 {
77 "PNG image file", "png", FALSE, TRUE,
78 FFMT_IMAGE , IMGFMT_PNG,
79 },
80 {
81 "PPM image file", "ppm", FALSE, TRUE,
82 FFMT_IMAGE , IMGFMT_PPM,
83 },
84 {
85 "PCX image file", "pcx", TRUE, TRUE,
86 FFMT_IMAGE , IMGFMT_PCX,
87 },
88 {
89 "IFFMaster RAW image file", "araw", FALSE, TRUE,
90 FFMT_IMAGE , IMGFMT_ARAW,
91 },
92
93 {
94 "C64 bitmap image file", NULL, TRUE, FALSE,
95 FFMT_BITMAP , 0,
96 },
97
98 {
99 "C64 character/font data", "chr", TRUE, FALSE,
100 FFMT_CHAR , 0
101 },
102 {
103 "C64 sprite data", "spr", TRUE, FALSE,
104 FFMT_SPRITE , 0
105 },
60 }; 106 };
61 107
62 static const int noutFormatList = sizeof(outFormatList) / sizeof(outFormatList[0]); 108 static const int nconvFormatList = sizeof(convFormatList) / sizeof(convFormatList[0]);
63 109
64 110
65 #define ASC_NBITS 8 111 #define ASC_NBITS 8
66 #define ASC_NCOLORS 4 112 #define ASC_NCOLORS 4
67 static const char dmASCIIPalette[ASC_NCOLORS] = ".:X#"; 113 static const char dmASCIIPalette[ASC_NCOLORS] = ".:X#";
68 114
69 115
70 char *optInFilename = NULL, 116 char *optInFilename = NULL,
71 *optOutFilename = NULL; 117 *optOutFilename = NULL;
72 int optInFormat = INFMT_AUTO, 118 int optInFormat = FFMT_AUTO,
73 optOutFormat = OUTFMT_ASCII, 119 optOutFormat = FFMT_ASCII,
120 optInSubFormat = IMGFMT_PNG,
121 optOutSubFormat = IMGFMT_PNG,
74 optItemCount = -1, 122 optItemCount = -1,
75 optScale = 2, 123 optScale = 2,
76 optPlanedWidth = 1, 124 optPlanedWidth = 1,
125 optForcedFormat = -1,
77 optBPP = 4; 126 optBPP = 4;
78 int optInSkip = 0; 127 int optInSkip = 0;
79 BOOL optInMulticolor = FALSE, 128 BOOL optInMulticolor = FALSE,
80 optSequential = FALSE, 129 optSequential = FALSE,
81 optPaletted = FALSE, 130 optPaletted = FALSE,
84 133
85 134
86 static DMOptArg optList[] = 135 static DMOptArg optList[] =
87 { 136 {
88 { 0, '?', "help", "Show this help", OPT_NONE }, 137 { 0, '?', "help", "Show this help", OPT_NONE },
138 {15, 'v', "verbose", "Increase verbosity", OPT_NONE },
89 { 3, 'o', "output", "Output filename", OPT_ARGREQ }, 139 { 3, 'o', "output", "Output filename", OPT_ARGREQ },
90 { 1, 'i', "informat", "Set input format ([s]prite, [c]har, [b]itmap, [i]mage)", OPT_ARGREQ }, 140 { 1, 'i', "informat", "Set input format ([s]prite, [c]har, [b]itmap, [i]mage)", OPT_ARGREQ },
91 { 2, 'm', "multicolor", "Input is multicolor", OPT_NONE }, 141 { 2, 'm', "multicolor", "Input is multicolor", OPT_NONE },
92 { 4, 's', "skip", "Skip bytes in input", OPT_ARGREQ }, 142 { 4, 's', "skip", "Skip bytes in input", OPT_ARGREQ },
93 { 5, 'f', "format", "Output format (see list below)", OPT_ARGREQ }, 143 { 5, 'f', "format", "Output format (see list below)", OPT_ARGREQ },
94 { 8, 'q', "sequential", "Output sequential files (image output only)", OPT_NONE }, 144 { 8, 'q', "sequential", "Output sequential files (image output only)", OPT_NONE },
95 { 6, 'c', "colormap", "Color mappings (see below for information)", OPT_ARGREQ }, 145 { 6, 'c', "colormap", "Color mappings (see below for information)", OPT_ARGREQ },
96 { 7, 'n', "numitems", "How many 'items' to view (default: all)", OPT_ARGREQ }, 146 { 7, 'n', "numitems", "How many 'items' to view (default: all)", OPT_ARGREQ },
97 { 9, 'S', "scale", "Scale output by x (image output only)", OPT_ARGREQ }, 147 { 9, 'S', "scale", "Scale output by x (image output only)", OPT_ARGREQ },
98 #ifdef UNFINISHED
99 {10, 'b', "bformat", "Force input bitmap format (see below)", OPT_ARGREQ }, 148 {10, 'b', "bformat", "Force input bitmap format (see below)", OPT_ARGREQ },
100 #endif
101 {11, 'w', "width", "Item width (number of items per row, min 1)", OPT_ARGREQ }, 149 {11, 'w', "width", "Item width (number of items per row, min 1)", OPT_ARGREQ },
102 {12, 'P', "paletted", "Use indexed/paletted output (png, pcx output only)", OPT_NONE }, 150 {12, 'P', "paletted", "Use indexed/paletted output (png, pcx output only)", OPT_NONE },
103 {13, 'b', "bplanes", "Bits per pixel OR # of bitplanes (certain output formats)", OPT_ARGREQ }, 151 {13, 'b', "bplanes", "Bits per pixel OR # of bitplanes (certain output formats)", OPT_ARGREQ },
104 {14, 'I', "interleave", "Interleave scanlines (default: output whole planes)", OPT_NONE }, 152 {14, 'I', "interleave", "Interleave scanlines (default: output whole planes)", OPT_NONE },
105 }; 153 };
112 int i; 160 int i;
113 161
114 dmPrintBanner(stdout, dmProgName, "[options] <input file>"); 162 dmPrintBanner(stdout, dmProgName, "[options] <input file>");
115 dmArgsPrintHelp(stdout, optList, optListN); 163 dmArgsPrintHelp(stdout, optList, optListN);
116 164
117 printf("\nAvailable output formats: "); 165 printf("\nAvailable output formats:\n");
118 for (i = 0; i < noutFormatList; i++) 166 for (i = 0; i < nconvFormatList; i++)
119 { 167 {
120 printf("%s", outFormatList[i]); 168 DMConvFormat *fmt = &convFormatList[i];
121 if (i < noutFormatList - 1) 169 printf("%3d | %-5s | %s\n",
122 printf(", "); 170 i, fmt->fext, fmt->name);
123 else 171 }
124 printf("\n"); 172
125 }
126
127 #ifdef UNFINISHED
128 printf("\nAvailable bitmap formats:\n"); 173 printf("\nAvailable bitmap formats:\n");
129 for (i = 0; i < ndmC64ImageFormats; i++) 174 for (i = 0; i < ndmC64ImageFormats; i++)
130 { 175 {
131 DM64ImageFormat *fmt = &dmC64ImageFormats[i]; 176 DMC64ImageFormat *fmt = &dmC64ImageFormats[i];
132 printf("%3d | %-5s | %-15s | %s\n", 177 printf("%3d | %-5s | %-15s | %s\n",
133 i, fmt->extension, 178 i, fmt->extension,
134 dmC64ImageTypeNames[fmt->type], 179 dmC64ImageTypeNames[fmt->type],
135 fmt->name); 180 fmt->name);
136 } 181 }
137 #endif
138 182
139 printf( 183 printf(
140 "\n" 184 "\n"
141 "Color map definitions are used for ANSI, PCX, PPM and PNG output, to declare what\n" 185 "Color map definitions are used for ANSI, PCX, PPM and PNG output, to declare what\n"
142 "output colors of the C64 palette are used for each single color/multi color\n" 186 "output colors of the C64 palette are used for each single color/multi color\n"
147 "special color that can be used for transparency.\n" 191 "special color that can be used for transparency.\n"
148 ); 192 );
149 } 193 }
150 194
151 195
196 int dmGetConvFormat(int format, int subformat)
197 {
198 int i;
199 for (i = 0; i < nconvFormatList; i++)
200 {
201 DMConvFormat *fmt = &convFormatList[i];
202 if (fmt->format == format &&
203 fmt->subformat == subformat)
204 return i;
205 }
206 return -1;
207 }
208
209
210 BOOL dmGetFormatByExt(const char *fext, int *format, int *subformat)
211 {
212 int i;
213 for (i = 0; i < nconvFormatList; i++)
214 {
215 DMConvFormat *fmt = &convFormatList[i];
216 if (strcasecmp(fext, fmt->fext) == 0)
217 {
218 *format = fmt->format;
219 *subformat = fmt->subformat;
220 return TRUE;
221 }
222 }
223 return FALSE;
224 }
225
226
152 BOOL argHandleOpt(const int optN, char *optArg, char *currArg) 227 BOOL argHandleOpt(const int optN, char *optArg, char *currArg)
153 { 228 {
154 switch (optN) 229 switch (optN)
155 { 230 {
156 case 0: 231 case 0:
157 argShowHelp(); 232 argShowHelp();
158 exit(0); 233 exit(0);
159 break; 234 break;
160 235
236 case 15:
237 dmVerbosity++;
238 break;
239
161 case 1: 240 case 1:
162 switch (tolower(optArg[0])) 241 switch (tolower(optArg[0]))
163 { 242 {
164 case 's': 243 case 's':
165 optInFormat = INFMT_SPRITE; 244 optInFormat = FFMT_SPRITE;
166 break; 245 break;
167 case 'c': 246 case 'c':
168 optInFormat = INFMT_CHAR; 247 optInFormat = FFMT_CHAR;
169 break; 248 break;
170 case 'b': 249 case 'b':
171 optInFormat = INFMT_BITMAP; 250 optInFormat = FFMT_BITMAP;
172 break; 251 break;
173 case 'i': 252 case 'i':
174 optInFormat = INFMT_IMAGE; 253 optInFormat = FFMT_IMAGE;
175 break; 254 break;
176 default: 255 default:
177 dmError("Invalid input format '%s'.\n", optArg); 256 dmError("Invalid input format '%s'.\n", optArg);
178 return FALSE; 257 return FALSE;
179 } 258 }
194 return FALSE; 273 return FALSE;
195 } 274 }
196 break; 275 break;
197 276
198 case 5: 277 case 5:
199 { 278 if (!dmGetFormatByExt(optArg, &optOutFormat, &optOutSubFormat))
200 int i, format = -1; 279 {
201 for (i = 0; i < noutFormatList; i++) 280 dmError("Invalid output format '%s'.\n", optArg);
202 if (strcasecmp(optArg, outFormatList[i]) == 0) 281 return FALSE;
203 {
204 format = i;
205 break;
206 }
207
208 if (format < 0)
209 {
210 dmError("Invalid output format '%s'.\n", optArg);
211 return FALSE;
212 }
213
214 optOutFormat = format;
215 } 282 }
216 break; 283 break;
217 284
218 case 6: 285 case 6:
219 { 286 {
335 { 402 {
336 int val = (byte & (3ULL << (i - 2))) >> (i - 2); 403 int val = (byte & (3ULL << (i - 2))) >> (i - 2);
337 char ch; 404 char ch;
338 switch (format) 405 switch (format)
339 { 406 {
340 case OUTFMT_ASCII: 407 case FFMT_ASCII:
341 ch = dmASCIIPalette[val]; 408 ch = dmASCIIPalette[val];
342 fprintf(out, "%c%c", ch, ch); 409 fprintf(out, "%c%c", ch, ch);
343 break; 410 break;
344 case OUTFMT_ANSI: 411 case FFMT_ANSI:
345 fprintf(out, "%c[0;%d;%dm##%c[0m", 412 fprintf(out, "%c[0;%d;%dm##%c[0m",
346 0x1b, 413 0x1b,
347 1, 414 1,
348 31 + optColors[val], 415 31 + optColors[val],
349 0x1b); 416 0x1b);
357 { 424 {
358 int val = (byte & (1ULL << (i - 1))) >> (i - 1); 425 int val = (byte & (1ULL << (i - 1))) >> (i - 1);
359 char ch; 426 char ch;
360 switch (format) 427 switch (format)
361 { 428 {
362 case OUTFMT_ASCII: 429 case FFMT_ASCII:
363 ch = val ? '#' : '.'; 430 ch = val ? '#' : '.';
364 fputc(ch, out); 431 fputc(ch, out);
365 break; 432 break;
366 case OUTFMT_ANSI: 433 case FFMT_ANSI:
367 fprintf(out, "%c[0;%d;%dm %c[0m", 434 fprintf(out, "%c[0;%d;%dm %c[0m",
368 0x1b, 435 0x1b,
369 1, 436 1,
370 31 + optColors[val], 437 31 + optColors[val],
371 0x1b); 438 0x1b);
631 fclose(fp); 698 fclose(fp);
632 return res; 699 return res;
633 } 700 }
634 701
635 702
636 #ifdef HAVE_LIBPNG 703 #ifdef DM_USE_LIBPNG
637 static BOOL dmWritePNGRow(void *cbdata, Uint8 *row, size_t len) 704 static BOOL dmWritePNGRow(void *cbdata, Uint8 *row, size_t len)
638 { 705 {
639 png_structp png_ptr = cbdata; 706 png_structp png_ptr = cbdata;
640 (void) len; 707 (void) len;
641 708
910 hdr.vres = img->height * scale; 977 hdr.vres = img->height * scale;
911 hdr.xmin = hdr.ymin = 0; 978 hdr.xmin = hdr.ymin = 0;
912 hdr.xmax = hdr.hres - 1; 979 hdr.xmax = hdr.hres - 1;
913 hdr.ymax = hdr.vres - 1; 980 hdr.ymax = hdr.vres - 1;
914 hdr.nplanes = dmImageGetBytesPerPixel(pcx.format); 981 hdr.nplanes = dmImageGetBytesPerPixel(pcx.format);
915 hdr.bpl = (((img->width * scale) / 2) + 1) * 2;
916 hdr.palinfo = 1; 982 hdr.palinfo = 1;
917 983 res = (img->width * scale);
918 dmMsg(1, "PCX: paletted=%d, nplanes=%d, bpp=%d, bpl=%d\n", 984 hdr.bpl = res / 2;
985 if (res % 2) hdr.bpl++;
986 hdr.bpl *= 2;
987
988 dmMsg(2, "PCX: paletted=%d, nplanes=%d, bpp=%d, bpl=%d\n",
919 paletted, hdr.nplanes, hdr.bpp, hdr.bpl); 989 paletted, hdr.nplanes, hdr.bpp, hdr.bpl);
920 990
921 pcx.bufLen = hdr.bpl * 4; 991 pcx.bufLen = hdr.bpl * 4;
922 if ((pcx.buf = dmMalloc(pcx.bufLen)) == NULL) 992 if ((pcx.buf = dmMalloc(pcx.bufLen)) == NULL)
923 { 993 {
974 // Write VGA palette 1044 // Write VGA palette
975 if (paletted) 1045 if (paletted)
976 { 1046 {
977 int i; 1047 int i;
978 dm_fwrite_byte(pcx.fp, 0x0C); 1048 dm_fwrite_byte(pcx.fp, 0x0C);
1049 dmMsg(2, "PCX: Writing palette of %d active entries.\n", img->ncolors);
979 1050
980 for (i = 0; i < img->ncolors; i++) 1051 for (i = 0; i < img->ncolors; i++)
981 { 1052 {
982 dm_fwrite_byte(pcx.fp, img->pal[i].r); 1053 dm_fwrite_byte(pcx.fp, img->pal[i].r);
983 dm_fwrite_byte(pcx.fp, img->pal[i].g); 1054 dm_fwrite_byte(pcx.fp, img->pal[i].g);
1249 fclose(fp); 1320 fclose(fp);
1250 return res; 1321 return res;
1251 } 1322 }
1252 1323
1253 1324
1254 int fmtProbePNGImageFILE(FILE *fp) 1325 static int fmtProbePNG(const Uint8 *buf, const size_t len)
1255 { 1326 {
1256 Uint8 buf[6]; 1327 if (len > 64 && buf[0] == 0x89 &&
1257 // if (!dm_fread_str(fp, 1328 buf[1] == 'P' && buf[2] == 'N' && buf[3] == 'G' &&
1329 buf[4] == 0x0d && buf[5] == 0x0a)
1330 return DM_PROBE_SCORE_GOOD;
1331
1258 return DM_PROBE_SCORE_FALSE; 1332 return DM_PROBE_SCORE_FALSE;
1259 } 1333 }
1260 1334
1261 1335
1262 int fmtProbePCXImageFILE(FILE *fp) 1336 static int fmtProbePCX(const Uint8 *buf, const size_t len)
1263 { 1337 {
1264 DMPCXHeader hdr; 1338 if (len > 128 + 64 &&
1265 1339 buf[0] == 10 &&
1266 if (!dm_fread_byte(fp, &hdr.manufacturer) || 1340 buf[1] == 5 &&
1267 !dm_fread_byte(fp, &hdr.version) || 1341 buf[2] == 1 &&
1268 !dm_fread_byte(fp, &hdr.encoding) || 1342 buf[3] == 8)
1269 !dm_fread_byte(fp, &hdr.bpp))
1270 return DM_PROBE_SCORE_FALSE;
1271
1272 if (hdr.manufacturer == 10 &&
1273 hdr.version == 5 &&
1274 hdr.encoding == 1 &&
1275 hdr.bpp == 8)
1276 return DM_PROBE_SCORE_GOOD; 1343 return DM_PROBE_SCORE_GOOD;
1277 1344
1278 return DM_PROBE_SCORE_FALSE; 1345 return DM_PROBE_SCORE_FALSE;
1279 } 1346 }
1280 1347
1319 return 0; 1386 return 0;
1320 } 1387 }
1321 #endif 1388 #endif
1322 1389
1323 1390
1324 int dmWriteImage(char *filename, DMImage *image) 1391 int dmWriteImage(char *filename, DMImage *image, BOOL info)
1325 { 1392 {
1326 switch (optOutFormat) 1393 if (info)
1327 { 1394 {
1328 #ifdef HAVE_LIBPNG 1395 dmMsg(1, "Outputting %s image %d x %d -> %d x %d [%d]\n",
1329 case OUTFMT_PNG: 1396 imageFormatList[optOutSubFormat],
1397 image->width, image->height,
1398 image->width * optScale, image->height * optScale, optScale);
1399 }
1400
1401 switch (optOutSubFormat)
1402 {
1403 #ifdef DM_USE_LIBPNG
1404 case IMGFMT_PNG:
1405 if (info) dmMsg(2, "%s output.\n", optPaletted ? "Indexed 8bpp" : "32bit RGBA");
1330 return dmWritePNGImage(filename, image, optScale, optPaletted ? DM_IFMT_PALETTE : DM_IFMT_RGBA); 1406 return dmWritePNGImage(filename, image, optScale, optPaletted ? DM_IFMT_PALETTE : DM_IFMT_RGBA);
1331 #endif 1407 #endif
1332 1408
1333 case OUTFMT_PPM: 1409 case IMGFMT_PPM:
1410 if (info) dmMsg(2, "24bit RGB output.\n");
1334 return dmWritePPMImage(filename, image, optScale); 1411 return dmWritePPMImage(filename, image, optScale);
1335 1412
1336 case OUTFMT_PCX: 1413 case IMGFMT_PCX:
1414 if (info) dmMsg(2, "%s output.\n", optPaletted ? "Indexed 8bpp" : "24bit RGB");
1337 return dmWritePCXImage(filename, image, optScale, optPaletted); 1415 return dmWritePCXImage(filename, image, optScale, optPaletted);
1338 1416
1339 case OUTFMT_ARAW: 1417 case IMGFMT_ARAW:
1340 { 1418 {
1341 int res; 1419 int res;
1342 char *palFilename = dm_strdup_printf("%s.pal", filename); 1420 char *palFilename = dm_strdup_printf("%s.pal", filename);
1343 res = dmWriteIFFMasterRAWPalette(palFilename, image, 1 << optBPP); 1421 res = dmWriteIFFMasterRAWPalette(palFilename, image, 1 << optBPP);
1344 dmFree(palFilename); 1422 dmFree(palFilename);
1345 if (res != DMERR_OK) 1423 if (res != DMERR_OK)
1346 return res; 1424 return res;
1347 1425
1426 if (info) dmMsg(2, "%d bitplanes, %s interleave.\n", optBPP, optInterleave ? "with" : "without");
1348 return dmWriteIFFMasterRAWImage(filename, image, optScale, optBPP, optInterleave); 1427 return dmWriteIFFMasterRAWImage(filename, image, optScale, optBPP, optInterleave);
1349 } 1428 }
1350 1429
1351 default: 1430 default:
1352 return FALSE; 1431 return FALSE;
1360 size_t bufSize; 1439 size_t bufSize;
1361 Uint8 *bufData; 1440 Uint8 *bufData;
1362 1441
1363 switch (optInFormat) 1442 switch (optInFormat)
1364 { 1443 {
1365 case INFMT_CHAR: 1444 case FFMT_CHAR:
1366 bufSize = C64_CHR_SIZE; 1445 bufSize = C64_CHR_SIZE;
1367 outWidth = C64_CHR_WIDTH; 1446 outWidth = C64_CHR_WIDTH;
1368 outWidthPX = C64_CHR_WIDTH_PX; 1447 outWidthPX = C64_CHR_WIDTH_PX;
1369 outHeight = C64_CHR_HEIGHT; 1448 outHeight = C64_CHR_HEIGHT;
1370 break; 1449 break;
1371 case INFMT_SPRITE: 1450
1451 case FFMT_SPRITE:
1372 bufSize = C64_SPR_SIZE; 1452 bufSize = C64_SPR_SIZE;
1373 outWidth = C64_SPR_WIDTH; 1453 outWidth = C64_SPR_WIDTH;
1374 outWidthPX = C64_SPR_WIDTH_PX; 1454 outWidthPX = C64_SPR_WIDTH_PX;
1375 outHeight = C64_SPR_HEIGHT; 1455 outHeight = C64_SPR_HEIGHT;
1376 break; 1456 break;
1457
1377 default: 1458 default:
1378 dmError("Invalid input format %d, internal error.\n", optInFormat); 1459 dmError("Invalid input format %d, internal error.\n", optInFormat);
1379 return -1; 1460 return -1;
1380 } 1461 }
1381 1462
1387 1468
1388 1469
1389 dataOffs = optInSkip; 1470 dataOffs = optInSkip;
1390 itemCount = 0; 1471 itemCount = 0;
1391 1472
1392 if (optOutFormat == OUTFMT_ANSI || optOutFormat == OUTFMT_ASCII) 1473 if (optOutFormat == FFMT_ANSI || optOutFormat == FFMT_ASCII)
1393 { 1474 {
1394 BOOL error = FALSE; 1475 BOOL error = FALSE;
1395 FILE *outFile; 1476 FILE *outFile;
1396 1477
1397 if (optOutFilename == NULL) 1478 if (optOutFilename == NULL)
1418 1499
1419 fprintf(outFile, "---- : -------------- #%d\n", itemCount); 1500 fprintf(outFile, "---- : -------------- #%d\n", itemCount);
1420 1501
1421 switch (optInFormat) 1502 switch (optInFormat)
1422 { 1503 {
1423 case INFMT_CHAR: 1504 case FFMT_CHAR:
1424 dmDumpCharASCII(outFile, bufData, &dataOffs, optOutFormat, optInMulticolor); 1505 dmDumpCharASCII(outFile, bufData, &dataOffs, optOutFormat, optInMulticolor);
1425 break; 1506 break;
1426 case INFMT_SPRITE: 1507 case FFMT_SPRITE:
1427 dmDumpSpriteASCII(outFile, bufData, &dataOffs, optOutFormat, optInMulticolor); 1508 dmDumpSpriteASCII(outFile, bufData, &dataOffs, optOutFormat, optInMulticolor);
1428 break; 1509 break;
1429 } 1510 }
1430 itemCount++; 1511 itemCount++;
1431 } 1512 }
1432 1513
1433 fclose(outFile); 1514 fclose(outFile);
1434 } 1515 }
1435 else 1516 else
1436 if (optOutFormat == OUTFMT_PNG || optOutFormat == OUTFMT_PPM || optOutFormat == OUTFMT_PCX) 1517 if (optOutFormat == IMGFMT_PNG || optOutFormat == IMGFMT_PPM || optOutFormat == IMGFMT_PCX)
1437 { 1518 {
1438 DMImage *outImage = NULL; 1519 DMImage *outImage = NULL;
1439 char *outFilename = NULL; 1520 char *outFilename = NULL;
1440 int outX = 0, outY = 0, err; 1521 int outX = 0, outY = 0, err;
1441 1522
1466 outIHeight = (optItemCount / optPlanedWidth); 1547 outIHeight = (optItemCount / optPlanedWidth);
1467 if (optItemCount % optPlanedWidth) 1548 if (optItemCount % optPlanedWidth)
1468 outIHeight++; 1549 outIHeight++;
1469 1550
1470 outImage = dmImageAlloc(outWidthPX * outIWidth, outIHeight * outHeight); 1551 outImage = dmImageAlloc(outWidthPX * outIWidth, outIHeight * outHeight);
1471 dmMsg(1, "Outputting image %d x %d -> %d x %d.\n",
1472 outImage->width, outImage->height,
1473 outImage->width * optScale, outImage->height * optScale);
1474 } 1552 }
1475 1553
1476 outImage->constpal = TRUE; 1554 outImage->constpal = TRUE;
1477 outImage->pal = dmC64Palette; 1555 outImage->pal = dmC64Palette;
1478 outImage->ncolors = C64_NCOLORS; 1556 outImage->ncolors = C64_NCOLORS;
1496 break; 1574 break;
1497 } 1575 }
1498 1576
1499 if (optSequential) 1577 if (optSequential)
1500 { 1578 {
1501 outFilename = dm_strdup_printf("%s%04d.%s", optOutFilename, itemCount, outFormatList[optOutFormat]); 1579 outFilename = dm_strdup_printf("%s%04d.%s", optOutFilename, itemCount, convFormatList[optOutFormat].fext);
1502 if (outFilename == NULL) 1580 if (outFilename == NULL)
1503 { 1581 {
1504 dmError("Could not allocate memory for filename template?\n"); 1582 dmError("Could not allocate memory for filename template?\n");
1505 goto error; 1583 goto error;
1506 } 1584 }
1507 1585
1508 dmWriteImage(outFilename, outImage); 1586 dmWriteImage(outFilename, outImage, FALSE);
1509 dmFree(outFilename); 1587 dmFree(outFilename);
1510 } 1588 }
1511 else 1589 else
1512 { 1590 {
1513 if (++outX >= optPlanedWidth) 1591 if (++outX >= optPlanedWidth)
1520 itemCount++; 1598 itemCount++;
1521 } 1599 }
1522 1600
1523 if (!optSequential) 1601 if (!optSequential)
1524 { 1602 {
1525 dmWriteImage(optOutFilename, outImage); 1603 dmWriteImage(optOutFilename, outImage, TRUE);
1526 } 1604 }
1527 1605
1528 dmImageFree(outImage); 1606 dmImageFree(outImage);
1529 } 1607 }
1530 1608
1538 1616
1539 1617
1540 int main(int argc, char *argv[]) 1618 int main(int argc, char *argv[])
1541 { 1619 {
1542 FILE *inFile; 1620 FILE *inFile;
1543 int i, optInImageFormat; 1621 DMC64ImageFormat *cfmt;
1622 DMC64Image cimage;
1623 Uint8 *dataBuf = NULL;
1624 size_t dataSize;
1625 int i;
1544 1626
1545 // Default colors 1627 // Default colors
1546 for (i = 0; i < C64_MAX_COLORS; i++) 1628 for (i = 0; i < C64_MAX_COLORS; i++)
1547 optColors[i] = i + 1; 1629 optColors[i] = i + 1;
1548 1630
1551 1633
1552 if (!dmArgsProcess(argc, argv, optList, optListN, 1634 if (!dmArgsProcess(argc, argv, optList, optListN,
1553 argHandleOpt, argHandleFile, TRUE)) 1635 argHandleOpt, argHandleFile, TRUE))
1554 exit(1); 1636 exit(1);
1555 1637
1556 #ifndef HAVE_LIBPNG 1638 #ifndef DM_USE_LIBPNG
1557 if (optOutFormat == OUTFMT_PNG) 1639 if (optOutFormat == IMGFMT_PNG)
1558 { 1640 {
1559 dmError("PNG output format support not compiled in, sorry.\n"); 1641 dmError("PNG output format support not compiled in, sorry.\n");
1560 exit(3); 1642 goto error;
1561 } 1643 }
1562 #endif 1644 #endif
1563 1645
1564 // Determine input format, if not specified' 1646 // Determine input format, if not specified'
1565 if (optInFormat == INFMT_AUTO && optInFilename != NULL) 1647 if (optInFormat == FFMT_AUTO && optInFilename != NULL)
1566 { 1648 {
1567 char *dext = strrchr(optInFilename, '.'); 1649 char *dext = strrchr(optInFilename, '.');
1568 if (dext) 1650 if (dext)
1569 { 1651 {
1570 dext++; 1652 dmGetFormatByExt(dext + 1, &optInFormat, &optInSubFormat);
1571 if (!strcasecmp(dext, "fnt") || !strcasecmp(dext, "chr"))
1572 optInFormat = INFMT_CHAR;
1573 else if (!strcasecmp(dext, "spr"))
1574 optInFormat = INFMT_SPRITE;
1575 else if (!strcasecmp(dext, "png") || !strcasecmp(dext, "pcx"))
1576 optInFormat = INFMT_IMAGE;
1577 } 1653 }
1578 } 1654 }
1579 1655
1580 if (optInFilename == NULL) 1656 if (optInFilename == NULL)
1581 { 1657 {
1582 if (optInFormat == INFMT_AUTO) 1658 if (optInFormat == FFMT_AUTO)
1583 { 1659 {
1584 dmError("Standard input cannot be used without specifying input format.\n"); 1660 dmError("Standard input cannot be used without specifying input format.\n");
1585 exit(3); 1661 goto error;
1586 } 1662 }
1587 inFile = stdin; 1663 inFile = stdin;
1588 } 1664 }
1589 else 1665 else
1590 if ((inFile = fopen(optInFilename, "rb")) == NULL) 1666 if ((inFile = fopen(optInFilename, "rb")) == NULL)
1591 { 1667 {
1592 int res = errno; 1668 int res = errno;
1593 dmError("Error opening input file '%s'. (%s)\n", 1669 dmError("Error opening input file '%s'. (%s)\n",
1594 optInFilename, strerror(res)); 1670 optInFilename, strerror(res));
1595 exit(3); 1671 goto error;
1596 } 1672 }
1597 1673
1598 if (optInFormat == INFMT_AUTO) 1674 if (dmReadDataFile(inFile, NULL, &dataBuf, &dataSize) != 0)
1599 { 1675 goto error;
1600 // Skip, if needed 1676
1601 if (fseek(inFile, optInSkip, SEEK_SET) != 0) 1677 if (optInFormat == FFMT_AUTO || optInFormat == FFMT_BITMAP)
1602 { 1678 {
1603 int res = errno; 1679 // Probe for format
1604 dmError("Could not seek to file position %d (0x%x): %s\n", 1680 DMC64ImageFormat *forced = NULL;
1605 optInSkip, optInSkip, strerror(res)); 1681 int res;
1606 exit(3); 1682
1607 } 1683 if (optForcedFormat >= 0)
1608 #if 0 1684 {
1609 if (optInFormat == INFMT_AUTO) 1685 forced = &dmC64ImageFormats[optForcedFormat];
1610 { 1686 dmMsg(0,"Forced %s format image, type %d, %s\n",
1611 int ret = dmC64ProbeGeneric 1687 forced->name, forced->type, forced->extension);
1612 } 1688 }
1613 #endif 1689
1614 1690 res = dmC64DecodeBMP(&cimage, dataBuf, dataSize, optInSkip, optInSkip + 2, &cfmt, forced);
1615 if (optInFormat == INFMT_AUTO || optInFormat == INFMT_IMAGE) 1691 if (forced == NULL && cfmt != NULL)
1616 { 1692 {
1617 if (fmtProbePNGImageFILE(inFile)) 1693 dmMsg(1,"Probed %s format image, type %d, %s\n",
1618 { 1694 cfmt->name, cfmt->type, cfmt->extension);
1619 optInFormat = INFMT_IMAGE; 1695 }
1620 optInImageFormat = OUTFMT_PNG; 1696
1621 } 1697 if (res == 0)
1622 else 1698 optInFormat = FFMT_BITMAP;
1623 if (fmtProbePCXImageFILE(inFile)) 1699 }
1624 { 1700
1625 optInFormat = INFMT_IMAGE; 1701 if (optInFormat == FFMT_AUTO)
1626 optInImageFormat = OUTFMT_PCX; 1702 {
1627 } 1703 // XXX, needs a proper probe loop
1628 else 1704 if (fmtProbePNG(dataBuf + optInSkip, dataSize - optInSkip))
1629 if (optInFormat == INFMT_IMAGE) 1705 {
1630 { 1706 optInFormat = FFMT_IMAGE;
1631 dmError("Unsupported image input format.\n"); 1707 optInSubFormat = IMGFMT_PNG;
1632 exit(4); 1708 }
1633 } 1709 else
1634 } 1710 if (fmtProbePCX(dataBuf + optInSkip, dataSize - optInSkip))
1635 } 1711 {
1636 1712 optInFormat = FFMT_IMAGE;
1637 if (optInFormat == INFMT_AUTO) 1713 optInSubFormat = IMGFMT_PCX;
1714 }
1715 }
1716
1717 if (optInFormat == FFMT_AUTO)
1638 { 1718 {
1639 dmError("No input format specified, and could not be determined automatically.\n"); 1719 dmError("No input format specified, and could not be determined automatically.\n");
1640 exit(1); 1720 exit(1);
1641 } 1721 }
1642 1722
1644 if (fseek(inFile, optInSkip, SEEK_SET) != 0) 1724 if (fseek(inFile, optInSkip, SEEK_SET) != 0)
1645 { 1725 {
1646 int res = errno; 1726 int res = errno;
1647 dmError("Could not seek to file position %d (0x%x): %s\n", 1727 dmError("Could not seek to file position %d (0x%x): %s\n",
1648 optInSkip, optInSkip, strerror(res)); 1728 optInSkip, optInSkip, strerror(res));
1649 exit(3); 1729 goto error;
1730 }
1731
1732 int inFormat = dmGetConvFormat(optInFormat, optInSubFormat),
1733 outFormat = dmGetConvFormat(optOutFormat, optOutSubFormat);
1734
1735 if (inFormat != -1 && outFormat != -1)
1736 {
1737 char *inFmtName = convFormatList[inFormat].name,
1738 *inFmtExt = convFormatList[inFormat].fext,
1739 *outFmtName = convFormatList[outFormat].name,
1740 *outFmtExt = convFormatList[outFormat].fext;
1741
1742 if (optInFormat == FFMT_BITMAP)
1743 inFmtExt = cfmt->name;
1744
1745 dmMsg(1, "Attempting conversion %s (%s) -> %s (%s)\n",
1746 inFmtName, inFmtExt, outFmtName, outFmtExt);
1650 } 1747 }
1651 1748
1652 switch (optInFormat) 1749 switch (optInFormat)
1653 { 1750 {
1654 case INFMT_SPRITE: 1751 case FFMT_SPRITE:
1655 case INFMT_CHAR: 1752 case FFMT_CHAR:
1656 dmDumpSpritesAndChars(inFile); 1753 dmDumpSpritesAndChars(inFile);
1657 break; 1754 break;
1658 1755
1659 case INFMT_BITMAP: 1756 case FFMT_BITMAP:
1660 case INFMT_IMAGE: 1757 {
1661 { 1758 DMImage *img = NULL;
1662 DMImage *img; 1759 int res = DMERR_OK;
1663 int res;
1664 1760
1665 if (optOutFilename == NULL) 1761 if (optOutFilename == NULL)
1666 { 1762 {
1667 dmError("Output filename not set, required for image formats.\n"); 1763 dmError("Output filename not set, required for image formats.\n");
1668 exit(3); 1764 goto error;
1669 } 1765 }
1670 1766
1767 switch (optOutFormat)
1768 {
1769 case FFMT_IMAGE:
1770 if ((img = dmImageAlloc(C64_SCR_WIDTH, C64_SCR_HEIGHT)) == NULL)
1771 {
1772 dmError("Could not allocate output image surface %d x %d.\n",
1773 C64_SCR_WIDTH, C64_SCR_HEIGHT);
1774 goto error;
1775 }
1776
1777 img->pal = (DMColor *) &dmC64Palette;
1778 img->ncolors = C64_NCOLORS;
1779 img->constpal = TRUE;
1780
1781 if (cfmt->convert != NULL)
1782 res = cfmt->convert(img, &cimage);
1783 else
1784 res = dmC64ConvertGenericBMP2Image(img, &cimage);
1785
1786 if (res != DMERR_OK || img == NULL)
1787 {
1788 dmError("Error in bitmap to image conversion.\n");
1789 goto error;
1790 }
1791
1792 res = dmWriteImage(optOutFilename, img, TRUE);
1793 break;
1794
1795 default:
1796 dmError("Unsupported output format for bitmap/image conversion.\n");
1797 break;
1798 }
1799
1800 dmImageFree(img);
1801 }
1802 break;
1803
1804 case FFMT_IMAGE:
1805 {
1806 DMImage *img;
1807 int res = DMERR_OK;
1808
1809 if (optOutFilename == NULL)
1810 {
1811 dmError("Output filename not set, required for image formats.\n");
1812 goto error;
1813 }
1814
1671 // Read input 1815 // Read input
1672 switch (optInImageFormat) 1816 switch (optInSubFormat)
1673 { 1817 {
1674 case OUTFMT_PCX: 1818 case IMGFMT_PCX: res = dmReadPCXImageFILE(inFile, &img); break;
1675 res = dmReadPCXImageFILE(inFile, &img); 1819 // case IMGFMT_PNG: res = dmReadPNGImageFILE(inFile, &img); break;
1676 break; 1820 // case IMGFMT_ARAW: res = dmReadARAWImageFILE(inFile, &img, optBPP); break;
1677 /*
1678 case OUTFMT_PNG:
1679 res = dmReadPNGImageFILE(inFile, &img);
1680 break;
1681 */
1682 default: 1821 default:
1683 dmError("Unsupported input image format for bitmap/image conversion.\n"); 1822 dmError("Unsupported input image format for bitmap/image conversion.\n");
1684 break; 1823 break;
1685 1824
1686 } 1825 }
1687 1826
1688 if (res != DMERR_OK) 1827 if (res != DMERR_OK || img == NULL)
1689 break; 1828 break;
1690 1829
1691 switch (optOutFormat) 1830 switch (optOutFormat)
1692 { 1831 {
1693 case OUTFMT_PCX: 1832 case FFMT_IMAGE:
1694 case OUTFMT_PPM: 1833 res = dmWriteImage(optOutFilename, img, TRUE);
1695 case OUTFMT_PNG:
1696 case OUTFMT_ARAW:
1697 res = dmWriteImage(optOutFilename, img);
1698 break; 1834 break;
1699 1835
1700 default: 1836 default:
1701 dmError("Unsupported output format for bitmap/image conversion.\n"); 1837 dmError("Unsupported output format for bitmap/image conversion.\n");
1702 break; 1838 break;
1703 } 1839 }
1840
1841 dmImageFree(img);
1704 } 1842 }
1705 break; 1843 break;
1706 } 1844 }
1707 1845
1708 fclose(inFile); 1846 fclose(inFile);
1709 1847
1710 exit(0); 1848 exit(0);
1711 return 0; 1849 return 0;
1712 } 1850
1851 error:
1852 return -3;
1853 exit(3);
1854 }