Resize image in Java without losing transparency
Asked Answered
H

3

5

I want to resize an image (jpg, png, gif) without losing the transparency.

I want to save the resized version to the disk after resizing.

I googled a lot but I only found solutions that lose the transparency and fill the transparent space black...

I am looking for a snippet or a library that does the job :)

Herries answered 23/9, 2012 at 11:55 Comment(6)
Are you simply trying to resize them for display (relatively easy) or create a 2nd resized image on disk (a lot harder)?Plumbing
i want to create a 2nd resized image on the disk. For example for uploaded avatars of a website.Herries
OK - first concentrate on the transparency. Note that the J2SE has no simple method for writing animated GIFs, and that PNG does not offer animation at all.Plumbing
should i open a new question or edit this one ? png offers animation: apng en.wikipedia.org/wiki/APNG (it's supported in firefox for example)Herries
I think edit this one. And "an unofficial extension to the Portable Network Graphics (PNG) specification" is not a PNG. At least, not in any sense that the J2SE understands.Plumbing
Ok, guess you are right with the png thing. I edited the question.Herries
H
2

This is how i solved my problem:

public static BufferedImage convertRGBAToIndexed(BufferedImage src) {
    BufferedImage dest = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_BYTE_INDEXED);
    Graphics g = dest.getGraphics();
    g.setColor(new Color(231, 20, 189));
    g.fillRect(0, 0, dest.getWidth(), dest.getHeight());
    dest = makeTransparent(dest, 0, 0);
    dest.createGraphics().drawImage(src, 0, 0, null);
    return dest;
}

public static BufferedImage makeTransparent(BufferedImage image, int x, int y) {
    ColorModel cm = image.getColorModel();
    if (!(cm instanceof IndexColorModel))
        return image; // sorry...
    IndexColorModel icm = (IndexColorModel) cm;
    WritableRaster raster = image.getRaster();
    int pixel = raster.getSample(x, y, 0);
    int size = icm.getMapSize();
    byte[] reds = new byte[size];
    byte[] greens = new byte[size];
    byte[] blues = new byte[size];
    icm.getReds(reds);
    icm.getGreens(greens);
    icm.getBlues(blues);
    IndexColorModel icm2 = new IndexColorModel(8, size, reds, greens, blues, pixel);
    return new BufferedImage(icm2, raster, image.isAlphaPremultiplied(), null);
}

public static Dimension getScaledDimension(Dimension imgSize, Dimension boundary) {
    int original_width = imgSize.width;
    int original_height = imgSize.height;
    int bound_width = boundary.width;
    int bound_height = boundary.height;
    int new_width = 0;
    int new_height = 0;

    if (original_width > original_height) {
        new_width = bound_width;
        new_height = (new_width*original_height)/original_width;
    } else {
        new_height = bound_height;
        new_width = (new_height*original_width)/original_height;
    }

    return new Dimension(new_width, new_height);
}

public static void resizeImage(File original_image, File resized_image, int IMG_SIZE) {
    try {
        BufferedImage originalImage = ImageIO.read(original_image);

        String extension = Files.getFileExtension(original_image.getName());

        int type = extension.equals("gif") || (originalImage.getType() == 0) ? BufferedImage.TYPE_INT_ARGB : originalImage.getType();

        Dimension new_dim = getScaledDimension(new Dimension(originalImage.getWidth(), originalImage.getHeight()), new Dimension(IMG_SIZE,IMG_SIZE));

        BufferedImage resizedImage = new BufferedImage((int) new_dim.getWidth(), (int) new_dim.getHeight(), type);
        Graphics2D g = resizedImage.createGraphics();
        g.drawImage(originalImage, 0, 0, (int) new_dim.getWidth(), (int) new_dim.getHeight(), null);
        g.dispose();            

        if (!extension.equals("gif")) {
            ImageIO.write(resizedImage, extension, resized_image);
        } else {
            // Gif Transparence workarround
            ImageIO.write(convertRGBAToIndexed(resizedImage), "gif", resized_image);
        }

    } catch (IOException e) {
        Utils.log("resizeImage", e.getMessage());
    }
}
Herries answered 25/9, 2012 at 13:25 Comment(0)
O
3

After resarch i found that you can resize buffer image only if you keep it as BufferedImage without convert it to ImageIcon

I solve the proplem like this:

