changeset 1360:fcaf04cb0830

Make image palette remapping use a destination image instead of doing remapping on the source image.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 22 Sep 2017 15:58:32 +0300
parents 28fe5b0925dc
children 00f47a678482
files tools/gfxconv.c
diffstat 1 files changed, 67 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/tools/gfxconv.c	Wed Aug 30 03:35:52 2017 +0300
+++ b/tools/gfxconv.c	Fri Sep 22 15:58:32 2017 +0300
@@ -869,15 +869,22 @@
 }
 
 
-int dmRemapImageColors(DMImage *image)
+int dmRemapImageColors(DMImage **pdst, const DMImage *src)
 {
-    DMColor *npal = dmCalloc(image->ncolors, sizeof(DMColor));
-    int  *mapping = dmMalloc(image->ncolors * sizeof(int));
-    BOOL *mapped  = dmMalloc(image->ncolors * sizeof(BOOL));
-    BOOL *used    = dmMalloc(image->ncolors * sizeof(BOOL));
+    DMColor *npal = dmCalloc(src->ncolors, sizeof(DMColor));
+    int  *mapping = dmMalloc(src->ncolors * sizeof(int));
+    BOOL *mapped  = dmMalloc(src->ncolors * sizeof(BOOL));
+    BOOL *used    = dmMalloc(src->ncolors * sizeof(BOOL));
     int n, index, xc, yc, ncolors;
+    DMImage *dst;
 
-    dmMsg(1, "Remapping %d output image colors of %d colors.\n", optNRemapTable, image->ncolors);
+    if ((dst = *pdst = dmImageAlloc(src->width, src->height, src->format, src->bpp)) == NULL)
+    {
+        return dmError(DMERR_MALLOC,
+            "Could not allocate memory for remapped image.\n");
+    }
+
+    dmMsg(1, "Remapping %d output image colors of %d colors.\n", optNRemapTable, src->ncolors);
 
     if (npal == NULL || mapping == NULL || mapped == NULL || used == NULL)
     {
@@ -885,7 +892,7 @@
             "Could not allocate memory for reused palette.\n");
     }
 
