1 /** 2 Copyright: Copyright (c) 2015-2016 Andrey Penechko. 3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 Authors: Andrey Penechko. 5 */ 6 7 module voxelman.utils.rlecompression; 8 9 import std.range : put; 10 11 ubyte[] rleEncode(in ubyte[] data, ubyte[] outBuffer) 12 { 13 if (data.length == 0) return null; 14 15 ubyte[] original = outBuffer; 16 ubyte count = 1; 17 ubyte current = data[0]; 18 19 foreach(item; data[1..$]) 20 { 21 if (current == item && count < ubyte.max) 22 { 23 ++count; 24 } 25 else 26 { 27 put(outBuffer, count); 28 put(outBuffer, current); 29 count = 1; 30 current = item; 31 } 32 } 33 put(outBuffer, count); 34 put(outBuffer, current); 35 36 return original[0..$-outBuffer.length]; 37 } 38 39 ubyte[] rleDecode(in ubyte[] data, ubyte[] outBuffer) 40 { 41 if (data.length == 0) return null; 42 43 assert(data.length % 2 == 0); 44 ubyte[] original = outBuffer; 45 46 foreach(i; 0..data.length/2) 47 { 48 ubyte count = data[i*2]; 49 ubyte item = data[i*2 + 1]; 50 51 outBuffer[0..count] = item; 52 outBuffer = outBuffer[count..$]; 53 } 54 55 return original[0..$-outBuffer.length]; 56 } 57 58 unittest 59 { 60 ubyte[32] data = [0,0,0,0,0,1,1,1,1,2,2,2,2,0,0,0,0,0,1,0,4,0,1,0,0,0,0,0,0,0,0,1]; 61 ubyte[32] outBuffer; 62 assert(rleEncode(data, outBuffer) == [5,0,4,1,4,2,5,0,1,1,1,0,1,4,1,0,1,1,8,0,1,1]); 63 assert(rleDecode(rleEncode(data, outBuffer).dup, outBuffer) == data); 64 }