RLE行程编码算法的java实现

目录

针对字符的RLE压缩

针对一维对象的RLE压缩

针对二维图像的RLE压缩


针对字符的RLE压缩

  • 针对纯字符的压缩
  • 不考虑两位数及以上的循环
  • 例如:用1*2#5*3#表示:11555两个1三个5,即 数*重复次数#

至于为什么只考虑一位数:多位数可以用包装类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次......

针对一维对象的RLE压缩

  • 对象具有一个属性值和一个坐标值
  • 不考虑独立多属性值,因为很难重复

 先定义像素点:

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;
    }
}

RLE行程编码算法的java实现

这样就把很多个连续的同值像素点压缩成了3个key-value对,数据量巨大的时候压缩效果很明显

针对二维图像的RLE压缩

上面的那个RLE是只考虑了一维的相关性,而考虑二维相关性的算法一般用WBS跳过白块编码,而不用RLE算法

把图像拆分为多个a×a的小方块,这个方块的灰度值相同

按上面的逻辑对方阵进行判断,具体实现十分复杂,matlab和python有现成的库,此文不再对此进行研究。

一维压缩不光可以用于图片处理,对于大量的连续值的数据存储压缩效果都很好

上一篇:ArrayList和数组的一些比较


下一篇:扑克进阶