changeset 2208:90ec1ec89c56

Revamp the palette handling in lib64gfx somewhat, add helper functions to lib64util for handling external palette file options and add support for specifying one of the "internal" palettes or external (.act) palette file to gfxconv and 64vw.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 14 Jun 2019 05:01:12 +0300
parents 1ea48084055e
children 7a0af15fbe97
files tools/64vw.c tools/gfxconv.c tools/lib64fmts.c tools/lib64gfx.c tools/lib64gfx.h tools/lib64util.c tools/lib64util.h tools/libgfx.c
diffstat 8 files changed, 251 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/tools/64vw.c	Fri Jun 14 03:28:46 2019 +0300
+++ b/tools/64vw.c	Fri Jun 14 05:01:12 2019 +0300
@@ -8,6 +8,7 @@
 #include "dmlib.h"
 #include "dmargs.h"
 #include "dmfile.h"
+#include "libgfx.h"
 #include "lib64gfx.h"
 #include "lib64util.h"
 #include <SDL.h>
@@ -25,6 +26,8 @@
 size_t  noptFilenames1 = 0, noptFilenames2 = 0;
 char    **optFilenames = NULL;
 char    *optCharROMFilename = NULL;
+DMC64Palette *optC64Palette = NULL;
+char    *optC64PaletteFile = NULL;
 
 DMC64MemBlock setCharROM;
 
@@ -41,6 +44,7 @@
     { 7, 'l', "list",       "Output list of files that were recognized (implies -i)", OPT_NONE },
     { 8, 'P', "probe",      "Probe only (do not attempt to decode the image)", OPT_NONE },
     { 9,   0, "char-rom",   "Set character ROM file to be used.", OPT_ARGREQ },
+    {10, 'p', "palette" ,   "Set C64 palette to be used (see -p list).", OPT_ARGREQ },
 };
 
 const int optListN = sizeof(optList) / sizeof(optList[0]);
@@ -164,6 +168,9 @@
             optCharROMFilename = optArg;
             break;
 
+        case 10:
+            return argHandleC64PaletteOption(optArg, &optC64Palette, &optC64PaletteFile);
+
         default:
             dmErrorMsg("Unimplemented option argument '%s'.\n", currArg);
             return FALSE;
@@ -223,7 +230,7 @@
 {
     DMImage bmap;
     BOOL charDataSet;
-    int ret;
+    int res;
 
     memset(&bmap, 0, sizeof(bmap));
     bmap.size     = surf->pitch * surf->h;
@@ -231,9 +238,12 @@
     bmap.pitch    = surf->pitch;
     bmap.width    = surf->w;
     bmap.height   = surf->h;
-
-    if ((ret = dmC64SetImagePalette(&bmap, NULL, FALSE)) != DMERR_OK)
-        return ret;
+    
+    if ((res = dmPaletteCopy(&bmap.pal, spec->pal)) != DMERR_OK)
+    {
+        dmErrorMsg("Could not create copy of palette.\n");
+        return res;
+    }
 
     if (cimage->charData[0].data == NULL)
     {
@@ -244,9 +254,9 @@
         charDataSet = FALSE;
 
     if (fmt->format->convertFrom != NULL)
-        ret = fmt->format->convertFrom(&bmap, cimage, fmt, spec);
+        res = fmt->format->convertFrom(&bmap, cimage, fmt, spec);
     else
-        ret = dmC64ConvertGenericBMP2Image(&bmap, cimage, fmt, spec);
+        res = dmC64ConvertGenericBMP2Image(&bmap, cimage, fmt, spec);
 
     if (charDataSet)
         memset(&cimage->charData[0], 0, sizeof(DMC64MemBlock));
@@ -254,15 +264,40 @@
     SDL_SetPaletteColors(surf->format->palette, (SDL_Color *) bmap.pal->colors, 0, bmap.pal->ncolors);
 
     dmPaletteFree(bmap.pal);
+    return res;
+}
 
-    return ret;
-}
+#if 0
+        DIR *dirh;
+        struct dirent *entry;
+
+        if ((dirh = opendir(npath)) == NULL)
+        {
+            int err = th_get_error();
+            THERR("Could not open directory '%s': %s\n",
+                path, th_error_str(err));
+            ret = FALSE;
+            goto out;
+        }
+
+        while ((entry = readdir(dirh)) != NULL)
+        if (entry->d_name[0] != '.')
+        {
+            if (!argHandleFileDir(npath, entry->d_name, pattern))
+            {
+                ret = FALSE;
+                goto out;
+            }
+        }
+
+        closedir(dirh);
+#endif
 
 
 int main(int argc, char *argv[])
 {
     const DMC64ImageFormat *forced;
-    DMC64ImageConvSpec spec;
+    DMC64ImageConvSpec optSpec;
     SDL_Window *window = NULL;
     SDL_Renderer *renderer = NULL;
     SDL_Texture *texture = NULL;
@@ -280,7 +315,7 @@
     }
 
     dmSetScaleFactor(2.0);
