55

I am trying to resized a bufferedimage. I am able to store it and show up on a jframe no problems but I can't seem to resize it. Any tips on how I can change this to make it work and show the image as a 200*200 file would be great

private void profPic(){
    String path = factory.getString("bottle");
    BufferedImage img = ImageIO.read(new File(path));
}


public static BufferedImage resize(BufferedImage img, int newW, int newH) {  
    int w = img.getWidth();  
    int h = img.getHeight();  
    BufferedImage dimg = new BufferedImage(newW, newH, img.getType());  
    Graphics2D g = dimg.createGraphics();  
    g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
    RenderingHints.VALUE_INTERPOLATION_BILINEAR);  
    g.drawImage(img, 0, 0, newW, newH, 0, 0, w, h, null);  
    g.dispose();  
    return dimg;  
}  
Grant Miller
  • 27,532
  • 16
  • 147
  • 165
user1060187
  • 957
  • 5
  • 12
  • 28

7 Answers7

80

Updated answer

I cannot recall why my original answer worked but having tested it in a separate environment, I agree, the original accepted answer doesn't work (why I said it did I cannot remember either). This, on the other hand, did work:

public static BufferedImage resize(BufferedImage img, int newW, int newH) { 
    Image tmp = img.getScaledInstance(newW, newH, Image.SCALE_SMOOTH);
    BufferedImage dimg = new BufferedImage(newW, newH, BufferedImage.TYPE_INT_ARGB);

    Graphics2D g2d = dimg.createGraphics();
    g2d.drawImage(tmp, 0, 0, null);
    g2d.dispose();

    return dimg;
}  
Community
  • 1
  • 1
Ocracoke
  • 1,718
  • 3
  • 24
  • 38
  • 3
    That doesn't compile - getScaledInstance returns an Image not a BufferedImage. – I82Much Feb 18 '13 at 02:46
  • The example I used was extracted from a working example I have, but yes, this wouldn't compile as is. I'll update this now. – Ocracoke Feb 18 '13 at 12:18
  • 7
    Still not safe - on my Macbook, e.g., I get a ClassCastException - it's not a guaranteed conversion. – I82Much Feb 18 '13 at 17:08
  • 1
    This doesn't work, you cannot cast Image, which is result of getScaledInstance, into BufferedImage. – kazinix Aug 10 '13 at 12:34
  • 4
    @I82Much Write once, run anywhere... Ahem. – TEK Nov 15 '13 at 15:45
  • I get exception: sun.awt.image.ToolkitImage cannot be cast to java.awt.image.BufferedImage – Jasper Jul 25 '14 at 10:47
  • 2
    why is this listed as the correct answer when it doesn't work. – Jeremy Sep 26 '14 at 19:41
  • @Alex this is normal, because a solid color when resized by, say, 2* width and 2* height will result in the surrounding colors being "smeared" with the color to make the image seem more "smooth" and less chunky. – hyper-neutrino Jul 29 '15 at 20:47
  • 8
    Why `TYPE_INT_ARGB` and not `img.getType()`? – ADTC Aug 04 '15 at 04:19
  • 2
    The reason the first one doesn't compile is because the getScaledInstance() returns a ToolkitImage, not an Image. The reason an Image can be cast to a BufferedImage is be cause Image is a superclass of BufferedImage, not ToolkitImage. – John S. Jan 18 '16 at 00:53
22

If all that is required is to resize a BufferedImage in the resize method, then the Thumbnailator library can do that fairly easily:

public static BufferedImage resize(BufferedImage img, int newW, int newH) {
  return Thumbnails.of(img).size(newW, newH).asBufferedImage();
}

The above code will resize the img to fit the dimensions of newW and newH while maintaining the aspect ratio of the original image.

If maintaining the aspect ratio is not required and resizing to exactly the given dimensions is required, then the forceSize method can be used in place of the size method:

public static BufferedImage resize(BufferedImage img, int newW, int newH) {
  return Thumbnails.of(img).forceSize(newW, newH).asBufferedImage();
}

Using the Image.getScaledInstance method will not guarantee that the aspect ratio of the original image will be maintained for the resized image, and furthermore, it is in general very slow.

Thumbnailator uses a technique to progressively resize the image which can be several times faster than Image.getScaledInstance while achieving an image quality which generally is comparable.

Disclaimer: I am the maintainer of this library.

coobird
  • 159,216
  • 35
  • 211
  • 226
5

Here's some code that I have used to resize bufferedimages, no frills, pretty quick:

public static BufferedImage scale(BufferedImage src, int w, int h)
{
    BufferedImage img = 
            new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
    int x, y;
    int ww = src.getWidth();
    int hh = src.getHeight();
    int[] ys = new int[h];
    for (y = 0; y < h; y++)
        ys[y] = y * hh / h;
    for (x = 0; x < w; x++) {
        int newX = x * ww / w;
        for (y = 0; y < h; y++) {
            int col = src.getRGB(newX, ys[y]);
            img.setRGB(x, y, col);
        }
    }
    return img;
}
rlbaker
  • 103
  • 1
  • 7
  • great method, but the proportions where not correct, when I divided the factor for the height by the squareroot of two it worked fine.. =) – nyx00 Sep 20 '19 at 13:18
