Okay so i've got a University assignment where I need to compress an image using both Run-length encoding and huffman encoding. I'm focusing on the Run-Length encoding atm since I don't think i'm going to have time to implement the huffman.
What I am currently doing is passing in a buffered image, Then doing
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;
}
to get the byte's of the image. I then take that and do the actual compression, to do this atm I'm using a stringBuffer which I'm pretty sure is wrong but I can't think of another way to do it. so the code for that is
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();
}
I'm pretty sure I shouldn't be converting to a string since when I go back to the bytes then I will be getting the ascii values rather than the actual bytes. But I can't figure out how I would go about appending the run length to a standard Byte Array efficiently (I think I could do it if I appended the run length to the start, then moved everything after byte[i+runLength] down runLength amount in the array.. but that would be extremely inefficient and prone to error... probably)
I then need to save it as an image, which obviously isn't working at the moment but the code i've currently got for that is
try{
File newImage = new File("Saved.png");
ImageIO.write(rleImage, "BMP", newImage);
}catch(Exception e){
System.out.println("something fucked up");
}
Thanks for any help you might be able to provide :)
Just noticed I missed out the part where I set the rleImage that is done like
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;
}
You should be able to use a ByteArrayOutputStream in the exact same way you use the StringBuffer:
This avoids the whole convert to char and back.
By the way, the algorithm is inefficient and probably wrong. You iterate over each character, and then for each character you look forward for the span of characters. You don't need to do that. You are already walking through all the characters, so all you need to do is remember what the last character was, and ac accordingly.
You will see that this touches each byte value only once.