Mercurial > hg > dmlib
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; }