好的,所以我有一个大学任务,我需要使用行程编码和霍夫曼编码来压缩图像。我专注于运行长度编码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值而不是实际字节。但是我无法弄清楚如何有效地将运行长度附加到标准字节数组(我想如果我将运行长度添加到开头,我会做到这一点,然后在字节之后移动所有内容[i + 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;
}
答案 0 :(得分:2)
您应该能够以与使用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();
}
您将看到这只触及每个字节值一次。
答案 1 :(得分:0)
您在ByteArrayOutputStream中使用刷新,这将为您提供错误的信息 要使您的代码运行,只需删除行
public byte[] byteArray(BufferedImage image){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] imageInByte = null;
try{
ImageIO.write(image, "BMP", baos);
imageInByte = baos.toByteArray();
baos.close();
}catch(IOException e){
System.out.println(e.getMessage());
}
return imageInByte;
}