changeset 2053:6dfbe976d740

Implement basic initial support for IFF ACBM format images.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 03 Dec 2018 23:05:58 +0200
parents aa8df4f1b785
children 1a032298adb8
files tools/libgfx.c
diffstat 1 files changed, 56 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/tools/libgfx.c	Mon Dec 03 19:24:32 2018 +0200
+++ b/tools/libgfx.c	Mon Dec 03 23:05:58 2018 +0200
@@ -1454,6 +1454,8 @@
 #define IFF_ID_CMAP        0x434D4150 // "CMAP"
 #define IFF_ID_BODY        0x424F4459 // "BODY"
 #define IFF_ID_CAMG        0x43414D47 // "CAMG"
+#define IFF_ID_ACBM        0x4143424D // "ACBM"
+#define IFF_ID_ABIT        0x41424954 // "ABIT"
 
 #define IFF_MASK_NONE      0
 #define IFF_MASK_HAS_MASK  1
@@ -1499,6 +1501,7 @@
     Uint32 camg;
     int ncolors;
     DMColor *pal;
+    Uint32 idsig;
 } DMIFF;
 
 
@@ -1577,7 +1580,7 @@
 }
 
 
-static int dmCheckIFFChunk(DMIFFChunk *dest, DMIFFChunk *chunk,
+static int dmCheckIFFChunk(DMIFFChunk *dest, const DMIFFChunk *chunk,
     const BOOL multi, const Uint32 minSize)
 {
     if (dest->count > 0 && !multi)
@@ -1664,22 +1667,53 @@
     int res = DMERR_OK;
     const int nplanes = iff->bmhd.nplanes;
 
-    if (iff->planar)
+    if (iff->idsig == IFF_ID_ILBM)
     {
-        // Allocate planar decoding buffer
         bufLen = ((img->width + 15) / 16) * 2;
-        if ((buf = dmMalloc(bufLen)) == NULL)
-            return DMERR_MALLOC;
-
         dmMsg(2, "IFF: Line / plane row size %d bytes.\n", bufLen);
+
     }
+    else
+    if (iff->idsig == IFF_ID_ACBM)
+    {
+        bufLen = (img->width * img->height) / 8;
+        dmMsg(2, "IFF: Plane buffer size %d bytes.\n", bufLen);
+    }
+
+    if (bufLen > 0 && (buf = dmMalloc(bufLen)) == NULL)
+        return DMERR_MALLOC;
 
     // Decode the chunk
+    if (iff->idsig == IFF_ID_ACBM)
+    {
+        for (int plane = 0; plane < nplanes; plane++)
+        {
+            if (!dmf_read_str(fp, buf, bufLen))
+            {
+                res = dmError(DMERR_FREAD,
+                    "IFF: Error in reading image plane #%d.\n",
+                    plane);
+                goto out;
+            }
+
+            for (int yc = 0; yc < img->height; yc++)
+            {
+                Uint8 *dp = img->data + (yc * img->pitch);
+                for (int xc = 0; xc < img->width; xc++)
+                {
+                    const Uint8 data = dmDecodeBit(buf + yc * 40, xc);
+                    if (data)
+                        dp[xc] |= 1 << plane;
+                }
+            }
+        }
+    }
+    else
     for (int yc = 0; yc < img->height; yc++)
     {
         Uint8 *dp = img->data + (yc * img->pitch);
 
-        if (iff->planar)
+        if (iff->idsig == IFF_ID_ILBM)
         {
             // Clear planar decoding buffer
             dmMemset(dp, 0, img->pitch);
@@ -1723,6 +1757,7 @@
             }
         }
         else
+        if (iff->idsig == IFF_ID_PBM)
         {
             if (!dmIFFReadOneRow(fp, iff, dp, img->width))
             {
@@ -1743,7 +1778,6 @@
 {
     DMIFFChunk chunk;
     DMIFF iff;
-    Uint32 idsig;
     BOOL parsed = FALSE;
     int res = DMERR_OK;
 
@@ -1761,17 +1795,18 @@
     }
 
     // Check IFF ILBM/PBM signature
-    if (!dmf_read_be32(fp, &idsig) ||
-        (idsig != IFF_ID_ILBM && idsig != IFF_ID_PBM))
+    if (!dmf_read_be32(fp, &iff.idsig) ||
+        (iff.idsig != IFF_ID_ILBM &&
+         iff.idsig != IFF_ID_PBM &&
+         iff.idsig != IFF_ID_ACBM))
     {
         return dmError(DMERR_INVALID_DATA,
-            "IFF: Not a IFF ILBM/PBM file.\n");
+            "IFF: Not a IFF ILBM/PBM/ACBM file.\n");
     }
 
-    iff.planar = (idsig == IFF_ID_ILBM);
-
     dmMsg(3, "IFF: FORM is %s format image, with size %d bytes.\n",
-        iff.planar ? "ILBM" : "PBM", chunk.size);
+        iff.idsig == IFF_ID_ILBM ? "ILBM" : (iff.idsig == IFF_ID_PBM ? "PBM" : "ACBM"),
+        chunk.size);
 
     while (!parsed && !dmfeof(fp))
     {
@@ -1865,6 +1900,7 @@
                 break;
 
             case IFF_ID_BODY:
+            case IFF_ID_ABIT:
                 // Check for multiple occurences of BODY
                 if ((res = dmCheckIFFChunk(&iff.chBODY, &chunk, FALSE, 1)) != DMERR_OK)
                     return res;
@@ -1873,10 +1909,10 @@
                 if (!iff.chBMHD.count)
                 {
                     return dmError(DMERR_INVALID_DATA,
-                        "IFF: BODY chunk before BMHD?\n");
+                        "IFF: %s chunk before BMHD?\n", chunk.idStr);
                 }
 
-                dmMsg(2, "IFF: BODY chunk size %d bytes\n", chunk.size);
+                dmMsg(2, "IFF: %s chunk size %d bytes\n", chunk.idStr, chunk.size);
 
                 // Allocate image
                 if ((*pimg = dmImageAlloc(iff.bmhd.w, iff.bmhd.h,
@@ -1902,7 +1938,6 @@
                     parsed = TRUE;
                 break;
 
-
             case IFF_ID_CAMG:
                 if (!dmf_read_be32(fp, &iff.camg))
                 {
@@ -1950,7 +1985,7 @@
         if (iff.camg & IFF_CAMG_HALFBRITE)
         {
             void *ptmp;
-            if (!iff.planar)
+            if (iff.idsig != IFF_ID_ILBM)
             {
                 dmErrorMsg("IFF: Non-planar PBM file with Halfbrite enabled! This might not work.\n");
             }
@@ -2161,7 +2196,6 @@
 
 int dmWriteIFFImage(DMResource *fp, const DMImage *img, const DMImageConvSpec *cpspec)
 {
-    Uint32 idsig;
     DMIFF iff;
     Uint8 *buf = NULL;
     size_t bufLen;
@@ -2196,7 +2230,7 @@
     iff.bmhd.compression = spec->compression ? IFF_COMP_BYTERUN1 : IFF_COMP_NONE;
     iff.bmhd.transp      = (img->ctransp >= 0 && spec->mask == IFF_MASK_TRANSP) ? img->ctransp : 0xffff;
     iff.bmhd.nplanes     = spec->nplanes;
-    idsig                = spec->planar ? IFF_ID_ILBM : IFF_ID_PBM;
+    iff.idsig            = spec->planar ? IFF_ID_ILBM : IFF_ID_PBM;
 
     dmMsg(2, "IFF: nplanes=%d, comp=%d, mask=%d\n",
         iff.bmhd.nplanes, iff.bmhd.compression, iff.bmhd.masking);
@@ -2206,7 +2240,7 @@
         goto out;
 
     // Write IFF ILBM/PBM signature
-    if (!dmf_write_be32(fp, idsig))
+    if (!dmf_write_be32(fp, iff.idsig))
     {
         res = dmError(DMERR_FWRITE,
             "IFF: Error writing %s signature.\n",
@@ -2392,7 +2426,7 @@
         fmtProbePCX, dmReadPCXImage, dmWritePCXImage,
     },
     {
-        "iff", "IFF ILBM / PBM",
+        "iff", "IFF ILBM/PBM/ACBM",
         DM_IMGFMT_IFF, DM_FMT_RDWR,
         fmtProbeIFF, dmReadIFFImage, dmWriteIFFImage,
     },