/*******************************************************************************
* Copyright (c) 2005-2011, G. Weirich and Elexis
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* G. Weirich - initial implementation
*
*******************************************************************************/
package ch.rgw.compress;
import java.io.ByteArrayOutputStream;
import ch.rgw.tools.IntTool;
/**
* RLL Commpressor/Decompressor
*
* @author Gerry
*/
public class RLL {
public static String Version(){
return "0.2.1";
}
/**
* compress the source array. use rllchar as character to indicate repetition. if rllchar is
* 0x0, the least frequent character from source will be used.
*
* @return a newly created array with the rll compressed data.
*/
public static byte[] compress(byte rllchar, byte[] source){
if (rllchar == (byte) 0) {
int[] freq = HuffmanTree.constructTable(source);
int min = 100000;
for (int i = 0; i < freq.length; i++) {
if (freq[i] == 0) {
rllchar = (byte) i;
break;
}
if (freq[i] < min) {
min = freq[i];
rllchar = (byte) i;
}
}
}
ByteArrayOutputStream baos = new ByteArrayOutputStream(source.length);
baos.write(rllchar);
int i;
for (i = 0; i < source.length - 3; i++) {
if ((source[i] == source[i + 1]) && (source[i + 1] == source[i + 2])) {
int rep = 3;
while (((i + rep) < source.length) && source[i + rep] == source[i]) {
if (rep == 254)
break;
rep++;
}
baos.write(rllchar);
baos.write(rep);
baos.write(source[i]);
i += rep - 1;
} else if (source[i] == rllchar) {
baos.write(rllchar);
baos.write(1);
} else {
baos.write(source[i]);
}
}
while (i < source.length) {
baos.write(source[i++]);
}
return baos.toByteArray();
}
/**
* Expand a rll-compressed array
*
* @param source
* the compressed array. First byte must be the rllchar.
* @return a newly created array with the expanded data.
*/
public static byte[] expand(byte[] source){
ByteArrayOutputStream baos = new ByteArrayOutputStream(source.length);
byte rllchar = source[0];
int i;
for (i = 1; i < source.length - 2; i++) {
if (source[i] == rllchar) {
if (source[i + 1] == 1) {
baos.write(rllchar);
i++;
} else {
int k = IntTool.ByteToInt(source[i + 1]);
while (k-- > 0) {
baos.write(source[i + 2]);
}
i += 2;
}
} else {
baos.write(source[i]);
}
}
while (i < source.length) {
baos.write(source[i++]);
}
return baos.toByteArray();
}
}