changeset 1478:d883b4c1cf48

More work on RLE encoding/decoding.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 11 May 2018 02:42:49 +0300
parents e8fe529f4341
children c4755b73b93c
files tools/lib64gfx.c
diffstat 1 files changed, 75 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/tools/lib64gfx.c	Fri May 11 02:26:29 2018 +0300
+++ b/tools/lib64gfx.c	Fri May 11 02:42:49 2018 +0300
@@ -289,18 +289,83 @@
 }
 
 
-static int dmEncodeGenericRLE(DMGrowBuf *dst, const Uint8 *src, const Uint8 *srcEnd,
+static int dmDecodeGenericRLEAlloc(DMGrowBuf *dst, const Uint8 *src, const Uint8 *srcEnd,
     const Uint8 rleMarker, const Uint8 rleMask1, const Uint8 rleMask2, const int rleType)
 {
-    (void) dst;
-    (void) src;
-    (void) srcEnd;
-    (void) rleMarker;
-    (void) rleMask1;
-    (void) rleMask2;
-    (void) rleType;
+    int res;
+    if ((res = dmGrowBufAlloc(dst, BUF_SIZE_INITIAL, BUF_SIZE_GROW)) != DMERR_OK)
+        return res;
+
+    return dmDecodeGenericRLE(dst, src, srcEnd, rleMarker, rleMask1, rleMask2, rleType);
+}
+
+
+static BOOL dmEncodeGenericRLESequence(DMGrowBuf *dst, const Uint8 data, const Uint8 count, const Uint8 rleMarker, const int rleType)
+{
+    switch (rleType)
+    {
+        case DM_RLE_MARKER:
+            // A simple marker byte RLE variant: [Marker] [count] [data]
+            if (!dmGrowBufPutU8(dst, rleMarker) ||
+                !dmGrowBufPutU8(dst, count) ||
+                !dmGrowBufPutU8(dst, data))
+                return FALSE;
+            break;
+
+        case DM_RLE_MASK:
+            // Mask marker RLE: usually high bit(s) of byte mark RLE sequence
+            // and the lower bits contain the count: [Mask + count] [data]
+            if (!dmGrowBufPutU8(dst, rleMarker | count) ||
+                !dmGrowBufPutU8(dst, data))
+                return FALSE;
+            break;
+    }
+
+    return TRUE;
+}
+
 
-    return DMERR_OK;
+static int dmEncodeGenericRLE(DMGrowBuf *dst, const Uint8 *src, const Uint8 *srcEnd,
+    const Uint8 rleMarker, const Uint8 rleMinCount, const Uint8 rleMaxCount, const int rleType)
+{
+    int res;
+
+    // Perform RLE encoding
+    int count = 0, prev;
+    while (src < srcEnd)
+    {
+        Uint8 data = *src++;
+
+        if ((count >= rleMinCount && data != prev) || count >= rleMaxCount)
+        {
+            if (!dmEncodeGenericRLESequence(dst, prev, count + 1, rleMarker, rleType))
+            {
+                res = dmError(DMERR_MALLOC,
+                    "Could reallocate memory for RLE encoding buffer.\n");
+                goto err;
+            }
+
+            count = 1;
+        }
+
+        prev = data;
+    }
+
+    res = DMERR_OK;
+
+err:
+    return res;
+}
+
+
+static int dmEncodeGenericRLEAlloc(DMGrowBuf *dst, const Uint8 *src, const Uint8 *srcEnd,
+    const Uint8 rleMarker, const Uint8 rleMinCount, const Uint8 rleMaxCount, const int rleType)
+{
+    int res;
+    if ((res = dmGrowBufAlloc(dst, BUF_SIZE_INITIAL, BUF_SIZE_GROW)) != DMERR_OK)
+        return res;
+
+    return dmEncodeGenericRLE(dst, src, srcEnd, rleMarker, rleMinCount, rleMaxCount, rleType);
 }
 
 
@@ -370,7 +435,7 @@
     int res;
     DMGrowBuf mem;
 
-    if ((res = dmDecodeGenericRLE(&mem, buf + 0x0e, buf + len, *(buf + 0x0d), 0, 0, DM_RLE_MARKER)) != DMERR_OK)
+    if ((res = dmDecodeGenericRLEAlloc(&mem, buf + 0x0e, buf + len, *(buf + 0x0d), 0, 0, DM_RLE_MARKER)) != DMERR_OK)
         goto out;
 
     res = dmC64DecodeGenericBMP(img, mem.data, mem.len, fmt);