Mercurial > hg > dmlib
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 } |