java - Java 中的游程编码图像压缩

标签 java image-processing image-compression run-length-encoding

好吧,我有一份大学作业,需要使用游程编码和霍夫曼编码来压缩图像。我专注于运行长度编码 atm,因为我认为我没有时间实现霍夫曼。

我目前正在做的是传入一个缓冲图像,然后做

public byte[] byteArray(BufferedImage image){
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    byte[] imageInByte = null;
    try{
        ImageIO.write(image, "BMP", baos);
        baos.flush();
        imageInByte = baos.toByteArray();
        baos.close();
    }catch(IOException e){
        System.out.println(e.getMessage());
    }

    return imageInByte;
}

获取图像的字节。 然后我采取它并进行实际的压缩,为了做到这一点,我使用了一个 stringBuffer ,我很确定这是错误的,但我想不出另一种方法来做到这一点。所以代码是

public String getRunLength(){
    StringBuffer dest = new StringBuffer();        
    for(int i =0; i < imageByteArray.length; i++){
        int runlength = 1;
        while(i+1 < imageByteArray.length && imageByteArray[i] == imageByteArray[i+1]){
            runlength++;
            i++;

        }     


        dest.append(runlength);  

        dest.append(imageByteArray[i]);

    }
    return dest.toString();
}

我很确定我不应该转换为字符串,因为当我返回字节时,我将得到 ascii 值而不是实际的字节。但我不知道如何有效地将游程长度附加到标准字节数组(我想如果我将游程长度附加到开头,然后将 byte[i+runLength] 之后的所有内容向下移动,我就可以做到这一点数组中的 runLength 数量..但这将非常低效并且容易出错...可能)

然后我需要将其保存为图像,这显然目前不起作用,但我目前获得的代码是

 try{
        File newImage = new File("Saved.png");
        ImageIO.write(rleImage, "BMP", newImage);
    }catch(Exception e){
        System.out.println("something fucked up");
    }

感谢您提供的任何帮助:)

刚刚注意到我错过了设置 rleImage 的部分

 public BufferedImage stringToImage(String runLengthEncode){
    ByteArrayInputStream bais = new ByteArrayInputStream(runLengthEncode.getBytes());
    try{
        imageRLE = ImageIO.read(new ByteArrayInputStream(runLengthEncode.getBytes()));
    }catch(IOException e){

    }
    //decode(runLengthEncode);
    if(imageRLE == null)
        System.out.println("imageRLE is null");
    return imageRLE;
}

最佳答案

您应该能够以与使用 StringBuffer 完全相同的方式使用 ByteArrayOutputStream:

public byte[] getRunLength(){
    ByteArrayOutputStream dest = new ByteArrayOutputStream();        
    for(int i =0; i < imageByteArray.length; i++){
        int runlength = 1;
        while(i+1 < imageByteArray.length && imageByteArray[i] == imageByteArray[i+1]){
            runlength++;
            i++;

        }     

        dest.write((byte)runlength);  
        dest.write((byte)imageByteArray[i]);
    }
    return dest.toByteArray();
}

这避免了整个转换为 char 并返回。

顺便说一句,该算法效率低下,而且可能是错误的。您迭代每个字符,然后对于每个字符,您期待字符的跨度。你不需要这样做。您已经遍历了所有字符,因此您需要做的就是记住最后一个字符是什么,并进行相应的操作。

public byte[] getRunLength(){
    ByteArrayOutputStream dest = new ByteArrayOutputStream();  
    byte lastByte = imageByteArray[0];
    int matchCount = 1;
    for(int i=1; i < imageByteArray.length; i++){
        byte thisByte = imageByteArray[i];
        if (lastByte == thisByte) {
            matchCount++;
        }
        else {
            dest.write((byte)matchCount);  
            dest.write((byte)lastByte);
            matchCount=1;
            lastByte = thisByte;
        }                
    }
    dest.write((byte)matchCount);  
    dest.write((byte)lastByte);
    return dest.toByteArray();
}

您将看到这仅触及每个字节值一次。

关于java - Java 中的游程编码图像压缩,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27158610/

相关文章:

java - 从 int 中获取字节以避免移位乐趣 - Java(中值过滤)

image-processing - 即时无损图像压缩

Flutter Web : How Do You Compress an Image/File?

Java泛型问题

java - Lucene - 关键词归档困惑

java - 在文本字段中使用 if/else 吗?

opencv - opencv 2.4.5无法在Windows中正确加载tif图像文件

java - 访问 MQTT 异步消息

image-processing - 有没有人在 OpenCV 中使用 MSER 来检测区域?

java - 调整某些图像大小时抛出异常 "java.awt.color.CMMException: Invalid image format"...为什么?