changeset 2050:416af5a842ec

Fixes to the ByteRun1 encoder. Could use some cleanups now, tho.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 03 Dec 2018 19:01:07 +0200
parents a945a5f2fd70
children c67d863384a5
files tools/libgfx.c
diffstat 1 files changed, 80 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/tools/libgfx.c	Mon Dec 03 18:58:45 2018 +0200
+++ b/tools/libgfx.c	Mon Dec 03 19:01:07 2018 +0200
@@ -2048,80 +2048,105 @@
 };
 
 
-BOOL dmIFFEncodeByteRun1Flush(
-    DMResource *fp, const int mode, const BOOL flush,
-    size_t *l_offs, const size_t offs, const Uint8 *buf,
-    const Uint8 data, unsigned int *r_count)
+BOOL dmIFFEncodeByteRun1LIT(DMResource *fp,
+    const Uint8 *buf, const size_t offs,
+    const size_t count)
 {
-    if (mode == DMODE_LIT)
-    {
-        size_t l_count = offs - *l_offs;
-        if (l_count > *r_count || flush)
-        {
-            size_t count = l_count - *r_count;
-            Uint8 tmp = count - 1;
-
-            if (!dmf_write_byte(fp, tmp) ||
-                !dmf_write_str(fp, buf + *l_offs, count))
-                return FALSE;
-        }
-        (*r_count)++;
-    }
-    else
-    {
-        if (*r_count > 0)
-        {
-            unsigned int count = *r_count;
-            Uint8 tmp = ((Uint8) count - 2) ^ 0xff;
-
-            if (!dmf_write_byte(fp, tmp) ||
-                !dmf_write_byte(fp, data))
-                return FALSE;
-
-            *r_count = 0;
-        }
-        *l_offs = offs;
-    }
-
-    return TRUE;
+    if (count <= 0)
+        return TRUE;
+
+    Uint8 tmp = count - 1;
+
+    return
+        dmf_write_byte(fp, tmp) &&
+        dmf_write_str(fp, buf + offs, count);
+}
+
+
+BOOL dmIFFEncodeByteRun1RLE(DMResource *fp,
+    const Uint8 *buf, const size_t offs,
+    const size_t count)
+{
+    if (count <= 0)
+        return TRUE;
+
+    Uint8
+        tmp = ((Uint8) count - 2) ^ 0xff,
+        data = buf[offs];
+
+    return
+        dmf_write_byte(fp, tmp) &&
+        dmf_write_byte(fp, data);
 }
 
 
 BOOL dmIFFEncodeByteRun1Row(DMResource *fp, const Uint8 *buf, const size_t bufLen)
 {
-    unsigned int r_count = 0;
     int prev = -1, mode = DMODE_LIT;
-    size_t offs, l_offs = 0;
-
-    for (offs = 0; offs < bufLen; offs++)
+    size_t offs, l_offs, r_offs;
+    BOOL ret = TRUE;
+
+    for (offs = l_offs = r_offs = 0; offs < bufLen; offs++)
     {
         Uint8 data = buf[offs];
-        int next_mode;
-        BOOL flush;
+        BOOL flush = FALSE;
+        int pmode = mode;
 
         if (data == prev)
         {
-            r_count++;
-            next_mode = DMODE_RLE;
+            if (mode == DMODE_LIT &&
+                offs - r_offs >= 2)
+            {
+                ret = dmIFFEncodeByteRun1LIT(fp, buf, l_offs, r_offs - l_offs);
+                mode = DMODE_RLE;
+            }
         }
         else
         {
-            next_mode = DMODE_LIT;
+            if (mode != DMODE_LIT)
+            {
+                ret = dmIFFEncodeByteRun1RLE(fp, buf, r_offs, offs - r_offs);
+                mode = DMODE_LIT;
+                l_offs = offs;
+            }
+            r_offs = offs;
         }
 
-        flush = offs - l_offs >= 126 || r_count >= 126;
-        if ((next_mode != mode || flush) &&
-            !dmIFFEncodeByteRun1Flush(fp, mode, flush, &l_offs, offs, buf, prev, &r_count))
-            return FALSE;
-
-        mode = next_mode;
+        if (!ret)
+            goto out;
+
+        // NOTE! RLE and LIT max are both 128, checked against DP2e
+        flush =
+            (pmode == DMODE_RLE && offs - r_offs >= 128) ||
+            (pmode == DMODE_LIT && offs - l_offs >= 128);
+
+        // Check for last byte of input
+        if (offs == bufLen - 1)
+        {
+            offs++;
+            flush = TRUE;
+            pmode = mode;
+        }
+
+        if (flush)
+        {
+            if (pmode == DMODE_RLE)
+                ret = dmIFFEncodeByteRun1RLE(fp, buf, r_offs, offs - r_offs);
+            else
+                ret = dmIFFEncodeByteRun1LIT(fp, buf, l_offs, offs - l_offs);
+
+            r_offs = l_offs = offs;
+            mode = DMODE_LIT;
+
+            if (!ret)
+                goto out;
+        }
+
         prev = data;
     }
 
-    if (!dmIFFEncodeByteRun1Flush(fp, mode, TRUE, &l_offs, offs, buf, prev, &r_count))
-        return FALSE;
-
-    return TRUE;
+out:
+    return ret;
 }
 
 
@@ -2256,6 +2281,7 @@
     if ((res = dmWriteIFFChunkFinish(fp, &iff.chCMAP)) != DMERR_OK)
         goto out;
 
+
     //
     // Encode the body
     //