public class NewJFrame extends javax.swing.JFrame {

/**
 * Creates new form NewJFrame
 */
public NewJFrame()  {
    try {
        initComponents();
        BufferedImage c = ImageIO.read(new File("60_Personnel.png"));
        JLabel lblMains = new JLabel( new ImageIcon(c));
        this.add(lblMains);                                       //add real size
        this.add(new JLabel(new ImageIcon((resize(c, 150)))));    //add converting image
        this.pack();
        this.setLocationRelativeTo(null);
        this.setVisible(true);
    } catch (IOException ex) {
        Logger.getLogger(NewJFrame.class.getName()).log(Level.SEVERE, null, ex);
    }

}

public static BufferedImage resize(Object img, int percent) {
    BufferedImage buff = (BufferedImage) img;
    return resize(buff, buff.getWidth() * percent / 100, buff.getWidth() * percent / 100);
}

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;
}

}

Orelie answered 17/11, 2015 at 8:11 Comment(1)
This seems good. I put it into a JavaX standard function: tinybrain.de/1004224Moran
E
3

Change something like this:

public static BufferedImage resizeImage(BufferedImage originalImage, int targetWidth, int targetHeight) {
        BufferedImage resizedImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics2D = resizedImage.createGraphics();
        graphics2D.drawImage(originalImage, 0, 0, targetWidth, targetHeight, null);
        graphics2D.dispose();
        return resizedImage;
    }

to this:

public static BufferedImage resizeImage(BufferedImage originalImage, int targetWidth, int targetHeight) {
        BufferedImage resizedImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_ARGB);
        Graphics2D graphics2D = resizedImage.createGraphics();
        graphics2D.drawImage(originalImage, 0, 0, targetWidth, targetHeight, null);
        graphics2D.dispose();
        return resizedImage;
    }

you basically change "BufferedImage.TYPE_INT_RGB" to "BufferedImage.TYPE_INT_ARGB"

Emmenagogue answered 27/3, 2021 at 21:30 Comment(0)
H
2

This is how i solved my problem:

public static BufferedImage convertRGBAToIndexed(BufferedImage src) {
    BufferedImage dest = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_BYTE_INDEXED);
    Graphics g = dest.getGraphics();
    g.setColor(new Color(231, 20, 189));
    g.fillRect(0, 0, dest.getWidth(), dest.getHeight());
    dest = makeTransparent(dest, 0, 0);
    dest.createGraphics().drawImage(src, 0, 0, null);
    return dest;
}

public static BufferedImage makeTransparent(BufferedImage image, int x, int y) {
    ColorModel cm = image.getColorModel();
    if (!(cm instanceof IndexColorModel))
        return image; // sorry...
    IndexColorModel icm = (IndexColorModel) cm;
    WritableRaster raster = image.getRaster();
    int pixel = raster.getSample(x, y, 0);
    int size = icm.getMapSize();
    byte[] reds = new byte[size];
    byte[] greens = new byte[size];
    byte[] blues = new byte[size];
    icm.getReds(reds);
    icm.getGreens(greens);
    icm.getBlues(blues);
    IndexColorModel icm2 = new IndexColorModel(8, size, reds, greens, blues, pixel);
    return new BufferedImage(icm2, raster, image.isAlphaPremultiplied(), null);
}

public static Dimension getScaledDimension(Dimension imgSize, Dimension boundary) {
    int original_width = imgSize.width;
    int original_height = imgSize.height;
    int bound_width = boundary.width;
    int bound_height = boundary.height;
    int new_width = 0;
    int new_height = 0;

    if (original_width > original_height) {
        new_width = bound_width;
        new_height = (new_width*original_height)/original_width;
    } else {
        new_height = bound_height;
        new_width = (new_height*original_width)/original_height;
    }

    return new Dimension(new_width, new_height);
}

public static void resizeImage(File original_image, File resized_image, int IMG_SIZE) {
    try {
        BufferedImage originalImage = ImageIO.read(original_image);

        String extension = Files.getFileExtension(original_image.getName());

        int type = extension.equals("gif") || (originalImage.getType() == 0) ? BufferedImage.TYPE_INT_ARGB : originalImage.getType();

        Dimension new_dim = getScaledDimension(new Dimension(originalImage.getWidth(), originalImage.getHeight()), new Dimension(IMG_SIZE,IMG_SIZE));

        BufferedImage resizedImage = new BufferedImage((int) new_dim.getWidth(), (int) new_dim.getHeight(), type);
        Graphics2D g = resizedImage.createGraphics();
        g.drawImage(originalImage, 0, 0, (int) new_dim.getWidth(), (int) new_dim.getHeight(), null);
        g.dispose();            

        if (!extension.equals("gif")) {
            ImageIO.write(resizedImage, extension, resized_image);
        } else {
            // Gif Transparence workarround
            ImageIO.write(convertRGBAToIndexed(resizedImage), "gif", resized_image);
        }

    } catch (IOException e) {
        Utils.log("resizeImage", e.getMessage());
    }
}
Herries answered 25/9, 2012 at 13:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.