# HG changeset patch # User Matti Hamalainen # Date 1525995769 -10800 # Node ID d883b4c1cf4810969541a380754c3c60396abfd2 # Parent e8fe529f43413adcf4eee1bfcbeac4821c883d80 More work on RLE encoding/decoding. diff -r e8fe529f4341 -r d883b4c1cf48 tools/lib64gfx.c --- 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);