-    memset(&spec, 0, sizeof(spec));
+    memset(&optSpec, 0, sizeof(optSpec));
     memset(&setCharROM, 0, sizeof(setCharROM));
 
     dmInitProg("64vw", "Displayer for various C64 graphics formats", "0.4", NULL, NULL);
@@ -351,6 +386,30 @@
         goto exit;
     }
 
+    if (optC64PaletteFile != NULL)
+    {
+        if ((res = dmHandleExternalPalette(optC64PaletteFile, &optSpec.pal)) != DMERR_OK)
+            goto exit;
+    }
+    else
+    {
+        // No palette file specified, use internal palette
+        if (optC64Palette == NULL)
+            optC64Palette = &dmC64DefaultPalettes[0];
+            
+        dmMsg(1, "Using internal palette '%s' (%s).\n",
+            optC64Palette->name, optC64Palette->desc);
+
+        optSpec.cpal = optC64Palette;
+
+        if ((res = dmC64PaletteFromC64Palette(&optSpec.pal, optC64Palette, FALSE)) != DMERR_OK)
+        {
+            dmErrorMsg("Could not setup palette: %s\n",
+                dmErrorStr(res));
+            goto exit;
+        }
+    }
+
     // Check character ROM filename
     if (optCharROMFilename == NULL)
         optCharROMFilename = DM_DEF_CHARGEN;
@@ -524,7 +583,7 @@
                 goto exit;
             }
 
-            if (dmDecodeC64Image(cimage, fmt, surf, &spec) == DMERR_OK)
+            if (dmDecodeC64Image(cimage, fmt, surf, &optSpec) == DMERR_OK)
             {
                 title = dm_strdup_printf("%s - [%d / %d] %s (%dx%d @ %s)",
                     dmProgName,
@@ -608,6 +667,7 @@
     if (initSDL)
         SDL_Quit();
 
+    dmPaletteFree(optSpec.pal);
     dmLib64GFXClose();
 
     return 0;
--- a/tools/gfxconv.c	Fri Jun 14 03:28:46 2019 +0300
+++ b/tools/gfxconv.c	Fri Jun 14 05:01:12 2019 +0300
@@ -136,6 +136,8 @@
 DMMapValue optRemapTable[DM_MAX_COLORS];
 int     optColorMap[D64_NCOLORS];
 char    *optCharROMFilename = NULL;
+DMC64Palette *optC64Palette = NULL;
+char    *optC64PaletteFile = NULL;
 
 
 DMImageWriteSpec optSpec =
@@ -149,6 +151,9 @@
     .compression = FCMP_BEST,
 };
 
+DMC64ImageConvSpec optC64Spec;
+
+
 static const DMOptArg optList[] =
 {
     {  0, '?', "help",          "Show this help", OPT_NONE },
@@ -170,6 +175,7 @@
     { 20, 'C', "compress",      "Use compression -C <0-9>, 0 = disable, default is 9", OPT_ARGREQ },
     { 16, 'R', "remap",         "Remap output image colors (-R <(#RRGGBB|index):index>[,<..>][+remove] | -R @map.txt[+remove])", OPT_ARGREQ },
     { 21,   0, "char-rom",      "Set character ROM file to be used.", OPT_ARGREQ },
+    { 22, 'p', "palette" ,      "Set C64 palette to be used (see list with -p help).", OPT_ARGREQ },
 };
 
 static const int optListN = sizeof(optList) / sizeof(optList[0]);
@@ -958,6 +964,9 @@
             optCharROMFilename = optArg;
             break;
 
+        case 22:
+            return argHandleC64PaletteOption(optArg, &optC64Palette, &optC64PaletteFile);
+
         default:
             dmErrorMsg("Unimplemented option argument '%s'.\n", currArg);
             return FALSE;
@@ -1831,7 +1840,7 @@
             outImage = dmImageAlloc(outWidthPX * outIWidth, outIHeight * outHeight, DM_PIXFMT_PALETTE, -1);
         }
 
