25

From pagespeed I am getting only image link and possible optimizations in bytes & percentage like, Compressing and resizing https://example.com/…ts/xyz.jpg?036861 could save 212KiB (51% reduction). Compressing https://example.com/…xyz.png?303584508 could save 4.4KiB (21% reduction).

For an example I have image of size 300kb and for this image pagespeed is displaying 100kb & 30% of reduction.

This is only for one image but I am sure I will have lots of images for compression. so how can I compress image by passing bytes or percentage as a parameter or using anyother calculations in java (by using API or image-processing Tool) so,that I can get compressed version of image as suggested by google.

Thanks in advance.

Darshit Patel
  • 700
  • 1
  • 6
  • 16

4 Answers4

38

You can use Java ImageIO package to do the compression for many images formats, here is an example

import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Iterator;
import javax.imageio.*;
import javax.imageio.stream.*;

public class Compresssion {

  public static void main(String[] args) throws IOException {

    File input = new File("original_image.jpg");
    BufferedImage image = ImageIO.read(input);

    File compressedImageFile = new File("compressed_image.jpg");
    OutputStream os = new FileOutputStream(compressedImageFile);

    Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
    ImageWriter writer = (ImageWriter) writers.next();

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

    ImageWriteParam param = writer.getDefaultWriteParam();

    param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
    param.setCompressionQuality(0.05f);  // Change the quality value you prefer
    writer.write(null, new IIOImage(image, null, null), param);

    os.close();
    ios.close();
    writer.dispose();
  }
}

You can find more details about it here

Also there are some third party tools like these

EDIT: If you want to use Google PageSpeed in your application, it is available as web server module either for Apache or Nginx, you can find how to configure it for your website here

https://developers.google.com/speed/pagespeed/module/

But if you want to integrate the PageSpeed C++ library in your application, you can find build instructions for it here.

https://developers.google.com/speed/pagespeed/psol

It also has a Java Client here

https://github.com/googleapis/google-api-java-client-services/tree/main/clients/google-api-services-pagespeedonline/v5

nitin737
  • 39
  • 8
fujy
  • 5,168
  • 5
  • 31
  • 50
  • 1
    Using ImageWriteParam I got the compressed version of images but I am not getting required compression whatever google page speed is suggesting. so, basically I want compressed version of image whatever google page speed is suggesting . – Darshit Patel Jun 16 '17 at 08:23
  • A lot of interesting information on this answer. Thanks :) –  Dec 23 '17 at 21:14
  • 1
    What about resizing? Resizing is the main way to reduce file size. – Tim Cooper Jan 19 '18 at 02:02
  • This works with jpg/jpeg images as written. If image is a png image the following code throws exception even if you use get image writer for png – Aekansh Kansal Oct 04 '21 at 13:01
10

There is colour compression ("compression quality") and there is resolution compression ("resizing"). Fujy's answer deals with compression quality, but this is not where the main savings come from: the main savings come from resizing down to a smaller size. E.g. I got a 4mb photo to 207K using the maximum compression quality using fujy's answer, and it looked awful, but I got it down to 12K using a reasonable quality but a smaller size.

So the above code should be used for "compression quality", but this is my recommendation for resizing:

https://github.com/rkalla/imgscalr/blob/master/src/main/java/org/imgscalr/Scalr.java

I wish resizing was part of the standard Java libraries, but it seems it's not, (or there are image quality problems with the standard methods?). But Riyad's library is really small - it's just one class. I just copied this class into my project, because I never learnt how to use Maven, and it works great.

Tim Cooper
  • 10,023
  • 5
  • 61
  • 77
  • 1
    The code you given is hard to understand, can you give another code please... – John dahat Jun 21 '20 at 11:44
  • @Johndahat Copy paste Scalr class from URL above. Then, you may use it, such as `BufferedImage img = Scalr.resize(ImageIO.read(src), 500);` where `src` is a `File`, `URL` or `InputStream`. – Miguel Gamboa Dec 23 '21 at 13:29
3

One liner java solution: thumbnailator.

Maven dependency:

<!-- https://mvnrepository.com/artifact/net.coobird/thumbnailator -->
<dependency>
    <groupId>net.coobird</groupId>
    <artifactId>thumbnailator</artifactId>
    <version>0.4.17</version>
</dependency>

The one liner:

Thumbnails.of(inputImagePathString).scale(scalingFactorFloat).outputQuality(qualityFactorFloat).toFile(outputImagePathString);
derek.z
  • 907
  • 11
  • 19
1

As a solution for this problem I can recommend the API of TinyPNG.
You can use it for compressing as well as resizing the image.

Documentation: tinypng.com/developers/reference/java

tgallei
  • 827
  • 3
  • 13
  • 22
  • 2
    unfortunately it has web API only which brings some network delay to processing. Do they have any client library which does the compression clientside without the need of API? – michal.jakubeczy Mar 27 '20 at 15:37