4

This class resize from a file and get the format name:

import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageInputStream;
import org.apache.commons.io.IOUtils;

public class ImageResizer {

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

    File f = new File("C:/Users/samsungrob/Desktop/shuttle.jpg");

    byte[] ba = resize(f, 600, 600);

    IOUtils.write(ba, new FileOutputStream( new File("C:/Users/samsungrob/Desktop/shuttle_resized.jpg") ) );

}




public static byte[] resize(File file,
                            int maxWidth, int maxHeight) throws IOException{
    int scaledWidth = 0, scaledHeight = 0;

    BufferedImage img = ImageIO.read((ImageInputStream) file );

    scaledWidth = maxWidth;
    scaledHeight = (int) (img.getHeight() * ( (double) scaledWidth / img.getWidth() ));

    if (scaledHeight> maxHeight) {
        scaledHeight = maxHeight;
        scaledWidth= (int) (img.getWidth() * ( (double) scaledHeight/ img.getHeight() ));

        if (scaledWidth > maxWidth) {
            scaledWidth = maxWidth;
            scaledHeight = maxHeight;
        }
    }

    Image resized =  img.getScaledInstance( scaledWidth, scaledHeight, Image.SCALE_SMOOTH);

    BufferedImage buffered = new BufferedImage(scaledWidth, scaledHeight, Image.SCALE_REPLICATE);

    buffered.getGraphics().drawImage(resized, 0, 0 , null);

    String formatName = getFormatName( file ) ;

    ByteArrayOutputStream out = new ByteArrayOutputStream();

    ImageIO.write(buffered,
            formatName,
            out);

    return out.toByteArray();
}


private static String getFormatName(ImageInputStream iis) {
    try { 

        // Find all image readers that recognize the image format
        Iterator iter = ImageIO.getImageReaders(iis);
        if (!iter.hasNext()) {
            // No readers found
            return null;
        }

        // Use the first reader
        ImageReader reader = (ImageReader)iter.next();

        // Close stream
        iis.close();

        // Return the format name
        return reader.getFormatName();
    } catch (IOException e) {
    }

    return null;
}

private static String getFormatName(File file) throws IOException {
    return getFormatName( ImageIO.createImageInputStream(file) );
}

private static String getFormatName(InputStream is) throws IOException {
    return getFormatName( ImageIO.createImageInputStream(is) );
}

}

ElOjcar
  • 301
  • 2
  • 4
  • 12
Frizz1977
  • 1,121
  • 13
  • 21
4

This is a shortened version of what is actually happening in imgscalr, if you just want to use the "balanced" smoothing:

/**
 * Takes a BufferedImage and resizes it according to the provided targetSize
 *
 * @param src the source BufferedImage
 * @param targetSize maximum height (if portrait) or width (if landscape)
 * @return a resized version of the provided BufferedImage
 */
private BufferedImage resize(BufferedImage src, int targetSize) {
    if (targetSize <= 0) {
        return src; //this can't be resized
    }
    int targetWidth = targetSize;
    int targetHeight = targetSize;
    float ratio = ((float) src.getHeight() / (float) src.getWidth());
    if (ratio <= 1) { //square or landscape-oriented image
        targetHeight = (int) Math.ceil((float) targetWidth * ratio);
    } else { //portrait image
        targetWidth = Math.round((float) targetHeight / ratio);
    }
    BufferedImage bi = new BufferedImage(targetWidth, targetHeight, src.getTransparency() == Transparency.OPAQUE ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2d = bi.createGraphics();
    g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); //produces a balanced resizing (fast and decent quality)
    g2d.drawImage(src, 0, 0, targetWidth, targetHeight, null);
    g2d.dispose();
    return bi;
}
Clint
  • 41
  • 1
3

try the imgscalr library. Best lib i found- very fast, good quality and simple to use

BufferedImage thumbnail = Scalr.resize(image, 150);

https://github.com/rkalla/imgscalr

Apache 2 License

Alexander Sidikov Pfeif
  • 2,418
  • 1
  • 20
  • 35
1

Check this out, it helps:

BufferedImage bImage = ImageIO.read(new File(C:\image.jpg);

BufferedImage thumbnail = Scalr.resize(bImage,  Scalr.Method.SPEED, Scalr.Mode.FIT_TO_WIDTH,
                                       750, 150, Scalr.OP_ANTIALIAS);
Unihedron
  • 10,902
  • 13
  • 62
  • 72
  • 1
    Just to add, that this is Imgscalr library -> https://mvnrepository.com/artifact/org.imgscalr/imgscalr-lib – RichardK Mar 17 '20 at 11:33