-        if ((err = dmC64SetImagePalette(outImage, NULL, FALSE)) != DMERR_OK)
+        if ((err = dmC64SetImagePalette(outImage, &optC64Spec, FALSE)) != DMERR_OK)
         {
             dmErrorMsg("Could not allocate C64 palette for output image: %d\n", err);
             goto error;
@@ -1914,7 +1923,6 @@
 int main(int argc, char *argv[])
 {
     FILE *inFile = NULL;
-    DMC64ImageConvSpec imageSpecC64;
     const DMC64ImageFormat *inC64Fmt = NULL;
     DMConvFormat inFormat, outFormat;
     DMC64Image *inC64Image = NULL, *outC64Image = NULL;
@@ -1928,7 +1936,7 @@
         optColorMap[i] = i;
 
     // Initialize c64 image conversion spec
-    memset(&imageSpecC64, 0, sizeof(imageSpecC64));
+    memset(&optC64Spec, 0, sizeof(optC64Spec));
 
     // Initialize list of additional conversion formats
     if ((res = dmLib64GFXInit()) != DMERR_OK)
@@ -2144,6 +2152,30 @@
         }
     }
 
+    if (optC64PaletteFile != NULL)
+    {
+        if ((res = dmHandleExternalPalette(optC64PaletteFile, &optC64Spec.pal)) != DMERR_OK)
+            goto exit;
+    }
+    else
+    {
+        // No palette file specified, use internal palette
+        if (optC64Palette == NULL)
+            optC64Palette = &dmC64DefaultPalettes[0];
+            
+        dmMsg(1, "Using internal palette '%s' (%s).\n",
+            optC64Palette->name, optC64Palette->desc);
+
+        optC64Spec.cpal = optC64Palette;
+
+        if ((res = dmC64PaletteFromC64Palette(&optC64Spec.pal, optC64Palette, FALSE)) != DMERR_OK)
+        {
+            dmErrorMsg("Could not setup palette: %s\n",
+                dmErrorStr(res));
+            goto exit;
+        }
+    }
+
     switch (optInType)
     {
         case FFMT_SPRITE:
@@ -2186,7 +2218,7 @@
                     }
 
                     // Convert the image
