view tools/lib64util.c @ 2210:fa5e74384d87

Check for non-existing palette when reading palette from image file.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 14 Jun 2019 05:35:20 +0300
parents 90ec1ec89c56
children 5db6e0b63b35
line wrap: on
line source

/*
 * Common utility functions for gfxconv and 64vw
 * Programmed and designed by Matti 'ccr' Hamalainen
 * (C) Copyright 2019 Tecnic Software productions (TNSP)
 *
 * Please read file 'COPYING' for information on license and distribution.
 */
#include "lib64util.h"
#include "dmfile.h"


char * dmC64GetImageTypeString(char *buf, const size_t len, const int type, const BOOL lng)
{
    static const char *fmtModesShort[] = { "*", "HiR", "MC", "ECM" };
    static const char *fmtModesLong[] = { "*", "HiRes", "MultiColor", "Extended Color Mode" };
    const char *fmtStr;
    size_t nfmt = type & D64_FMT_MODE_MASK;

    if (nfmt < sizeof(fmtModesShort) / sizeof(fmtModesShort[0]))
        fmtStr = lng ? fmtModesLong[nfmt] : fmtModesShort[nfmt];
    else
        fmtStr = lng ? "ERROR" : "ERR";

    snprintf(buf, len,
        "%s %s%s%s",
        fmtStr,
        (type & D64_FMT_ILACE) ? (lng ? "Interlaced " : "ILace ") : "",
        (type & D64_FMT_FLI)   ? "FLI " : "",
        (type & D64_FMT_CHAR)  ? "CHAR" : ""
        );

    return buf;
}


void dmC64ImageDump(FILE *fh, const DMC64Image *img, const DMC64ImageFormat *fmt, const char *indent)
{
    char typeStr[64];

    if (fmt != NULL)
    {
        fprintf(fh,
            "%sFormat              : %s [%s]\n",
            indent, fmt->name, fmt->fext);
    }

    if (img != NULL)
    {
        dmC64GetImageTypeString(typeStr, sizeof(typeStr), img->fmt->type, TRUE);

        fprintf(fh,
            "%sType                : %s\n"
            "%sInternal blocks     : %d\n",
            indent, typeStr,
            indent, img->nblocks);

        if (img->fmt->type & D64_FMT_ILACE)
        {
            char *tmps;
            switch (img->laceType)
            {
                case D64_ILACE_COLOR: tmps = "color"; break;
                case D64_ILACE_RES: tmps = "resolution"; break;
                default: tmps = "ERROR"; break;
            }
            fprintf(fh,
                "%sInterlace type      : %s\n",
                indent, tmps);
        }

        fprintf(fh,
            "%sWidth x Height      : %d x %d\n"
            "%sCHwidth x CHheight  : %d x %d\n"
            "%sd020 / border       : %d ($%02x)\n"
            "%sd021 / background   : %d ($%02x)\n",
            indent, img->fmt->width, img->fmt->height,
            indent, img->fmt->chWidth, img->fmt->chHeight,
            indent, img->d020, img->d020,
            indent, img->bgcolor, img->bgcolor);
    }
    else
    if (fmt != NULL)
    {
        dmC64GetImageTypeString(typeStr, sizeof(typeStr), fmt->format->type, TRUE);
        fprintf(fh,
            "%sType                : %s\n"
            "%sWidth x Height      : %d x %d\n"
            "%sCHwidth x CHheight  : %d x %d\n",
            indent, typeStr,
            indent, fmt->format->width, fmt->format->height,
            indent, fmt->format->chWidth, fmt->format->chHeight);
    }
}


void argShowC64PaletteHelp()
{
    fprintf(stdout, "\nAvailable C64 palettes:\n");
    for (int n = 0; n < ndmC64DefaultPalettes; n++)
    {
        DMC64Palette *pal = &dmC64DefaultPalettes[n];
        fprintf(stdout,
            "%-10s | %s\n",
            pal->name, pal->desc);
    }
    fprintf(stdout, "\n");
}


BOOL argHandleC64PaletteOption(char *optArg, DMC64Palette **ppal, char **palFile)
{
    if (strcasecmp(optArg, "help") == 0 ||
        strcasecmp(optArg, "list") == 0)
    {
        argShowC64PaletteHelp();
        return FALSE;
    }

    for (int n = 0; n < ndmC64DefaultPalettes; n++)
    {
        DMC64Palette *pal = &dmC64DefaultPalettes[n];
        if (strcasecmp(pal->name, optArg) == 0)
        {
            *ppal = pal;
            return TRUE;
        }
    }

    *palFile = optArg;
    return TRUE;
}


int dmHandleExternalPalette(const char *filename, DMPalette **ppal)
{
    DMResource *fp = NULL;
    const DMImageFormat *ifmt = NULL;
    const DMPaletteFormat *pfmt = NULL;
    DMImage *inImage = NULL;
    Uint8 *dataBuf = NULL;
    size_t dataSize;
    int index, res;

    dmMsg(1, "Probing file '%s' for palette data.\n", filename);

    if ((res = dmReadDataFile(NULL, filename, &dataBuf, &dataSize)) != DMERR_OK)
    {
        dmErrorMsg("No such palette '%s', and no such file found (%s).\n",
            filename, dmErrorStr(res));
        goto done;
    }

    if ((res = dmf_open_memio(NULL, filename, dataBuf, dataSize, &fp)) != DMERR_OK)
    {
        dmErrorMsg("Could not create MemIO handle for input.\n");
        goto done;
    }

    if (dmImageProbeGeneric(dataBuf, dataSize, &ifmt, &index) > 0 &&
        ifmt->read != NULL)
    {
        dmMsg(1, "Probed image format %s (%s)\n",
            ifmt->name, ifmt->fext);

        res = ifmt->read(fp, &inImage);
        if (res != DMERR_OK)
        {
            dmErrorMsg("Could not read image file: %s\n",
                dmErrorStr(res));
            goto done;
        }

        if (inImage->pal != NULL)
            res = dmPaletteCopy(ppal, inImage->pal);
        else
        {
            dmErrorMsg("Image file does not have a palette.\n");
            res = DMERR_NULLPTR;
        }
    }
    else
    if (dmPaletteProbeGeneric(dataBuf, dataSize, &pfmt, &index) > 0 &&
        pfmt->read != NULL)
    {
        dmMsg(1, "Probed palette format %s (%s)\n",
            pfmt->name, pfmt->fext);

        res = pfmt->read(fp, ppal);
    }
    else
    {
        res = DMERR_NOT_SUPPORTED;
        dmErrorMsg("Not an internal palette or recognized palette file '%s'.\n",
            filename);
    }

done:
    dmf_close(fp);
    dmImageFree(inImage);
    dmFree(dataBuf);

    return res;
}