目录
针对字符的RLE压缩
针对一维对象的RLE压缩
针对二维图像的RLE压缩
至于为什么只考虑一位数:多位数可以用包装类Integer表示,并且实际压缩中不会单纯压缩字符,一般都是整个对象一起压缩,所以没必要两位相连的数与后面判断
public static StringBuffer RLE(char...chars){//行程编码方法,形参放char型数组 //因为频繁更改字符串,所以返回值不用String StringBuffer dest = new StringBuffer(); //注意:StringBuffer必须用new,不然不分配空间 //StringBuffer dest = null;会空指针异常 for(int i = 0 ; i<chars.length-1 ; i++){//chars数组遍历——————压缩 //每次轮到chars[i],都需要用if和屁股后面紧跟的元素判断是否相等 dest.append(chars[i]); dest.append('*'); int count = 1;//相等元素计数器 boolean bo = true; while(bo){//while循环直到碰不到一样的元素就break if(i<chars.length-1 && chars[i]==chars[i+1]){//必须要避免空指针异常 //注意:此处对i的判断必须在前,否则角标越界 //并且要用&& 不能用&,否则仍角标越界 count++; i++; }else{ bo = false; } } //循环结束,统计相同的个数 dest.append(count); dest.append('#');//标识符,#之后又开始新的判断 } return dest; }
//main方法中实现 String s1 = "1112233334455566777778889999"; StringBuffer s2 = RLE(s1.toCharArray()); System.out.println(s2.toString());
输出结果:1*3#2*2#3*4#4*2#5*3#6*2#7*5#8*3#9*4#
含义为:1出现了3次,2出现了2次......
先定义像素点:
public class PixelPoint {//一维像素点 private int grayScale;//灰度值 private int x;//x坐标 public PixelPoint(int grayScale,int x){ this.grayScale = grayScale; this.x = x; } public int getX(){ return this.x; } public int getGrayScale() { return grayScale; } }
定义像素点的压缩方法:
public static LinkedHashMap<PixelPoint,Integer> RLE(ArrayList<PixelPoint> px){ //形参放入ArryaList,返回值用LinkedHashMap存储键值对,并且LinkedHashMap可以按添加顺序遍历 LinkedHashMap<ZJH.HJZ.PixelPoint,Integer> linkedHashMap = new LinkedHashMap<>(); for(int i = 0 ; i < px.size() ; ){// int j = i; boolean bo = true; int count = 1;//计相同个数 while(bo){ if(i<px.size()-1){ if(px.get(i).getGrayScale() == px.get(i+1).getGrayScale()){ count++; i++; }else{ i++; bo = false; } } else{ bo = false; i++; } } linkedHashMap.put(px.get(j), count); } return linkedHashMap; }
载入像素点:并使用上面定义好的压缩方法,最后迭代器遍历(完整源码如下)
public class RLE_complex_one {//对一维像素点的RLE算法测试 public static void main(String[] args) { //此例中所有像素点x坐标连续分布,故暂不考虑排序,用ArrayList效率更高 ArrayList<ZJH.HJZ.PixelPoint> arrayList = new ArrayList<>(20);//初始容量设为20(默认是10,每次扩大1.5X) //以下模拟像素点的连续排布及灰度值情况 arrayList.add(new PixelPoint(1,1)); arrayList.add(new PixelPoint(1,2)); arrayList.add(new PixelPoint(1,3)); arrayList.add(new PixelPoint(1,4)); arrayList.add(new PixelPoint(1,5)); arrayList.add(new PixelPoint(50,6)); arrayList.add(new PixelPoint(50,7)); arrayList.add(new PixelPoint(50,8)); arrayList.add(new PixelPoint(50,9)); arrayList.add(new PixelPoint(255,10)); arrayList.add(new PixelPoint(255,11)); arrayList.add(new PixelPoint(255,12)); arrayList.add(new PixelPoint(255,13)); arrayList.add(new PixelPoint(255,14)); arrayList.add(new PixelPoint(255,15)); arrayList.add(new PixelPoint(255,16)); arrayList.add(new PixelPoint(255,17)); arrayList.add(new PixelPoint(255,18)); LinkedHashMap<ZJH.HJZ.PixelPoint, Integer> rleDest = RLE(arrayList);//返回编码结果 //以下用迭代器遍历 Set<Map.Entry<PixelPoint, Integer>> entries = rleDest.entrySet(); Iterator<Map.Entry<PixelPoint, Integer>> iterator = entries.iterator(); while(iterator.hasNext()){ int i = 1; Map.Entry<PixelPoint, Integer> nextentries = iterator.next(); System.out.println("第"+i+"位压缩后的元素的灰度值是:"+nextentries.getKey().getGrayScale()+",且压缩了"+nextentries.getValue()+"个连续的像素点"); i++; } } public static LinkedHashMap<PixelPoint,Integer> RLE(ArrayList<PixelPoint> px){ //形参放入ArryaList,返回值用LinkedHashMap存储键值对,并且LinkedHashMap可以按添加顺序遍历 LinkedHashMap<ZJH.HJZ.PixelPoint,Integer> linkedHashMap = new LinkedHashMap<>(); for(int i = 0 ; i < px.size() ; ){// int j = i; boolean bo = true; int count = 1;//计相同个数 while(bo){ if(i<px.size()-1){ if(px.get(i).getGrayScale() == px.get(i+1).getGrayScale()){ count++; i++; }else{ i++; bo = false; } } else{ bo = false; i++; } } linkedHashMap.put(px.get(j), count); } return linkedHashMap; } }
这样就把很多个连续的同值像素点压缩成了3个key-value对,数据量巨大的时候压缩效果很明显
上面的那个RLE是只考虑了一维的相关性,而考虑二维相关性的算法一般用WBS跳过白块编码,而不用RLE算法
把图像拆分为多个a×a的小方块,这个方块的灰度值相同
按上面的逻辑对方阵进行判断,具体实现十分复杂,matlab和python有现成的库,此文不再对此进行研究。
一维压缩不光可以用于图片处理,对于大量的连续值的数据存储压缩效果都很好