-                    res = dmC64ConvertBMP2Image(&outImage, inC64Image, inC64Fmt, &imageSpecC64);
+                    res = dmC64ConvertBMP2Image(&outImage, inC64Image, inC64Fmt, &optC64Spec);
 
                     if (res != DMERR_OK || outImage == NULL)
                     {
@@ -2275,7 +2307,7 @@
                         {
                             DMC64Image *tmpC64Image = NULL;
                             res = dmC64ConvertImage2BMP(&tmpC64Image, inImage,
-                                &dmC64ImageFormats[optOutFormat], &imageSpecC64);
+                                &dmC64ImageFormats[optOutFormat], &optC64Spec);
 
                             if (res != DMERR_OK || tmpC64Image == NULL)
                             {
--- a/tools/lib64fmts.c	Fri Jun 14 03:28:46 2019 +0300
+++ b/tools/lib64fmts.c	Fri Jun 14 05:01:12 2019 +0300
@@ -1545,10 +1545,7 @@
 {
     int res;
 
-    if (spec->pal != NULL)
-        dst->pal = spec->pal;
-    else
-    if ((res = dmC64SetImagePalette(dst, spec->cpal, TRUE)) != DMERR_OK)
+    if ((res = dmC64SetImagePalette(dst, spec, TRUE)) != DMERR_OK)
         return res;
 
     return dmC64ConvertGenericBMP2Image(dst, src, fmt, spec);
--- a/tools/lib64gfx.c	Fri Jun 14 03:28:46 2019 +0300
+++ b/tools/lib64gfx.c	Fri Jun 14 05:01:12 2019 +0300
@@ -88,13 +88,12 @@
 const int ndmC64DefaultPalettes = sizeof(dmC64DefaultPalettes) / sizeof(dmC64DefaultPalettes[0]);
 
 
-int dmC64PaletteFromC64Palette(DMPalette **ppal, const DMC64Palette *pcpal, const BOOL mixed)
+int dmC64PaletteFromC64Colors(DMPalette **ppal, const DMColor *colors, const BOOL mixed)
 {
-    const DMC64Palette *cpal = pcpal;
     int res;
 
-    if (cpal == NULL)
-        cpal = &dmC64DefaultPalettes[0];
+    if (ppal == NULL || colors == NULL)
+        return DMERR_NULLPTR;
 
     // Allocate and create new
     if (mixed)
@@ -105,10 +104,10 @@
 
         for (int n1 = 0, n = 0; n1 < D64_NCOLORS; n1++)
         {
-            const DMColor *col1 = &cpal->colors[n1];
+            const DMColor *col1 = &colors[n1];
             for (int n2 = 0; n2 < D64_NCOLORS; n2++)
             {
-                const DMColor *col2 = &cpal->colors[n2];
+                const DMColor *col2 = &colors[n2];
                 (*ppal)->colors[n].r = (col1->r + col2->r) / 2;
                 (*ppal)->colors[n].g = (col1->g + col2->g) / 2;
                 (*ppal)->colors[n].b = (col1->b + col2->b) / 2;
@@ -119,19 +118,28 @@
     else
     {
         // Standard palette, just copy it
-        if ((res = dmPaletteAlloc(ppal, 256, 255)) != DMERR_OK)
+        if ((res = dmPaletteAlloc(ppal, D64_NCOLORS, 255)) != DMERR_OK)
             return res;
 
-        memcpy((*ppal)->colors, cpal->colors, D64_NCOLORS * sizeof(DMColor));
+        memcpy((*ppal)->colors, colors, D64_NCOLORS * sizeof(DMColor));
     }
 
     return DMERR_OK;
 }
 
 
-int dmC64SetImagePalette(DMImage *img, const DMC64Palette *cpal, const BOOL mixed)
+int dmC64PaletteFromC64Palette(DMPalette **ppal, const DMC64Palette *cpal, const BOOL mixed)
 {
-    if (img == NULL)
+    if (ppal == NULL || cpal == NULL)
+        return DMERR_NULLPTR;
+
+    return dmC64PaletteFromC64Colors(ppal, cpal->colors, mixed);
+}
+
+
+int dmC64SetImagePalette(DMImage *img, const DMC64ImageConvSpec *spec, const BOOL mixed)
+{
+    if (img == NULL || spec == NULL)
         return DMERR_NULLPTR;
 
     // Free previous palette
@@ -140,7 +148,18 @@
 
     img->constpal = FALSE;
 
-    return dmC64PaletteFromC64Palette(&img->pal, cpal, mixed);
+    // If specific palette is wanted, use it
+    if (spec->pal != NULL)
+    {
+        if (spec->pal->ncolors > D64_NCOLORS)
+            return dmPaletteCopy(&img->pal, spec->pal);
+        else
+        if (spec->pal->ncolors == D64_NCOLORS)
+            return dmC64PaletteFromC64Colors(&img->pal, spec->pal->colors, mixed);
+    }
+
+    // Else, use the c64 palette specified
+    return dmC64PaletteFromC64Palette(&img->pal, spec->cpal, mixed);
 }
 
 
@@ -1429,10 +1448,7 @@
         return DMERR_MALLOC;
 
     // Set palette information
-    if (spec->pal != NULL)
-        dst->pal = spec->pal;
-    else
-    if ((res = dmC64SetImagePalette(dst, spec->cpal, FALSE)) != DMERR_OK)
+    if ((res = dmC64SetImagePalette(dst, spec, FALSE)) != DMERR_OK)
         return res;
 
     // Convert
--- a/tools/lib64gfx.h	Fri Jun 14 03:28:46 2019 +0300
+++ b/tools/lib64gfx.h	Fri Jun 14 05:01:12 2019 +0300
@@ -352,8 +352,8 @@
 //
 int       dmC64ProbeBMP(const DMGrowBuf *buf, const DMC64ImageFormat **fmt);
 
-int       dmC64PaletteFromC64Palette(DMPalette **ppal, const DMC64Palette *pcpal, const BOOL mixed);
-int       dmC64SetImagePalette(DMImage *img, const DMC64Palette *cpal, const BOOL mixed);
+int       dmC64PaletteFromC64Palette(DMPalette **ppal, const DMC64Palette *cpal, const BOOL mixed);
+int       dmC64SetImagePalette(DMImage *img, const DMC64ImageConvSpec *spec, const BOOL mixed);
 
 BOOL      dmCompareAddr16(const DMGrowBuf *buf, const size_t offs, const Uint16 addr);
 
--- a/tools/lib64util.c	Fri Jun 14 03:28:46 2019 +0300
+++ b/tools/lib64util.c	Fri Jun 14 05:01:12 2019 +0300
@@ -6,6 +6,7 @@
  * 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)
@@ -104,3 +105,93 @@
     }
     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;
+        }
+
+        res = dmPaletteCopy(ppal, inImage->pal);
+    }
+    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;
+}
--- a/tools/lib64util.h	Fri Jun 14 03:28:46 2019 +0300
+++ b/tools/lib64util.h	Fri Jun 14 05:01:12 2019 +0300
@@ -27,6 +27,10 @@
 void      dmC64ImageDump(FILE *fh, const DMC64Image *img, const DMC64ImageFormat *fmt, const char *indent);
 
 