-    for (index = 0; index < image->ncolors; index++)
+    for (index = 0; index < src->ncolors; index++)
     {
         mapping[index] = -1;
         mapped[index] = used[index] = FALSE;
@@ -893,13 +900,13 @@
 
     // Find used colors
     dmMsg(2, "Scanning image for used colors...\n");
-    for (ncolors = yc = 0; yc < image->height; yc++)
+    for (ncolors = yc = 0; yc < src->height; yc++)
     {
-        Uint8 *dp = image->data + image->pitch * yc;
-        for (xc = 0; xc < image->width; xc++)
+        const Uint8 *dp = src->data + src->pitch * yc;
+        for (xc = 0; xc < src->width; xc++)
         {
             Uint8 col = dp[xc];
-            if (col < image->ncolors && !used[col])
+            if (col < src->ncolors && !used[col])
             {
                 used[col] = TRUE;
                 ncolors++;
@@ -915,9 +922,9 @@
         if (map->triplet)
         {
             BOOL found = FALSE;
-            for (n = 0; n < image->ncolors; n++)
+            for (n = 0; n < src->ncolors; n++)
             {
-                if (dmCompareColor(&(image->pal[n]), &(map->color), map->alpha))
+                if (dmCompareColor(&(src->pal[n]), &(map->color), map->alpha))
                 {
                     dmMsg(3, "RGBA match #%02x%02x%02x%02x: %d -> %d\n",
                         map->color.r, map->color.g, map->color.b, map->color.a,
@@ -952,10 +959,10 @@
     if (optRemapRemove)
     {
         dmMsg(2, "Removing unused colors.\n");
-        for (index = 0; index < image->ncolors; index++)
+        for (index = 0; index < src->ncolors; index++)
         if (mapping[index] < 0 && used[index])
         {
-            for (n = 0; n < image->ncolors; n++)
+            for (n = 0; n < src->ncolors; n++)
             if (!mapped[n])
             {
                 mapping[index] = n;
@@ -966,10 +973,10 @@
     }
     else
     {
-        for (index = 0; index < image->ncolors; index++)
+        for (index = 0; index < src->ncolors; index++)
         if (mapping[index] < 0)
         {
-            for (n = 0; n < image->ncolors; n++)
+            for (n = 0; n < src->ncolors; n++)
             if (!mapped[n])
             {
                 mapping[index] = n;
@@ -981,30 +988,31 @@
 
     // Calculate final number of palette colors
     ncolors = 0;
-    for (index = 0; index < image->ncolors; index++)
+    for (index = 0; index < src->ncolors; index++)
     {
         if (mapping[index] + 1 > ncolors)
             ncolors = mapping[index] + 1;
     }
 
     // Copy palette entries
-    for (index = 0; index < image->ncolors; index++)
+    for (index = 0; index < src->ncolors; index++)
     {
         if (mapping[index] >= 0)
         {
-            memcpy(&npal[mapping[index]], &(image->pal[index]), sizeof(DMColor));
+            memcpy(&npal[mapping[index]], &(src->pal[index]), sizeof(DMColor));
         }
     }
 
     // Remap image
     dmMsg(1, "Remapping image to %d colors...\n", ncolors);
-    for (yc = 0; yc < image->height; yc++)
+    for (yc = 0; yc < src->height; yc++)
     {
-        Uint8 *dp = image->data + image->pitch * yc;
-        for (xc = 0; xc < image->width; xc++)
+        Uint8 *sp = src->data + src->pitch * yc;
+        Uint8 *dp = dst->data + dst->pitch * yc;
+        for (xc = 0; xc < src->width; xc++)
         {
-            Uint8 col = dp[xc];
-            if (col < image->ncolors && mapping[col] >= 0 && mapping[col] < image->ncolors)
+            Uint8 col = sp[xc];
+            if (col < src->ncolors && mapping[col] >= 0 && mapping[col] < src->ncolors)
                 dp[xc] = mapping[col];
             else
                 dp[xc] = 0;
@@ -1012,9 +1020,8 @@
     }
 
     // Set new palette, free memory
-    dmFree(image->pal);
-    image->pal = npal;
-    image->ncolors = ncolors;
+    dst->pal = npal;
+    dst->ncolors = ncolors;
 
     dmFree(mapping);
     dmFree(mapped);
@@ -1093,23 +1100,29 @@
 }
 
 
-int dmWriteImage(const char *filename, DMImage *image, DMImageConvSpec *spec, int iformat, BOOL info)
+int dmWriteImage(const char *filename, DMImage *pimage, DMImageConvSpec *spec, int iformat, BOOL info)
 {
+    int res = DMERR_OK;
+
     if (info)
     {
         dmMsg(1, "Outputting %s image %d x %d -> %d x %d [%d x %d]\n",
             dmImageFormatList[iformat].fext,
-            image->width, image->height,
-            image->width * spec->scaleX, image->height * spec->scaleY,
+            pimage->width, pimage->height,
+            pimage->width * spec->scaleX, pimage->height * spec->scaleY,
             spec->scaleX, spec->scaleY);
     }
 
     // Perform color remapping
+    DMImage *image = pimage;
+    BOOL allocated = FALSE;
     if (optRemapColors)
     {
         int res;
-        if ((res = dmRemapImageColors(image)) != DMERR_OK)
+        if ((res = dmRemapImageColors(&image, pimage)) != DMERR_OK)
             return res;
+
+        allocated = TRUE;
     }
 
     switch (iformat)
@@ -1118,44 +1131,44 @@
         case IMGFMT_PNG:
             spec->format = spec->paletted ? DM_IFMT_PALETTE : DM_IFMT_RGBA;
             dmOutputImageBitFormat(spec->format, info);
-            return dmWritePNGImage(filename, image, spec);
+            res = dmWritePNGImage(filename, image, spec);
+            break;
 #endif
 
         case IMGFMT_PPM:
             spec->format = DM_IFMT_RGB;
             dmOutputImageBitFormat(spec->format, info);
-            return dmWritePPMImage(filename, image, spec);
+            res = dmWritePPMImage(filename, image, spec);
+            break;
 
         case IMGFMT_PCX:
             spec->format = spec->paletted ? DM_IFMT_PALETTE : DM_IFMT_RGB;
             dmOutputImageBitFormat(spec->format, info);
-            return dmWritePCXImage(filename, image, spec);
+            res = dmWritePCXImage(filename, image, spec);
+            break;
 
         case IMGFMT_RAW:
         case IMGFMT_ARAW:
             {
+                // Open data file for writing
                 FILE *fp;
-                char *dataFilename;
-
-                // Form data file filename
-                dataFilename = dm_strdup_fext(filename, "%s.inc");
-                if (dataFilename == NULL)
-                    return DMERR_MALLOC;
-
-                // Open data file for writing
+                char * dataFilename = dm_strdup_fext(filename, "%s.inc");
                 if ((fp = fopen(dataFilename, "w")) == NULL)
-                    dmErrorMsg("Could not create '%s'.\n", dataFilename);
+                {
+                    res = dmError(DMERR_FOPEN,
+                        "Could not create '%s'.\n", dataFilename);
+                    goto err;
+                }
 
                 dmFree(dataFilename);
 
                 if (fp != NULL)
                 {
                     // Strip extension
-                    int i;
                     char *palID = dm_strdup_fext(filename, "img_%s");
 
                     // Replace any non-alphanumerics
-                    for (i = 0; palID[i]; i++)
+                    for (int i = 0; palID[i]; i++)
                     {
                         if (isalnum(palID[i]))
                             palID[i] = tolower(palID[i]);
@@ -1204,13 +1217,19 @@
                         spec->nplanes,
                         spec->planar ? "planar/interleaved" : "non-interleaved");
                 }
-                return dmWriteRAWImage(filename, image, spec);
+                res = dmWriteRAWImage(filename, image, spec);
             }
             break;
 
         default:
-            return DMERR_INVALID_DATA;
+            res = DMERR_INVALID_DATA;
     }
+
+err:
+    if (allocated)
+        dmImageFree(image);
+
+    return res;
 }