# HG changeset patch # User Matti Hamalainen # Date 1352750657 -7200 # Node ID fca3c240ccacb59f924e23d8803864432e0d8c0f # Parent 49f0ce2cc347ec22d040b3794ac94042c377c43b Implement simplistic image input to char/sprite splitter conversion. diff -r 49f0ce2cc347 -r fca3c240ccac gfxconv.c --- a/gfxconv.c Mon Nov 12 22:02:47 2012 +0200 +++ b/gfxconv.c Mon Nov 12 22:04:17 2012 +0200 @@ -84,11 +84,11 @@ }, { - "C64 character/font data", "chr", TRUE, FALSE, + "C64 character/font data", "chr", TRUE, TRUE, FFMT_CHAR , 0 }, { - "C64 sprite data", "spr", TRUE, FALSE, + "C64 sprite data", "spr", TRUE, TRUE, FFMT_SPRITE , 0 }, }; @@ -138,7 +138,7 @@ { 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 }, + { 2, 'm', "multicolor", "Input is multicolor / output in multicolor", OPT_NONE }, { 4, 's', "skip", "Skip bytes in input", OPT_ARGREQ }, { 5, 'f', "format", "Output format (see --formats)", OPT_ARGREQ }, { 17, 'F', "formats", "Output format (see list below)", OPT_NONE }, @@ -1014,6 +1014,168 @@ } +Uint8 dmConvertByte(const Uint8 *sp, const BOOL multicolor) +{ + Uint8 byte = 0; + int xc; + + if (multicolor) + { + for (xc = 0; xc < 8 / 2; xc++) + { + Uint8 pixel = sp[xc * 2] & 3; + byte |= pixel << (6 - (xc * 2)); + } + } + else + { + for (xc = 0; xc < 8; xc++) + { + Uint8 pixel = sp[xc] == 0 ? 0 : 1; + byte |= pixel << (7 - xc); + } + } + + return byte; +} + + +BOOL dmConvertImage2Char(Uint8 *buf, const DMImage *image, + const int xoffs, const int yoffs, const BOOL multicolor) +{ + int yc; + + if (xoffs < 0 || yoffs < 0 || + xoffs + C64_CHR_WIDTH_PX > image->width || + yoffs + C64_CHR_HEIGHT > image->height) + return FALSE; + + for (yc = 0; yc < C64_CHR_HEIGHT; yc++) + { + const Uint8 *sp = image->data + ((yc + yoffs) * image->pitch) + xoffs; + buf[yc] = dmConvertByte(sp, multicolor); + } + + return TRUE; +} + + +BOOL dmConvertImage2Sprite(Uint8 *buf, const DMImage *image, + const int xoffs, const int yoffs, const BOOL multicolor) +{ + int yc, xc; + + if (xoffs < 0 || yoffs < 0 || + xoffs + C64_SPR_WIDTH_PX > image->width || + yoffs + C64_SPR_HEIGHT > image->height) + return FALSE; + + for (yc = 0; yc < C64_SPR_HEIGHT; yc++) + { + for (xc = 0; xc < C64_SPR_WIDTH_PX / C64_SPR_WIDTH; xc++) + { + const Uint8 *sp = image->data + ((yc + yoffs) * image->pitch) + (xc * 8) + xoffs; + buf[(yc * C64_SPR_WIDTH) + xc] = dmConvertByte(sp, multicolor); + } + } + + return TRUE; +} + + +int dmWriteSpritesAndChars(const char *filename, DMImage *image, int outFormat, BOOL multicolor) +{ + int outBlockW, outBlockH, bx, by; + FILE *outFile = NULL; + Uint8 *buf = NULL; + char *outType; + size_t bufSize; + + switch (outFormat) + { + case FFMT_CHAR: + bufSize = C64_CHR_SIZE; + outBlockW = image->width / C64_CHR_WIDTH_PX; + outBlockH = image->height / C64_CHR_HEIGHT; + outType = "char"; + break; + + case FFMT_SPRITE: + bufSize = C64_SPR_SIZE; + outBlockW = image->width / C64_SPR_WIDTH_PX; + outBlockH = image->height / C64_SPR_HEIGHT; + outType = "sprite"; + break; + + default: + dmError("Invalid output format %d, internal error.\n", outFormat); + goto error; + } + + if (outBlockW <= 0 || outBlockH <= 0) + { + dmError("Source image dimensions too small for conversion, block dimensions %d x %d.\n", + outBlockW, outBlockH); + goto error; + } + + if ((outFile = fopen(filename, "wb")) == NULL) + { + int err = dmGetErrno(); + dmError("Could not open '%s' for writing, %d: %s.\n", + filename, err, dmErrorStr(err)); + goto error; + } + + if ((buf = dmMalloc(bufSize)) == NULL) + { + dmError("Could not allocate %d bytes for conversion buffer.\n", + bufSize); + goto error; + } + + dmMsg(1, "Writing %d x %d = %d blocks of %s data...\n", + outBlockW, outBlockH, outBlockW * outBlockH, outType); + + for (by = 0; by < outBlockH; by++) + for (bx = 0; bx < outBlockW; bx++) + { + switch (outFormat) + { + case FFMT_CHAR: + if (!dmConvertImage2Char(buf, image, + bx * C64_CHR_WIDTH_PX, by * C64_CHR_HEIGHT, + multicolor)) + goto error; + break; + + case FFMT_SPRITE: + if (!dmConvertImage2Sprite(buf, image, + bx * C64_SPR_WIDTH_PX, by * C64_SPR_HEIGHT, + multicolor)) + goto error; + } + + if (!dm_fwrite_str(outFile, buf, bufSize)) + { + int err = dmGetErrno(); + dmError("Error writing data block %d,%d to '%s', %d: %s\n", + bx, by, filename, err, dmErrorStr(err)); + goto error; + } + } + + fclose(outFile); + dmFree(buf); + return 0; + +error: + if (outFile != NULL) + fclose(outFile); + dmFree(buf); + return -1; +} + int dmDumpSpritesAndChars(FILE *inFile) { int dataOffs, itemCount, outWidth, outWidthPX, outHeight; @@ -1407,6 +1569,11 @@ res = dmWriteImage(optOutFilename, outImage, &optSpec, optOutSubFormat, TRUE); break; + case FFMT_CHAR: + case FFMT_SPRITE: + res = dmWriteSpritesAndChars(optOutFilename, outImage, optOutFormat, optInMulticolor); + break; + default: dmError("Unsupported output format for bitmap/image conversion.\n"); break;