131

I need to resize PNG, JPEG and GIF files. How can I do this using Java?

Kara
  • 6,115
  • 16
  • 50
  • 57
pbreault
  • 14,176
  • 18
  • 45
  • 38
  • 14
    since you asked for a library, the real answer is here: http://stackoverflow.com/questions/244164/resize-an-image-in-java-any-open-source-library/4528136#4528136. It's much easier to use than the code in accepted answer ;) – Artur Gajowy Mar 03 '11 at 10:16
  • I disagree on the library part: Graphics2D is part of the awt library and it is open source. For the last part (open source) I am not 100% sure, but who would look at the awt code anyway? – Burkhard Aug 30 '11 at 15:46

19 Answers19

186

FWIW I just released (Apache 2, hosted on GitHub) a simple image-scaling library for Java called imgscalr (available on Maven central).

The library implements a few different approaches to image-scaling (including Chris Campbell's incremental approach with a few minor enhancements) and will either pick the most optimal approach for you if you ask it to, or give you the fastest or best looking (if you ask for that).

Usage is dead-simple, just a bunch of static methods. The simplest use-case is:

BufferedImage scaledImage = Scalr.resize(myImage, 200);

All operations maintain the image's original proportions, so in this case you are asking imgscalr to resize your image within a bounds of 200 pixels wide and 200 pixels tall and by default it will automatically select the best-looking and fastest approach for that since it wasn't specified.

I realize on the outset this looks like self-promotion (it is), but I spent my fair share of time googling this exact same subject and kept coming up with different results/approaches/thoughts/suggestions and decided to sit down and write a simple implementation that would address that 80-85% use-cases where you have an image and probably want a thumbnail for it -- either as fast as possible or as good-looking as possible (for those that have tried, you'll notice doing a Graphics.drawImage even with BICUBIC interpolation to a small enough image, it still looks like garbage).

Simon Forsberg
  • 13,086
  • 10
  • 64
  • 108
Riyad Kalla
  • 10,604
  • 7
  • 53
  • 56
  • 1
    Riyad, I liked using Scalr. I am curious to know, how did you end up picking an API with all static methods? I had written a similar api which was closer to a builder. Like `new ImageScaler(img).resizeTo(...).rotate(...).cropTo(...).toOutputBuffer()`. I like your way too and I think it is simpler. – Amir Raminfar Nov 22 '11 at 15:47
  • 4
    Amir, the builder pattern works wonderfully for these types of libraries as well, I just happened to go with the static-method approach because I thought it was a *hair* easier to follow for new users and the usage-pattern I expected from imgscalr (originally only single resize methods) didn't benefit from having an instance holding state (The builder instance). So I saved on the object instantiation and went with the static methods. I have taken a strong stance against object-creation inside of imgscalr in every place I can avoid it. Both approaches work great though. – Riyad Kalla Nov 24 '11 at 02:00
  • 6
    +1 for making this available on the central Maven repository! – Grilse Sep 21 '12 at 11:59
  • What is this BufferedImage class , Why android studio does not find it ?@Riyad Kalla – Milad Mar 22 '15 at 19:02
  • 3
    @xe4me BufferedImage is a class in the J2SE JDK (part of the Java2D framework) used to represent raw, uncompressed pixel data. It is not available on Android, Android provides it's own classes to work with image data. – Riyad Kalla Mar 23 '15 at 19:26
  • Hi Ryad, I need to resize an embedded image but get following error? The method resize(BufferedImage, int, BufferedImageOp...) in the type Scalr is not applicable for the arguments (Embedded, int) – Noosrep Jul 16 '15 at 13:38
  • @TimothyPersoon imgscalr only takes a BufferedImage argument, I don't know what type 'Embedded' is... is this Android? imgscalr won't work on Android because it's missing the underlying Java2D/ImageIO libraries it's based on. Android ships their own solution. – Riyad Kalla Jul 17 '15 at 14:30
  • It's from Vaadin actually – Noosrep Jul 19 '15 at 08:21
  • 1
    Thanks for the API. To convert a base image 24x7 to 256x256. The code would look like img=Scalr.resize(img,Mode.FIT_EXACT,256,256); – math_law Dec 21 '16 at 08:31
  • @RiyadKalla Thank you. Could you please upload an example? I want to take a small image and increase its size without losing detail. Examples would really sell it to people like me, because I want to know what I'm getting out before I put time in to learn to use Maven. Thanks again – Nathan majicvr.com Apr 20 '18 at 14:45
  • @frank You can download jars directly from Maven central if you don't want to use Maven. – Manius Feb 03 '19 at 17:14
90

After loading the image you can try:

BufferedImage createResizedCopy(Image originalImage, 
            int scaledWidth, int scaledHeight, 
            boolean preserveAlpha)
    {
        System.out.println("resizing...");
        int imageType = preserveAlpha ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
        BufferedImage scaledBI = new BufferedImage(scaledWidth, scaledHeight, imageType);
        Graphics2D g = scaledBI.createGraphics();
        if (preserveAlpha) {
            g.setComposite(AlphaComposite.Src);
        }
        g.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null); 
        g.dispose();
        return scaledBI;
    }
Burkhard
  • 14,596
  • 22
  • 87
  • 108
  • 9
    I found this technique creates an image which isn't high-enough quality for my needs. – morgancodes Aug 10 '10 at 21:49
  • 1
    will Image.getScaledInstance(width,height,hints) also do? – codeplay Jan 21 '11 at 03:55
  • 1
    is the preserveAlpha check the wrong way around (for the imageType)? – Thilo Aug 18 '12 at 04:13
  • I agree with @morgancodes. The image quality is much worse than what you get with for example OS X Preview when resizing to the same dimensions. Will try some open-source libraries to see if they fare better. – Thilo Aug 23 '12 at 23:11
  • 1
    "Will try some open-source libraries to see if they fare better. " +1 for imgscalr from @RiyadKalla's answer. – Thilo Aug 24 '12 at 01:29
  • To shrink an image, it worked ok for me. But yes, the preserveAlpha check should be the other way around. – William Aug 03 '17 at 15:28
  • A more functional example with java 11 is available here https://medium.com/@SatyaRaj_PC/simple-java-image-scaling-and-cropping-33f95e7d9278 – SatyaRajC Feb 18 '22 at 11:08
56

Thumbnailator is an open-source image resizing library for Java with a fluent interface, distributed under the MIT license.

I wrote this library because making high-quality thumbnails in Java can be surprisingly difficult, and the resulting code could be pretty messy. With Thumbnailator, it's possible to express fairly complicated tasks using a simple fluent API.

A simple example

For a simple example, taking a image and resizing it to 100 x 100 (preserving the aspect ratio of the original image), and saving it to an file can achieved in a single statement:

Thumbnails.of("path/to/image")
    .size(100, 100)
    .toFile("path/to/thumbnail");

An advanced example

Performing complex resizing tasks is simplified with Thumbnailator's fluent interface.

Let's suppose we want to do the following:

  1. take the images in a directory and,
  2. resize them to 100 x 100, with the aspect ratio of the original image,
  3. save them all to JPEGs with quality settings of 0.85,
  4. where the file names are taken from the original with thumbnail. appended to the beginning

Translated to Thumbnailator, we'd be able to perform the above with the following:

Thumbnails.of(new File("path/to/directory").listFiles())
    .size(100, 100)
    .outputFormat("JPEG")
    .outputQuality(0.85)
    .toFiles(Rename.PREFIX_DOT_THUMBNAIL);

A note about image quality and speed

This library also uses the progressive bilinear scaling method highlighted in Filthy Rich Clients by Chet Haase and Romain Guy in order to generate high-quality thumbnails while ensuring acceptable runtime performance.

Jacob van Lingen
  • 8,989
  • 7
  • 48
  • 78
coobird
  • 159,216
  • 35
  • 211
  • 226
  • 1
    coobird, really nice job with the API. Very straight forward and easy to use. – Riyad Kalla Jun 21 '11 at 00:55
  • @LordT: I'm glad you found Thumbnailator to be easy to use :) – coobird Jul 13 '11 at 14:28
  • How can i create 80x80 thumbnail with 500x400 orginal image? i didn't see any option for it. thanks! – terry Sep 03 '12 at 16:20
  • ".outputFormat("JPEG")" is written nowhere in the documentation. – Vincent Cantin Feb 08 '13 at 07:45
  • @Vincent The complete list of methods which can be used is in the Thumbnailator API Documentation -- http://thumbnailator.googlecode.com/hg/javadoc/net/coobird/thumbnailator/Thumbnails.Builder.html – coobird Feb 08 '13 at 16:44
  • This library uses BufferredImage , while android SDK does not support that , is there fix here ? – Milad Mar 22 '15 at 19:43
  • I also had a positive experience with this. It supports streams which was perfect for my SSH client. – Sridhar Sarnobat Jul 04 '15 at 22:10
  • @terry you can do the following: `Thumbnails.of(..).size(80,80).crop(Positions.CENTER).toFile( ... )`. This will first resize the width or height to 80 and after that crop from the center. – Wim Deblauwe Jan 21 '16 at 12:04
  • works well, 100% improvement in quality over trying for too long to use java native methods! – user2677034 Mar 09 '20 at 21:29
13

You don't need a library to do this. You can do it with Java itself.

Chris Campbell has an excellent and detailed write-up on scaling images - see this article.

Chet Haase and Romain Guy also have a detailed and very informative write-up of image scaling in their book, Filthy Rich Clients.

David Koelle
  • 20,726
  • 23
  • 93
  • 130
  • 7
    Chris's article is exactly what motivated me to write imgscalr in the first place; and questions like this (and answers like yours). A lot of people asking over and over and over again how to get good looking thumbnails from an image. There are a number of ways to do it, Chris's isn't *always* the best way, it depends on what you are trying to do and how big the reduction is. imgscalr addresses all of that and it's 1 class. – Riyad Kalla May 17 '11 at 03:00
  • 2
    +1, I agree, Filthy Rich clients is one of the best java books out there on par with "Effective java", But ImgScalr is what I use because I am lazy. – Shawn Vader Mar 03 '14 at 09:40
  • @RiyadKalla Where is this library you talk of? Your website does not work: http://ww1.thebuzzmedia.com/ – TheRealChx101 Aug 19 '21 at 19:12
10

Java Advanced Imaging is now open source, and provides the operations you need.

Ken Gentle
  • 13,277
  • 2
  • 41
  • 49
9

If you are dealing with large images or want a nice looking result it's not a trivial task in java. Simply doing it via a rescale op via Graphics2D will not create a high quality thumbnail. You can do it using JAI, but it requires more work than you would imagine to get something that looks good and JAI has a nasty habit of blowing our your JVM with OutOfMemory errors.

I suggest using ImageMagick as an external executable if you can get away with it. Its simple to use and it does the job right so that you don't have to.

Joel Carranza
  • 967
  • 2
  • 12
  • 19
4

If, having imagemagick installed on your maschine is an option, I recommend im4java. It is a very thin abstraction layer upon the command line interface, but does its job very well.

naltatis
  • 2,953
  • 2
  • 18
  • 9
3

The Java API does not provide a standard scaling feature for images and downgrading image quality.

Because of this I tried to use cvResize from JavaCV but it seems to cause problems.

I found a good library for image scaling: simply add the dependency for "java-image-scaling" in your pom.xml.

<dependency>
    <groupId>com.mortennobel</groupId>
    <artifactId>java-image-scaling</artifactId>
    <version>0.8.6</version>
</dependency>

In the maven repository you will get the recent version for this.

Ex. In your java program

ResampleOp resamOp = new ResampleOp(50, 40);
BufferedImage modifiedImage = resamOp.filter(originalBufferedImage, null);
Neuron
  • 5,141
  • 5
  • 38
  • 59
Ruju
  • 961
  • 1
  • 12
  • 24
  • It's also available on GitHub (https://github.com/mortennobel/java-image-scaling.git) and it has version 8.7 as for now. It needed li'l fix in pom.xml, thou (changing source and target to at least 1.6 as newer Maven doesn't support 1.5 anymore). – Cromax Jan 15 '18 at 23:41
2

You could try to use GraphicsMagick Image Processing System with im4java as a comand-line interface for Java.

There are a lot of advantages of GraphicsMagick, but one for all:

  • GM is used to process billions of files at the world's largest photo sites (e.g. Flickr and Etsy).
kajo
  • 5,631
  • 4
  • 31
  • 29
1

Simply use Burkhard's answer but add this line after creating the graphics:

    g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);

You could also set the value to BICUBIC, it will produce a better quality image but is a more expensive operation. There are other rendering hints you can set but I have found that interpolation produces the most notable effect. Keep in mind if you want to zoom in in a lot, java code most likely will be very slow. I find larger images start to produce lag around 300% zoom even with all rendering hints set to optimize for speed over quality.

1

It turns out that writing a performant scaler is not trivial. I did it once for an open source project: ImageScaler.

In principle 'java.awt.Image#getScaledInstance(int, int, int)' would do the job as well, but there is a nasty bug with this - refer to my link for details.

aanno
  • 638
  • 8
  • 17
1

Image Magick has been mentioned. There is a JNI front end project called JMagick. It's not a particularly stable project (and Image Magick itself has been known to change a lot and even break compatibility). That said, we've had good experience using JMagick and a compatible version of Image Magick in a production environment to perform scaling at a high throughput, low latency rate. Speed was substantially better then with an all Java graphics library that we previously tried.

http://www.jmagick.org/index.html

Jice
  • 51
  • 4
1

You can use Marvin (pure Java image processing framework) for this kind of operation: http://marvinproject.sourceforge.net

Scale plug-in: http://marvinproject.sourceforge.net/en/plugins/scale.html

Gabriel Archanjo
  • 4,547
  • 2
  • 34
  • 41
Robert
  • 11
  • 1
0

you can use following popular product: thumbnailator

gstackoverflow
  • 36,709
  • 117
  • 359
  • 710
0

If you dont want to import imgScalr like @Riyad Kalla answer above which i tested too works fine, you can do this taken from Peter Walser answer @Peter Walser on another issue though:

 /**
     * utility method to get an icon from the resources of this class
     * @param name the name of the icon
     * @return the icon, or null if the icon wasn't found.
     */
    public Icon getIcon(String name) {
        Icon icon = null;
        URL url = null;
        ImageIcon imgicon = null;
        BufferedImage scaledImage = null;
        try {
            url = getClass().getResource(name);

            icon = new ImageIcon(url);
            if (icon == null) {
                System.out.println("Couldn't find " + url);
            }

            BufferedImage bi = new BufferedImage(
                    icon.getIconWidth(),
                    icon.getIconHeight(),
                    BufferedImage.TYPE_INT_RGB);
            Graphics g = bi.createGraphics();
            // paint the Icon to the BufferedImage.
            icon.paintIcon(null, g, 0,0);
            g.dispose();

            bi = resizeImage(bi,30,30);
            scaledImage = bi;// or replace with this line Scalr.resize(bi, 30,30);
            imgicon = new ImageIcon(scaledImage);

        } catch (Exception e) {
            System.out.println("Couldn't find " + getClass().getName() + "/" + name);
            e.printStackTrace();
        }
        return imgicon;
    }

 public static BufferedImage resizeImage (BufferedImage image, int areaWidth, int areaHeight) {
        float scaleX = (float) areaWidth / image.getWidth();
        float scaleY = (float) areaHeight / image.getHeight();
        float scale = Math.min(scaleX, scaleY);
        int w = Math.round(image.getWidth() * scale);
        int h = Math.round(image.getHeight() * scale);

        int type = image.getTransparency() == Transparency.OPAQUE ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;

        boolean scaleDown = scale < 1;

        if (scaleDown) {
            // multi-pass bilinear div 2
            int currentW = image.getWidth();
            int currentH = image.getHeight();
            BufferedImage resized = image;
            while (currentW > w || currentH > h) {
                currentW = Math.max(w, currentW / 2);
                currentH = Math.max(h, currentH / 2);

                BufferedImage temp = new BufferedImage(currentW, currentH, type);
                Graphics2D g2 = temp.createGraphics();
                g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                g2.drawImage(resized, 0, 0, currentW, currentH, null);
                g2.dispose();
                resized = temp;
            }
            return resized;
        } else {
            Object hint = scale > 2 ? RenderingHints.VALUE_INTERPOLATION_BICUBIC : RenderingHints.VALUE_INTERPOLATION_BILINEAR;

            BufferedImage resized = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2 = resized.createGraphics();
            g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
            g2.drawImage(image, 0, 0, w, h, null);
            g2.dispose();
            return resized;
        }
    }
Community
  • 1
  • 1
shareef
  • 9,255
  • 13
  • 58
  • 89
0

Try this folowing method :

ImageIcon icon = new ImageIcon("image.png");
Image img = icon.getImage();
Image newImg = img.getScaledInstance(350, 350, java.evt.Image.SCALE_SMOOTH);
icon = new ImageIcon(img);
JOptionPane.showMessageDialog(null, "image on The frame", "Display Image", JOptionPane.INFORMATION_MESSAGE, icon);
0

you can also use

Process p = Runtime.getRuntime().exec("convert " + origPath + " -resize 75% -quality 70 " + largePath + "");
            p.waitFor();
Aqib Butt
  • 89
  • 1
  • 2
0

Design jLabel first:

JLabel label1 = new JLabel("");
label1.setHorizontalAlignment(SwingConstants.CENTER);
label1.setBounds(628, 28, 169, 125);
frame1.getContentPane().add(label1);   //frame1 = "Jframe name"

Then you can code below code(add your own height and width):

ImageIcon imageIcon1 = new ImageIcon(new ImageIcon("add location url").getImage().getScaledInstance(100, 100, Image.SCALE_DEFAULT)); //100, 100 add your own size
label1.setIcon(imageIcon1);
0

I have developed a solution with the freely available classes ( AnimatedGifEncoder, GifDecoder, and LWZEncoder) available for handling GIF Animation.
You can download the jgifcode jar and run the GifImageUtil class. Link: http://www.jgifcode.com

Community
  • 1
  • 1
  • 1
    Please mention in the answer if you're affiliated with the product you recommend. – Hans Olsson Feb 27 '12 at 10:44
  • waw... is that for resizing GIF Animated image? and it's free ?? Wwaww... i should try it on now... – gumuruh Feb 28 '12 at 06:50
  • Yes this is developed by me. Here is the source code for it https://github.com/rt29/jgifcode - This is now here. I am not supporting it anymore. – Rohit Tiwari Nov 03 '15 at 10:00