-2

I need to compress every image that is larger than 500 kbytes. So, i'm trying to create a code that will test every compression quality until i get <= 500 kb, then i'll have the best quality with the lowest length.

My biggest problem here is that writer method from ImageWriter appends my new image to the old. So, if i have a 600kb image and write a new one with low quality, i'll have 600kb + probably 500kb (size of the new image) in the same .jpg file and with a low quality.

My code:

public byte[] imageCompressor(String filePath, String newFileName, String formatName) throws IOException {

    File input = new File(filePath);
    BufferedImage image = ImageIO.read(input);

    File compressedImageFile = new File(newFileName);
    String compressedWithFormat = compressedImageFile + "." + formatName;
    OutputStream os = new FileOutputStream(compressedWithFormat);

    Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName);
    ImageWriter writer = (ImageWriter) writers.next();
    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    ImageOutputStream ios = ImageIO.createImageOutputStream(os);
    writer.setOutput(ImageIO.createImageOutputStream(baos));

    ImageWriteParam param = writer.getDefaultWriteParam();
    param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
    writer.write(null, new IIOImage(image, null, null), param);
    float contador = 1f;

    while (imageSizeChecker(compressedWithFormat) > 500) {
        param.setCompressionQuality(contador -= 0.09f); // Change the quality value you prefer
        writer.write(null, new IIOImage(image, null, null), param);
        System.out.println(imageSizeChecker(compressedWithFormat));
        writer.dispose();
    }

    writer.dispose();
    return baos.toByteArray();
}

public Long imageSizeChecker(String filePath) {
    File insertFile = new File(filePath);
    Long fileSize = insertFile.length() / 1024;

    return fileSize;
}

Also, i want to return the image in a byte array (as it follows), and i'm trying to send the image file on the parameter as a byte array (replacing String filepath for byte[] filepath)

  • _"ImageWriter appends my new image to the old"_ -- so write the new image to a different file. What is the question here? – Jim Garrison Mar 21 '18 at 20:17
  • He creates a new one, parameter newFileName. But i don't want to do this in a manual way (maybe the code will need to compress a image with 1mb more than twice, so i'll need to keep creating three or more files?) It will run in a robot, and i need to compress the attachments bigger than 500kb – Marcos Silva Mar 21 '18 at 20:18

1 Answers1

0

You keep writing multiple images to the same ByteArrayOutputStream. To reset the output stream and discard the data between each image, you can use:

baos.reset();

There are several other problems -- such as inspecting a file you never write -- but if you're finding that appended data is the major problem, this seems to be why.

that other guy
  • 116,971
  • 11
  • 170
  • 194
  • I hadn't tought this cause i was trying to create a new image file before, then i realized that trying by byte array could be successfull – Marcos Silva Mar 21 '18 at 20:33