+BOOL argHandleC64PaletteOption(char *optArg, DMC64Palette **ppal, char **palFile);
+int dmHandleExternalPalette(const char *filename, DMPalette **ppal);
+
+
 #ifdef __cplusplus
 }
 #endif
--- a/tools/libgfx.c	Fri Jun 14 03:28:46 2019 +0300
+++ b/tools/libgfx.c	Fri Jun 14 05:01:12 2019 +0300
@@ -233,6 +233,8 @@
     if (ncolors - pal->ncolors > 0)
         memset(&(pal->colors[pal->ncolors]), 0, sizeof(DMColor) * (ncolors - pal->ncolors));
 
+    pal->ncolors = ncolors;
+
     return DMERR_OK;
 }
 
@@ -329,13 +331,10 @@
 }
 
 
-#define ACT_MAGIC_ID 0x0010ffff
-
-
 static int fmtProbeACT(const Uint8 *buf, const size_t len)
 {
     if (len == 0x304 &&
-        DM_BE32_TO_NATIVE(*(Uint32 *) (buf + 0x300)) == ACT_MAGIC_ID)
+        buf[0x300] == 0)
         return DM_PROBE_SCORE_MAX;
 
     return DM_PROBE_SCORE_FALSE;
@@ -345,7 +344,7 @@
 int dmReadACTPalette(DMResource *fp, DMPalette **pdst)
 {
     int res;
-    Uint32 magicID;
+    Uint16 tmp1, tmp2;
 
     if ((res = dmPaletteAlloc(pdst, 256, -1)) != DMERR_OK)
         return res;
@@ -353,18 +352,24 @@
     if ((res = dmPaletteReadData(fp, *pdst, 256)) != DMERR_OK)
         goto error;
 
-    if (!dmf_read_be32(fp, &magicID))
+    if (!dmf_read_be16(fp, &tmp1) ||
+        !dmf_read_be16(fp, &tmp2))
     {
         res = DMERR_FREAD;
         goto error;
     }
 
-    if (magicID != ACT_MAGIC_ID)
+    if (tmp1 == 0 || tmp1 > 256)
     {
         res = DMERR_INVALID_DATA;
         goto error;
     }
 
+    if ((res = dmPaletteResize(pdst, tmp1)) != DMERR_OK)
+        goto error;
+
+    (*pdst)->ctransp = tmp2 < 256 ? tmp2 : -1;
+
     return res;
 
 error:
@@ -381,7 +386,8 @@
     if ((res = dmPaletteWriteData(fp, ppal, ppal->ncolors, 256)) != DMERR_OK)
         return res;
 
-    if (!dmf_write_be32(fp, ACT_MAGIC_ID))
+    if (!dmf_write_be16(fp, ppal->ncolors) ||
+        !dmf_write_be16(fp, ppal->ctransp >= 0 ? ppal->ctransp : 0xffff))
         return DMERR_FWRITE;
 
     return DMERR_OK;