一个经典的图片压缩算法RLE行程编码
因为图片的连续像素点灰度值与色值一般都有很长的相同,例如这是一张图的部分byte[]
因此可以将byte[] 压缩为 值1*长度1#值2*长度2#
的格式,这种压缩算法在证件照、白底画等有大面积连续颜色区域的时候效果很好;而在每个相邻像素点都不同颜色or灰度值的情况下压缩后反而更大
1.压缩rleEncoder
public static String rleEncoder(byte[] src){
//初始化,存入第一个元素
StringBuffer stringBuffer = new StringBuffer(src[0] + "*");
//遍历 从第二个元素开始
int count = 1;
for(int i = 1 ; i < src.length ; i++){
//如果跟上一个元素相同
if(src[i] != src[i-1]) {
stringBuffer.append(count);
stringBuffer.append("#");//结束标志
stringBuffer.append(src[i]);
stringBuffer.append("*");
count = 1;//计数器归位
}else{
//相同元素计数器+1
count++;
}
}
stringBuffer.append(count);
stringBuffer.append("#");
return stringBuffer.toString();
}
2.解压rleDecoder
public static byte[] rleDecoder(String src){
//此时的src是形如0*2#11*1#2*1#3*1#4*1#55*5#的字符串
String s = src.replaceAll("\\#", "*");//方便分割
String[] split = s.split("\\*");
ArrayList<Byte> list = new ArrayList<Byte>();
Byte tempValue = 0;
int tempNumber = 0;
//偶数索引是值 奇数索引是数量
for(int i = 0 ; i < split.length ; i++){
//偶数是值
if((i&1) == 0){
tempValue = Byte.parseByte(split[i]);
//奇数是数量
}else{
tempNumber = Integer.parseInt(split[i]);
//确定值和数量之后for循环
for(int j = 0 ; j < tempNumber ; j++){
list.add(tempValue);
}
}
}
byte[] bytes = new byte[list.size()];
for(int i = 0 ; i < list.size() ; i++){
bytes[i] = list.get(i);
}
return bytes;
}
3.演示
String dest = rleEncoder(new byte[]{0,0,0,0,0,0,0,0,0,0,0,0,0,
6,6,6,6,6,6,6,6,6,6,6,6,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8});
byte[] bytes = rleDecoder(dest);
System.out.println(new String(bytes));