1 /**
2 Copyright: Copyright (c) 2015-2018 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 }