好吧,我有一份大学作业,需要使用游程编码和霍夫曼编码来压缩图像。我专注于运行长度编码 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/