# HG changeset patch # User Matti Hamalainen # Date 1351922018 -7200 # Node ID 936bc27a79d631aa668ed47f9188d4033e7dc670 # Parent b6a1dc3bd2c3027ea10393e91a3fd8ab07e57440 Modularize some functions to lib64gfx, fix bitmap -> image conversion, and implement various cleanups. diff -r b6a1dc3bd2c3 -r 936bc27a79d6 gfxconv.c --- a/gfxconv.c Sat Nov 03 07:52:26 2012 +0200 +++ b/gfxconv.c Sat Nov 03 07:53:38 2012 +0200 @@ -15,51 +15,97 @@ //#define UNFINISHED 1 -#ifdef HAVE_LIBPNG +#ifdef DM_USE_LIBPNG #include #endif enum { - INFMT_AUTO = 0, - INFMT_CHAR, - INFMT_SPRITE, - INFMT_BITMAP, - INFMT_IMAGE, + IMGFMT_PNG, + IMGFMT_PPM, + IMGFMT_PCX, + IMGFMT_ARAW, + + IMGFMT_LAST +}; + +static const char *imageFormatList[IMGFMT_LAST] = +{ + "PNG", + "PPM", + "PCX", + "ARAW", }; enum { - OUTFMT_ASCII, - OUTFMT_ANSI, - OUTFMT_PNG, - OUTFMT_PPM, - OUTFMT_PCX, - OUTFMT_ARAW, + FFMT_AUTO = 0, + + FFMT_ASCII, + FFMT_ANSI, + FFMT_IMAGE, -#ifdef UNFINISHED - OUTFMT_SPRITE, - OUTFMT_CHAR, -#endif + FFMT_CHAR, + FFMT_SPRITE, + FFMT_BITMAP, - OUTFMT_LAST + FFMT_LAST }; -char * outFormatList[OUTFMT_LAST] = + +typedef struct +{ + char *name; + char *fext; + BOOL in, out; + int format; + int subformat; +} DMConvFormat; + + +static DMConvFormat convFormatList[] = { - "ascii", - "ansi", - "png", - "ppm", - "pcx", - "araw", -#ifdef UNFINISHED - "spr", - "char", -#endif + { + "ASCII text", "asc", FALSE, TRUE, + FFMT_ASCII , 0, + }, + { + "ANSI colored text", "ansi", FALSE, TRUE, + FFMT_ANSI , 0, + }, + { + "PNG image file", "png", FALSE, TRUE, + FFMT_IMAGE , IMGFMT_PNG, + }, + { + "PPM image file", "ppm", FALSE, TRUE, + FFMT_IMAGE , IMGFMT_PPM, + }, + { + "PCX image file", "pcx", TRUE, TRUE, + FFMT_IMAGE , IMGFMT_PCX, + }, + { + "IFFMaster RAW image file", "araw", FALSE, TRUE, + FFMT_IMAGE , IMGFMT_ARAW, + }, + + { + "C64 bitmap image file", NULL, TRUE, FALSE, + FFMT_BITMAP , 0, + }, + + { + "C64 character/font data", "chr", TRUE, FALSE, + FFMT_CHAR , 0 + }, + { + "C64 sprite data", "spr", TRUE, FALSE, + FFMT_SPRITE , 0 + }, }; -static const int noutFormatList = sizeof(outFormatList) / sizeof(outFormatList[0]); +static const int nconvFormatList = sizeof(convFormatList) / sizeof(convFormatList[0]); #define ASC_NBITS 8 @@ -69,11 +115,14 @@ char *optInFilename = NULL, *optOutFilename = NULL; -int optInFormat = INFMT_AUTO, - optOutFormat = OUTFMT_ASCII, +int optInFormat = FFMT_AUTO, + optOutFormat = FFMT_ASCII, + optInSubFormat = IMGFMT_PNG, + optOutSubFormat = IMGFMT_PNG, optItemCount = -1, optScale = 2, optPlanedWidth = 1, + optForcedFormat = -1, optBPP = 4; int optInSkip = 0; BOOL optInMulticolor = FALSE, @@ -86,6 +135,7 @@ static DMOptArg optList[] = { { 0, '?', "help", "Show this help", OPT_NONE }, + {15, 'v', "verbose", "Increase verbosity", OPT_NONE }, { 3, 'o', "output", "Output filename", OPT_ARGREQ }, { 1, 'i', "informat", "Set input format ([s]prite, [c]har, [b]itmap, [i]mage)", OPT_ARGREQ }, { 2, 'm', "multicolor", "Input is multicolor", OPT_NONE }, @@ -95,9 +145,7 @@ { 6, 'c', "colormap", "Color mappings (see below for information)", OPT_ARGREQ }, { 7, 'n', "numitems", "How many 'items' to view (default: all)", OPT_ARGREQ }, { 9, 'S', "scale", "Scale output by x (image output only)", OPT_ARGREQ }, -#ifdef UNFINISHED {10, 'b', "bformat", "Force input bitmap format (see below)", OPT_ARGREQ }, -#endif {11, 'w', "width", "Item width (number of items per row, min 1)", OPT_ARGREQ }, {12, 'P', "paletted", "Use indexed/paletted output (png, pcx output only)", OPT_NONE }, {13, 'b', "bplanes", "Bits per pixel OR # of bitplanes (certain output formats)", OPT_ARGREQ }, @@ -114,27 +162,23 @@ dmPrintBanner(stdout, dmProgName, "[options] "); dmArgsPrintHelp(stdout, optList, optListN); - printf("\nAvailable output formats: "); - for (i = 0; i < noutFormatList; i++) + printf("\nAvailable output formats:\n"); + for (i = 0; i < nconvFormatList; i++) { - printf("%s", outFormatList[i]); - if (i < noutFormatList - 1) - printf(", "); - else - printf("\n"); + DMConvFormat *fmt = &convFormatList[i]; + printf("%3d | %-5s | %s\n", + i, fmt->fext, fmt->name); } -#ifdef UNFINISHED printf("\nAvailable bitmap formats:\n"); for (i = 0; i < ndmC64ImageFormats; i++) { - DM64ImageFormat *fmt = &dmC64ImageFormats[i]; + DMC64ImageFormat *fmt = &dmC64ImageFormats[i]; printf("%3d | %-5s | %-15s | %s\n", i, fmt->extension, dmC64ImageTypeNames[fmt->type], fmt->name); } -#endif printf( "\n" @@ -149,6 +193,37 @@ } +int dmGetConvFormat(int format, int subformat) +{ + int i; + for (i = 0; i < nconvFormatList; i++) + { + DMConvFormat *fmt = &convFormatList[i]; + if (fmt->format == format && + fmt->subformat == subformat) + return i; + } + return -1; +} + + +BOOL dmGetFormatByExt(const char *fext, int *format, int *subformat) +{ + int i; + for (i = 0; i < nconvFormatList; i++) + { + DMConvFormat *fmt = &convFormatList[i]; + if (strcasecmp(fext, fmt->fext) == 0) + { + *format = fmt->format; + *subformat = fmt->subformat; + return TRUE; + } + } + return FALSE; +} + + BOOL argHandleOpt(const int optN, char *optArg, char *currArg) { switch (optN) @@ -158,20 +233,24 @@ exit(0); break; + case 15: + dmVerbosity++; + break; + case 1: switch (tolower(optArg[0])) { case 's': - optInFormat = INFMT_SPRITE; + optInFormat = FFMT_SPRITE; break; case 'c': - optInFormat = INFMT_CHAR; + optInFormat = FFMT_CHAR; break; case 'b': - optInFormat = INFMT_BITMAP; + optInFormat = FFMT_BITMAP; break; case 'i': - optInFormat = INFMT_IMAGE; + optInFormat = FFMT_IMAGE; break; default: dmError("Invalid input format '%s'.\n", optArg); @@ -196,22 +275,10 @@ break; case 5: + if (!dmGetFormatByExt(optArg, &optOutFormat, &optOutSubFormat)) { - int i, format = -1; - for (i = 0; i < noutFormatList; i++) - if (strcasecmp(optArg, outFormatList[i]) == 0) - { - format = i; - break; - } - - if (format < 0) - { - dmError("Invalid output format '%s'.\n", optArg); - return FALSE; - } - - optOutFormat = format; + dmError("Invalid output format '%s'.\n", optArg); + return FALSE; } break; @@ -337,11 +404,11 @@ char ch; switch (format) { - case OUTFMT_ASCII: + case FFMT_ASCII: ch = dmASCIIPalette[val]; fprintf(out, "%c%c", ch, ch); break; - case OUTFMT_ANSI: + case FFMT_ANSI: fprintf(out, "%c[0;%d;%dm##%c[0m", 0x1b, 1, @@ -359,11 +426,11 @@ char ch; switch (format) { - case OUTFMT_ASCII: + case FFMT_ASCII: ch = val ? '#' : '.'; fputc(ch, out); break; - case OUTFMT_ANSI: + case FFMT_ANSI: fprintf(out, "%c[0;%d;%dm %c[0m", 0x1b, 1, @@ -633,7 +700,7 @@ } -#ifdef HAVE_LIBPNG +#ifdef DM_USE_LIBPNG static BOOL dmWritePNGRow(void *cbdata, Uint8 *row, size_t len) { png_structp png_ptr = cbdata; @@ -912,10 +979,13 @@ hdr.xmax = hdr.hres - 1; hdr.ymax = hdr.vres - 1; hdr.nplanes = dmImageGetBytesPerPixel(pcx.format); - hdr.bpl = (((img->width * scale) / 2) + 1) * 2; hdr.palinfo = 1; + res = (img->width * scale); + hdr.bpl = res / 2; + if (res % 2) hdr.bpl++; + hdr.bpl *= 2; - dmMsg(1, "PCX: paletted=%d, nplanes=%d, bpp=%d, bpl=%d\n", + dmMsg(2, "PCX: paletted=%d, nplanes=%d, bpp=%d, bpl=%d\n", paletted, hdr.nplanes, hdr.bpp, hdr.bpl); pcx.bufLen = hdr.bpl * 4; @@ -976,6 +1046,7 @@ { int i; dm_fwrite_byte(pcx.fp, 0x0C); + dmMsg(2, "PCX: Writing palette of %d active entries.\n", img->ncolors); for (i = 0; i < img->ncolors; i++) { @@ -1251,28 +1322,24 @@ } -int fmtProbePNGImageFILE(FILE *fp) +static int fmtProbePNG(const Uint8 *buf, const size_t len) { - Uint8 buf[6]; -// if (!dm_fread_str(fp, + if (len > 64 && buf[0] == 0x89 && + buf[1] == 'P' && buf[2] == 'N' && buf[3] == 'G' && + buf[4] == 0x0d && buf[5] == 0x0a) + return DM_PROBE_SCORE_GOOD; + return DM_PROBE_SCORE_FALSE; } -int fmtProbePCXImageFILE(FILE *fp) +static int fmtProbePCX(const Uint8 *buf, const size_t len) { - DMPCXHeader hdr; - - if (!dm_fread_byte(fp, &hdr.manufacturer) || - !dm_fread_byte(fp, &hdr.version) || - !dm_fread_byte(fp, &hdr.encoding) || - !dm_fread_byte(fp, &hdr.bpp)) - return DM_PROBE_SCORE_FALSE; - - if (hdr.manufacturer == 10 && - hdr.version == 5 && - hdr.encoding == 1 && - hdr.bpp == 8) + if (len > 128 + 64 && + buf[0] == 10 && + buf[1] == 5 && + buf[2] == 1 && + buf[3] == 8) return DM_PROBE_SCORE_GOOD; return DM_PROBE_SCORE_FALSE; @@ -1321,22 +1388,33 @@ #endif -int dmWriteImage(char *filename, DMImage *image) +int dmWriteImage(char *filename, DMImage *image, BOOL info) { - switch (optOutFormat) + if (info) { -#ifdef HAVE_LIBPNG - case OUTFMT_PNG: + dmMsg(1, "Outputting %s image %d x %d -> %d x %d [%d]\n", + imageFormatList[optOutSubFormat], + image->width, image->height, + image->width * optScale, image->height * optScale, optScale); + } + + switch (optOutSubFormat) + { +#ifdef DM_USE_LIBPNG + case IMGFMT_PNG: + if (info) dmMsg(2, "%s output.\n", optPaletted ? "Indexed 8bpp" : "32bit RGBA"); return dmWritePNGImage(filename, image, optScale, optPaletted ? DM_IFMT_PALETTE : DM_IFMT_RGBA); #endif - case OUTFMT_PPM: + case IMGFMT_PPM: + if (info) dmMsg(2, "24bit RGB output.\n"); return dmWritePPMImage(filename, image, optScale); - case OUTFMT_PCX: + case IMGFMT_PCX: + if (info) dmMsg(2, "%s output.\n", optPaletted ? "Indexed 8bpp" : "24bit RGB"); return dmWritePCXImage(filename, image, optScale, optPaletted); - case OUTFMT_ARAW: + case IMGFMT_ARAW: { int res; char *palFilename = dm_strdup_printf("%s.pal", filename); @@ -1345,6 +1423,7 @@ if (res != DMERR_OK) return res; + if (info) dmMsg(2, "%d bitplanes, %s interleave.\n", optBPP, optInterleave ? "with" : "without"); return dmWriteIFFMasterRAWImage(filename, image, optScale, optBPP, optInterleave); } @@ -1362,18 +1441,20 @@ switch (optInFormat) { - case INFMT_CHAR: + case FFMT_CHAR: bufSize = C64_CHR_SIZE; outWidth = C64_CHR_WIDTH; outWidthPX = C64_CHR_WIDTH_PX; outHeight = C64_CHR_HEIGHT; break; - case INFMT_SPRITE: + + case FFMT_SPRITE: bufSize = C64_SPR_SIZE; outWidth = C64_SPR_WIDTH; outWidthPX = C64_SPR_WIDTH_PX; outHeight = C64_SPR_HEIGHT; break; + default: dmError("Invalid input format %d, internal error.\n", optInFormat); return -1; @@ -1389,7 +1470,7 @@ dataOffs = optInSkip; itemCount = 0; - if (optOutFormat == OUTFMT_ANSI || optOutFormat == OUTFMT_ASCII) + if (optOutFormat == FFMT_ANSI || optOutFormat == FFMT_ASCII) { BOOL error = FALSE; FILE *outFile; @@ -1420,10 +1501,10 @@ switch (optInFormat) { - case INFMT_CHAR: + case FFMT_CHAR: dmDumpCharASCII(outFile, bufData, &dataOffs, optOutFormat, optInMulticolor); break; - case INFMT_SPRITE: + case FFMT_SPRITE: dmDumpSpriteASCII(outFile, bufData, &dataOffs, optOutFormat, optInMulticolor); break; } @@ -1433,7 +1514,7 @@ fclose(outFile); } else - if (optOutFormat == OUTFMT_PNG || optOutFormat == OUTFMT_PPM || optOutFormat == OUTFMT_PCX) + if (optOutFormat == IMGFMT_PNG || optOutFormat == IMGFMT_PPM || optOutFormat == IMGFMT_PCX) { DMImage *outImage = NULL; char *outFilename = NULL; @@ -1468,9 +1549,6 @@ outIHeight++; outImage = dmImageAlloc(outWidthPX * outIWidth, outIHeight * outHeight); - dmMsg(1, "Outputting image %d x %d -> %d x %d.\n", - outImage->width, outImage->height, - outImage->width * optScale, outImage->height * optScale); } outImage->constpal = TRUE; @@ -1498,14 +1576,14 @@ if (optSequential) { - outFilename = dm_strdup_printf("%s%04d.%s", optOutFilename, itemCount, outFormatList[optOutFormat]); + outFilename = dm_strdup_printf("%s%04d.%s", optOutFilename, itemCount, convFormatList[optOutFormat].fext); if (outFilename == NULL) { dmError("Could not allocate memory for filename template?\n"); goto error; } - dmWriteImage(outFilename, outImage); + dmWriteImage(outFilename, outImage, FALSE); dmFree(outFilename); } else @@ -1522,7 +1600,7 @@ if (!optSequential) { - dmWriteImage(optOutFilename, outImage); + dmWriteImage(optOutFilename, outImage, TRUE); } dmImageFree(outImage); @@ -1540,7 +1618,11 @@ int main(int argc, char *argv[]) { FILE *inFile; - int i, optInImageFormat; + DMC64ImageFormat *cfmt; + DMC64Image cimage; + Uint8 *dataBuf = NULL; + size_t dataSize; + int i; // Default colors for (i = 0; i < C64_MAX_COLORS; i++) @@ -1553,36 +1635,30 @@ argHandleOpt, argHandleFile, TRUE)) exit(1); -#ifndef HAVE_LIBPNG - if (optOutFormat == OUTFMT_PNG) +#ifndef DM_USE_LIBPNG + if (optOutFormat == IMGFMT_PNG) { dmError("PNG output format support not compiled in, sorry.\n"); - exit(3); + goto error; } #endif // Determine input format, if not specified' - if (optInFormat == INFMT_AUTO && optInFilename != NULL) + if (optInFormat == FFMT_AUTO && optInFilename != NULL) { char *dext = strrchr(optInFilename, '.'); if (dext) { - dext++; - if (!strcasecmp(dext, "fnt") || !strcasecmp(dext, "chr")) - optInFormat = INFMT_CHAR; - else if (!strcasecmp(dext, "spr")) - optInFormat = INFMT_SPRITE; - else if (!strcasecmp(dext, "png") || !strcasecmp(dext, "pcx")) - optInFormat = INFMT_IMAGE; + dmGetFormatByExt(dext + 1, &optInFormat, &optInSubFormat); } } if (optInFilename == NULL) { - if (optInFormat == INFMT_AUTO) + if (optInFormat == FFMT_AUTO) { dmError("Standard input cannot be used without specifying input format.\n"); - exit(3); + goto error; } inFile = stdin; } @@ -1592,49 +1668,53 @@ int res = errno; dmError("Error opening input file '%s'. (%s)\n", optInFilename, strerror(res)); - exit(3); + goto error; } - if (optInFormat == INFMT_AUTO) + if (dmReadDataFile(inFile, NULL, &dataBuf, &dataSize) != 0) + goto error; + + if (optInFormat == FFMT_AUTO || optInFormat == FFMT_BITMAP) { - // Skip, if needed - if (fseek(inFile, optInSkip, SEEK_SET) != 0) + // Probe for format + DMC64ImageFormat *forced = NULL; + int res; + + if (optForcedFormat >= 0) { - int res = errno; - dmError("Could not seek to file position %d (0x%x): %s\n", - optInSkip, optInSkip, strerror(res)); - exit(3); + forced = &dmC64ImageFormats[optForcedFormat]; + dmMsg(0,"Forced %s format image, type %d, %s\n", + forced->name, forced->type, forced->extension); } -#if 0 - if (optInFormat == INFMT_AUTO) - { - int ret = dmC64ProbeGeneric - } -#endif - if (optInFormat == INFMT_AUTO || optInFormat == INFMT_IMAGE) + res = dmC64DecodeBMP(&cimage, dataBuf, dataSize, optInSkip, optInSkip + 2, &cfmt, forced); + if (forced == NULL && cfmt != NULL) { - if (fmtProbePNGImageFILE(inFile)) - { - optInFormat = INFMT_IMAGE; - optInImageFormat = OUTFMT_PNG; - } - else - if (fmtProbePCXImageFILE(inFile)) - { - optInFormat = INFMT_IMAGE; - optInImageFormat = OUTFMT_PCX; - } - else - if (optInFormat == INFMT_IMAGE) - { - dmError("Unsupported image input format.\n"); - exit(4); - } + dmMsg(1,"Probed %s format image, type %d, %s\n", + cfmt->name, cfmt->type, cfmt->extension); + } + + if (res == 0) + optInFormat = FFMT_BITMAP; + } + + if (optInFormat == FFMT_AUTO) + { + // XXX, needs a proper probe loop + if (fmtProbePNG(dataBuf + optInSkip, dataSize - optInSkip)) + { + optInFormat = FFMT_IMAGE; + optInSubFormat = IMGFMT_PNG; + } + else + if (fmtProbePCX(dataBuf + optInSkip, dataSize - optInSkip)) + { + optInFormat = FFMT_IMAGE; + optInSubFormat = IMGFMT_PCX; } } - if (optInFormat == INFMT_AUTO) + if (optInFormat == FFMT_AUTO) { dmError("No input format specified, and could not be determined automatically.\n"); exit(1); @@ -1646,61 +1726,119 @@ int res = errno; dmError("Could not seek to file position %d (0x%x): %s\n", optInSkip, optInSkip, strerror(res)); - exit(3); + goto error; + } + + int inFormat = dmGetConvFormat(optInFormat, optInSubFormat), + outFormat = dmGetConvFormat(optOutFormat, optOutSubFormat); + + if (inFormat != -1 && outFormat != -1) + { + char *inFmtName = convFormatList[inFormat].name, + *inFmtExt = convFormatList[inFormat].fext, + *outFmtName = convFormatList[outFormat].name, + *outFmtExt = convFormatList[outFormat].fext; + + if (optInFormat == FFMT_BITMAP) + inFmtExt = cfmt->name; + + dmMsg(1, "Attempting conversion %s (%s) -> %s (%s)\n", + inFmtName, inFmtExt, outFmtName, outFmtExt); } switch (optInFormat) { - case INFMT_SPRITE: - case INFMT_CHAR: + case FFMT_SPRITE: + case FFMT_CHAR: dmDumpSpritesAndChars(inFile); break; - case INFMT_BITMAP: - case INFMT_IMAGE: + case FFMT_BITMAP: { - DMImage *img; - int res; + DMImage *img = NULL; + int res = DMERR_OK; if (optOutFilename == NULL) { dmError("Output filename not set, required for image formats.\n"); - exit(3); + goto error; + } + + switch (optOutFormat) + { + case FFMT_IMAGE: + if ((img = dmImageAlloc(C64_SCR_WIDTH, C64_SCR_HEIGHT)) == NULL) + { + dmError("Could not allocate output image surface %d x %d.\n", + C64_SCR_WIDTH, C64_SCR_HEIGHT); + goto error; + } + + img->pal = (DMColor *) &dmC64Palette; + img->ncolors = C64_NCOLORS; + img->constpal = TRUE; + + if (cfmt->convert != NULL) + res = cfmt->convert(img, &cimage); + else + res = dmC64ConvertGenericBMP2Image(img, &cimage); + + if (res != DMERR_OK || img == NULL) + { + dmError("Error in bitmap to image conversion.\n"); + goto error; + } + + res = dmWriteImage(optOutFilename, img, TRUE); + break; + + default: + dmError("Unsupported output format for bitmap/image conversion.\n"); + break; + } + + dmImageFree(img); + } + break; + + case FFMT_IMAGE: + { + DMImage *img; + int res = DMERR_OK; + + if (optOutFilename == NULL) + { + dmError("Output filename not set, required for image formats.\n"); + goto error; } // Read input - switch (optInImageFormat) + switch (optInSubFormat) { - case OUTFMT_PCX: - res = dmReadPCXImageFILE(inFile, &img); - break; -/* - case OUTFMT_PNG: - res = dmReadPNGImageFILE(inFile, &img); - break; -*/ + case IMGFMT_PCX: res = dmReadPCXImageFILE(inFile, &img); break; +// case IMGFMT_PNG: res = dmReadPNGImageFILE(inFile, &img); break; +// case IMGFMT_ARAW: res = dmReadARAWImageFILE(inFile, &img, optBPP); break; default: dmError("Unsupported input image format for bitmap/image conversion.\n"); break; } - if (res != DMERR_OK) + if (res != DMERR_OK || img == NULL) break; switch (optOutFormat) { - case OUTFMT_PCX: - case OUTFMT_PPM: - case OUTFMT_PNG: - case OUTFMT_ARAW: - res = dmWriteImage(optOutFilename, img); + case FFMT_IMAGE: + res = dmWriteImage(optOutFilename, img, TRUE); break; default: dmError("Unsupported output format for bitmap/image conversion.\n"); break; } + + dmImageFree(img); } break; } @@ -1709,4 +1847,8 @@ exit(0); return 0; + +error: + return -3; + exit(3); } diff -r b6a1dc3bd2c3 -r 936bc27a79d6 lib64gfx.c --- a/lib64gfx.c Sat Nov 03 07:52:26 2012 +0200 +++ b/lib64gfx.c Sat Nov 03 07:53:38 2012 +0200 @@ -245,6 +245,8 @@ static BOOL fmtDrazLaceSetLaceType(DMC64Image *img, const struct _DMDecodeOp *op, const Uint8 *buf, const size_t len) { + (void) len; + img->laceType = buf[op->offs] ? DM_C64ILACE_RES : DM_C64ILACE_COLOR; img->laceBank2 = 0; return TRUE; @@ -324,6 +326,9 @@ static BOOL fmtTruePaintSetLaceType(DMC64Image *img, const struct _DMDecodeOp *op, const Uint8 *buf, const size_t len) { + (void) op; + (void) buf; + (void) len; img->laceType = DM_C64ILACE_RES; img->laceBank2 = 1; return TRUE; @@ -428,10 +433,9 @@ const int ndmC64ImageFormats = sizeof(dmC64ImageFormats) / sizeof(dmC64ImageFormats[0]); -int dmC64ProbeGeneric(const Uint8 *buf, const size_t len, - DMC64ImageFormat **pfmt) +int dmC64ProbeGeneric(const Uint8 *buf, const size_t len, DMC64ImageFormat **pfmt) { - int i, scoreMax = 0, scoreIndex = -1; + int i, scoreMax = DM_PROBE_SCORE_FALSE, scoreIndex = -1; for (i = 0; i < ndmC64ImageFormats; i++) { @@ -450,7 +454,7 @@ return scoreMax; } else - return 0; + return DM_PROBE_SCORE_FALSE; } @@ -667,61 +671,99 @@ #define BUF_SIZE_INITIAL (16*1024) -#define BUF_SIZE_GROW (2*1024) +#define BUF_SIZE_GROW (8*1024) -int dmReadDataFile(const char *filename, Uint8 **pbuf, size_t *pbufSize) +int dmReadDataFile(FILE *inFile, const char *filename, Uint8 **pbuf, size_t *pbufSize) { FILE *f; + int res = DMERR_OK; Uint8 *dataBuf = NULL, *dataPtr; - size_t bufSize, readSize, dataSize; + size_t readSize, dataSize, dataRead; - if (filename == NULL) - f = stdin; + if (inFile != NULL) + f = inFile; else - if ((f = fopen(filename, "rb")) == NULL) + if (filename != NULL) { - int err = errno; - dmError("Could not open input file '%s': %d, %s\n", - filename, err, strerror(err)); - return -1; + if ((f = fopen(filename, "rb")) == NULL) + { + dmError("Could not open '%s' for reading.\n", filename); + return DMERR_FOPEN; + } + } + else + { + dmError("NULL filename and stream pointers.\n"); + return DMERR_NULLPTR; } - readSize = bufSize = BUF_SIZE_INITIAL; - if ((dataBuf = dmMalloc(bufSize)) == NULL) + // Allocate initial data buffer + readSize = dataSize = BUF_SIZE_INITIAL; + if ((dataBuf = dmMalloc(dataSize)) == NULL) { - fclose(f); - dmError("Error allocating memory for data, %d bytes.\n", bufSize); - return -4; + dmError("Error allocating memory for data, %d bytes.\n", dataSize); + res = DMERR_MALLOC; + goto error; } dataPtr = dataBuf; - dataSize = 0; + dataRead = 0; + dataPtr += read; + dataRead += read; while (!feof(f) && !ferror(f)) { size_t read = fread(dataPtr, 1, readSize, f); - dataSize += read; - dataPtr += read; - - if (read == readSize && !feof(f)) + if (dataRead >= dataSize) { readSize = BUF_SIZE_GROW; - bufSize += BUF_SIZE_GROW; - if ((dataBuf = dmRealloc(dataBuf, bufSize)) == NULL) + dataSize += BUF_SIZE_GROW; + if ((dataBuf = dmRealloc(dataBuf, dataSize)) == NULL) { - dmError("Error reallocating memory for data, %d bytes.\n", bufSize); - return -4; + dmError("Error reallocating memory for data, %d bytes.\n", dataSize); + res = DMERR_MALLOC; + goto error; } } else break; } - fclose(f); - + *pbufSize = dataRead; *pbuf = dataBuf; - *pbufSize = dataSize; + +error: + if (f != inFile) + fclose(f); - return 0; + return res; } + + +int dmC64DecodeBMP(DMC64Image *img, const Uint8 *buf, const size_t len, + const size_t probeOffs, const size_t loadOffs, + DMC64ImageFormat **fmt, DMC64ImageFormat *forced) +{ + // Check for forced format + if (forced != NULL) + *fmt = forced; + else + { + // Nope, perform a generic probe + if (probeOffs >= len) + return -200; + + if (dmC64ProbeGeneric(buf + probeOffs, len - probeOffs, fmt) == DM_PROBE_SCORE_FALSE) + return -201; + } + + if (loadOffs >= len) + return -203; + + // Decode the bitmap to memory layout + if ((*fmt)->decode != NULL) + return (*fmt)->decode(img, buf + loadOffs, len - loadOffs, *fmt); + else + return dmC64DecodeGenericBMP(img, buf + loadOffs, len - loadOffs, *fmt); +} diff -r b6a1dc3bd2c3 -r 936bc27a79d6 lib64gfx.h --- a/lib64gfx.h Sat Nov 03 07:52:26 2012 +0200 +++ b/lib64gfx.h Sat Nov 03 07:53:38 2012 +0200 @@ -180,6 +180,8 @@ int dmC64ProbeGeneric(const Uint8 *buf, const size_t len, DMC64ImageFormat **fmt); int dmC64DecodeGenericBMP(DMC64Image *img, const Uint8 *buf, const size_t len, const DMC64ImageFormat *fmt); int dmC64ConvertGenericBMP2Image(DMImage *screen, const DMC64Image *img); -int dmReadDataFile(const char *filename, Uint8 **buf, size_t *size); +int dmC64DecodeBMP(DMC64Image *img, const Uint8 *buf, const size_t len, const size_t probeOffs, const size_t loadOffs, DMC64ImageFormat **fmt, DMC64ImageFormat *forced); + +int dmReadDataFile(FILE *inFile, const char *filename, Uint8 **buf, size_t *size); #endif // LIB64GFX_H diff -r b6a1dc3bd2c3 -r 936bc27a79d6 view64.c --- a/view64.c Sat Nov 03 07:52:26 2012 +0200 +++ b/view64.c Sat Nov 03 07:53:38 2012 +0200 @@ -155,12 +155,12 @@ SDL_Surface *screen = NULL, *surf = NULL; DMImage bmap; BOOL initSDL = FALSE, exitFlag, needRedraw; - DMC64ImageFormat *fmt; + DMC64ImageFormat *fmt, *forced; DMC64Image image; char *windowTitle; Uint8 *dataBuf = NULL; size_t dataSize; - int i, ret; + int ret; dmSetScaleFactor(2.0); @@ -175,71 +175,42 @@ if (optFilename == NULL) { dmError("No input file specified, perhaps you need some --help\n"); - goto error_exit; + goto error; } - if (dmReadDataFile(optFilename, &dataBuf, &dataSize) != 0) - goto error_exit; + if ((ret = dmReadDataFile(NULL, optFilename, &dataBuf, &dataSize)) != DMERR_OK) + goto error; + + dmMsg(1, "Read %d bytes of input.\n", dataSize); // Probe for format if (optForcedFormat >= 0) { - fmt = &dmC64ImageFormats[optForcedFormat]; - dmMsg(0,"Forced %s format image, type %d, %s\n", fmt->name, fmt->type, fmt->extension); - - if (fmt->decode != NULL) - ret = fmt->decode(&image, dataBuf + 2, dataSize - 2, fmt); - else - ret = dmC64DecodeGenericBMP(&image, dataBuf + 2, dataSize - 2, fmt); - - if (ret < 0) - { - dmError("Error decoding image format.\n"); - return -1; - } + forced = &dmC64ImageFormats[optForcedFormat]; + dmMsg(0,"Forced %s format image, type %d, %s\n", forced->name, forced->type, forced->extension); } else - { - BOOL found = FALSE; - for (i = 0; i < ndmC64ImageFormats; i++) - { - fmt = &dmC64ImageFormats[i]; - ret = fmt->probe(dataBuf, dataSize); - if (ret > 0) - { - dmMsg(0,"Probed %s format image, type %d, %s\n", fmt->name, fmt->type, fmt->extension); - if (fmt->decode != NULL) - ret = fmt->decode(&image, dataBuf + 2, dataSize - 2, fmt); - else - ret = dmC64DecodeGenericBMP(&image, dataBuf + 2, dataSize - 2, fmt); + forced = NULL; - if (ret < 0) - { - dmError("Error decoding image format.\n"); - return -1; - } - - found = TRUE; - break; - } - else - if (ret < 0) - { - dmError("Error in probing.\n"); - } - } - if (!found) - { - dmError("Probing could not find any matching image format. Perhaps try forcing a format via -f\n"); - return -2; - } + ret = dmC64DecodeBMP(&image, dataBuf, dataSize, 0, 2, &fmt, forced); + if (forced == NULL && fmt != NULL) + { + dmMsg(0,"Probed %s format image, type %d, %s\n", + fmt->name, fmt->type, fmt->extension); } + if (ret < 0) + { + dmError("Probing could not find any matching image format (%d). Perhaps try forcing a format via -f\n", ret); + return -1; + } + + // Initialize libSDL if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0) { dmError("Could not initialize SDL: %s\n", SDL_GetError()); - goto error_exit; + goto error; } initSDL = TRUE; @@ -249,7 +220,7 @@ if (screen == NULL) { dmError("Can't SDL_SetVideoMode(): %s\n", SDL_GetError()); - goto error_exit; + goto error; } // Create surface (we are lazy and ugly) @@ -302,7 +273,7 @@ optScrHeight = event.resize.h; if (!dmInitializeVideo(&screen)) - goto error_exit; + goto error; needRedraw = TRUE; break; @@ -320,7 +291,7 @@ if (SDL_MUSTLOCK(screen) != 0 && SDL_LockSurface(screen) != 0) { dmError("Can't lock surface.\n"); - goto error_exit; + goto error; } dmScaledBlitSurface8to8(surf, 0, 0, screen->w, screen->h, screen); @@ -337,7 +308,7 @@ } -error_exit: +error: if (screen) SDL_FreeSurface(screen);