diff tools/lib64gfx.c @ 1650:9233da9de92c

Refactor RLE encoding a bit, and add support for 16bit run counts and make things more configurable.
author Matti Hamalainen <ccr@tnsp.org>
date Wed, 30 May 2018 03:25:34 +0300
parents 948d6fda722d
children 7555c8803529
line wrap: on
line diff
--- a/tools/lib64gfx.c	Wed May 30 01:29:09 2018 +0300
+++ b/tools/lib64gfx.c	Wed May 30 03:25:34 2018 +0300
@@ -282,7 +282,7 @@
 }
 
 
-void dmGenericRLEAnalyze(const DMGrowBuf *buf, Uint8 *rleMarker, const int rleType)
+void dmGenericRLEAnalyze(const Uint8 *buf, const size_t len, DMCompParams *cfg)
 {
 #define DM_STAT_MAX 256
     size_t *stats;
@@ -292,29 +292,37 @@
         return;
 
     // Get statistics on the data
-    for (size_t offs = 0; offs < buf->len; offs++)
-        stats[buf->data[offs]]++;
+    for (size_t offs = 0; offs < len; offs++)
+        stats[buf[offs]]++;
 
     // According to compression type ..
-    if (rleType == DM_COMP_RLE_MARKER1 || rleType == DM_COMP_RLE_MARKER2)
+    switch (cfg->type)
     {
-        size_t selected = 0,
-            smallest = buf->len;
-
-        // Find least used byte value
-        for (size_t n = 0; n < DM_STAT_MAX; n++)
-        {
-            if (stats[n] < smallest)
+        case DM_COMP_RLE_MARKER:
             {
-                selected = n;
-                smallest = stats[n];
-            }
-        }
+                size_t selected = 0,
+                    smallest = len;
 
-        *rleMarker = selected;
+                // Find least used byte value
+                for (size_t n = 0; n < DM_STAT_MAX; n++)
+                {
+                    if (stats[n] < smallest)
+                    {
+                        selected = n;
+                        smallest = stats[n];
+                    }
+                }
+
+                cfg->rleMarker1 = selected;
+            }
+            break;
+
+        case DM_COMP_RLE_MASK:
+            cfg->rleMarker1 = 0xC0;
+            cfg->rleMask1   = 0xC0;
+            cfg->rleMask2   = 0x3f;
+            break;
     }
-    else
-        *rleMarker = 0xC0;
 
     dmFree(stats);
 }
@@ -330,49 +338,71 @@
         Uint8 data = *src++;
         int count = 1;
 
-        switch (cfg->type)
+        if (cfg->type == DM_COMP_RLE_MARKER)
         {
-            case DM_COMP_RLE_MARKER1:
-            case DM_COMP_RLE_MARKER2:
-                // A simple marker byte RLE variant: [Marker] [count] [data]
-                if (data == cfg->rleMarker)
+            // A simple marker byte RLE variant: [Marker] [count] [data]
+            if (data == cfg->rleMarker1 && (cfg->flags & DM_RLE_8BIT_RUNS))
+            {
+                if (srcEnd - src + 1 < 2)
                 {
-                    if (srcEnd - src + 1 < 2)
-                    {
-                        res = DMERR_INVALID_DATA;
-                        goto err;
-                    }
+                    res = DMERR_INVALID_DATA;
+                    goto err;
+                }
 
-                    switch (cfg->type)
-                    {
-                        case DM_COMP_RLE_MARKER1:
-                            count = *src++;
-                            data = *src++;
-                            break;
+                switch (cfg->flags & DM_RLE_ORDER_MASK)
+                {
+                    case DM_RLE_ORDER_1:
+                        count = src[0];
+                        data = src[1];
+                        break;
 
-                        case DM_COMP_RLE_MARKER2:
-                            data = *src++;
-                            count = *src++;
-                            break;
-                    }
+                    case DM_RLE_ORDER_2:
+                        data = src[0];
+                        count = src[1];
+                        break;
                 }
-                break;
+                src += 2;
+            }
+            else
+            if (data == cfg->rleMarker2 && (cfg->flags & DM_RLE_16BIT_RUNS))
+            {
+                if (srcEnd - src + 1 < 3)
+                {
+                    res = DMERR_INVALID_DATA;
+                    goto err;
+                }
+
+                switch (cfg->flags & DM_RLE_ORDER_MASK)
+                {
+                    case DM_RLE_ORDER_1:
+                        count = (src[1] << 8) | src[0];
+                        data = src[2];
+                        break;
 
-            case DM_COMP_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 ((data & cfg->rleMask1) == cfg->rleMarker)
+                    case DM_RLE_ORDER_2:
+                        data = src[0];
+                        count = (src[2] << 8) | src[1];
+                        break;
+                }
+                src += 3;
+            }
+        }
+        else
+        if (cfg->type == DM_COMP_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 ((data & cfg->rleMask1) == cfg->rleMarker1)
+            {
+                if (srcEnd - src + 1 < 1)
                 {
-                    if (srcEnd - src + 1 < 1)
-                    {
-                        res = DMERR_INVALID_DATA;
-                        goto err;
-                    }
+                    res = DMERR_INVALID_DATA;
+                    goto err;
+                }
 
-                    count = data & cfg->rleMask2;
-                    data = *src++;
-                }
-                break;
+                count = data & cfg->rleMask2;
+                data = *src++;
+            }
         }
 
         while (count--)
@@ -408,23 +438,22 @@
 
     switch (cfg->type)
     {
-        case DM_COMP_RLE_MARKER1:
-        case DM_COMP_RLE_MARKER2:
-            if (count >= cfg->rleMinCount || data == cfg->rleMarker)
+        case DM_COMP_RLE_MARKER:
+            if (count >= cfg->rleMinCount || data == cfg->rleMarker1)
             {
                 // A simple marker byte RLE variant: [Marker] [count] [data]
-                if (!dmGrowBufPutU8(dst, cfg->rleMarker))
+                if (!dmGrowBufPutU8(dst, cfg->rleMarker1))
                     return FALSE;
 
-                switch (cfg->type)
+                switch (cfg->flags & DM_RLE_ORDER_MASK)
                 {
-                    case DM_COMP_RLE_MARKER1:
+                    case DM_RLE_ORDER_1:
                         if (!dmGrowBufPutU8(dst, count) ||
                             !dmGrowBufPutU8(dst, data))
                             return FALSE;
                         break;
 
-                    case DM_COMP_RLE_MARKER2:
+                    case DM_RLE_ORDER_2:
                         if (!dmGrowBufPutU8(dst, data) ||
                             !dmGrowBufPutU8(dst, count))
                             return FALSE;
@@ -436,11 +465,11 @@
             break;
 
         case DM_COMP_RLE_MASK:
-            if (count >= cfg->rleMinCount || (data & cfg->rleMarker) == cfg->rleMarker)
+            if (count >= cfg->rleMinCount || (data & cfg->rleMask1) == cfg->rleMarker1)
             {
                 // 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, cfg->rleMarker | count) ||
+                if (!dmGrowBufPutU8(dst, cfg->rleMarker1 | count) ||
                     !dmGrowBufPutU8(dst, data))
                     return FALSE;
             }