旋转具有透明背景的BufferedImage [英] Rotate BufferedImage with transparent background

查看:70
本文介绍了旋转具有透明背景的BufferedImage的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一张透明背景的图像.我想将此图像旋转到特定角度,并保持生成的图像的透明背景.为此,我使用以下方法:

 公共静态BufferedImage rotationImage(BufferedImage图像,双角度,彩色backgroundColor){System.out.println(image.getType());double theta = Math.toRadians(angle);双重罪恶= Math.abs(Math.sin(theta));double cos = Math.abs(Math.cos(theta));int w = image.getWidth();int h = image.getHeight();int newW =(int)Math.floor(w * cos + h * sin);int newH =(int)Math.floor(h * cos + w * sin);BufferedImage tmp = new BufferedImage(newW,newH,image.getType());Graphics2D g2d = tmp.createGraphics();如果(backgroundColor!= null){g2d.setColor(backgroundColor);g2d.fillRect(0,0,newW,newH);}g2d.fillRect(0,0,newW,newH);g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BICUBIC);g2d.translate((newW-w)/2,(newH-h)/2);g2d.rotate(theta,w/2,h/2);g2d.drawImage(image,0,0,null);g2d.dispose();返回tmp;} 

我用background = null调用它:

  BufferedImage image = ImageIO.read(file);rotationImage(image,4,null);ImageIO.write(bi,"PNG",新File("image.png")); 

,但是生成的image.png的背景是白色.我在做错什么以及如何正确保持image.png的透明背景?

解决方案

我对 Graphics.drawImage()的行为感到有些困惑.也许其他人可以对此发表评论.

但是, Graphics2D.drawRenderedImage()可以解决问题.它需要一个 AffineTransform 来控制旋转.下面的示例很好地工作.您可能对最终图像的大小和旋转图像的位置还有其他要求.

  import javax.imageio.ImageIO;导入java.awt.Graphics2D;导入java.awt.geom.AffineTransform;导入java.awt.image.BufferedImage;导入java.io.File;公共类ImageRotation {公共静态void main(String [] args){ImageRotation旋转= new ImageRotation();rotation.rotate("input.png",45,"output.png");}public void rotation(String inputImageFilename,double angle,String outputImageFilename){尝试 {BufferedImage inputImage = ImageIO.read(新文件(inputImageFilename));BufferedImage outputImage = rotationImage(inputImage,angle);ImageIO.write(outputImage,"PNG",新File(outputImageFilename));} catch(Exception e){抛出新的RuntimeException(e);}}私人BufferedImage rotationImage(BufferedImage sourceImage,双角度){int width = sourceImage.getWidth();int height = sourceImage.getHeight();BufferedImage destImage =新的BufferedImage(宽度,高度,BufferedImage.TYPE_INT_ARGB);Graphics2D g2d = destImage.createGraphics();AffineTransform transform = new AffineTransform();transform.rotate(角度/180 * Math.PI,宽度/2,高度/2);g2d.drawRenderedImage(sourceImage,transform);g2d.dispose();返回destImage;}} 

更新

虽然以上代码适用于大多数PNG,但不适用于

输出图像:

I have an image with transparent background. I'd like to rotate this image to a specific angle and keep the transparent background for the resulting image. For this purpose I use the following method:

public static BufferedImage rotateImage(BufferedImage image, double angle, Color backgroundColor) {
    System.out.println(image.getType());
    double theta = Math.toRadians(angle);
    double sin = Math.abs(Math.sin(theta));
    double cos = Math.abs(Math.cos(theta));
    int w = image.getWidth();
    int h = image.getHeight();
    int newW = (int) Math.floor(w * cos + h * sin);
    int newH = (int) Math.floor(h * cos + w * sin);

    BufferedImage tmp = new BufferedImage(newW, newH, image.getType());
    Graphics2D g2d = tmp.createGraphics();
    if (backgroundColor != null) {
        g2d.setColor(backgroundColor);
        g2d.fillRect(0, 0, newW, newH);
    } 
    g2d.fillRect(0, 0, newW, newH);
    g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
    g2d.translate((newW - w) / 2, (newH - h) / 2);
    g2d.rotate(theta, w / 2, h / 2);
    g2d.drawImage(image, 0, 0, null);
    g2d.dispose();
    return tmp;
}

I invoke it with background=null:

BufferedImage image = ImageIO.read(file);
rotateImage(image, 4, null);
ImageIO.write(bi, "PNG", new File("image.png"));

but the background of the resulting image.png is WHITE. What am I doing wrong and how to properly keep the transparent background for image.png?

解决方案

I'm a bit puzzled about the behavior of Graphics.drawImage(). Maybe somebody else can comment about it.

However, Graphics2D.drawRenderedImage() works a treat. It takes an AffineTransform to control the rotation. The below example nicely works. You probably have additional requirement about the final image size and the location of the rotated image.

import javax.imageio.ImageIO;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;

public class ImageRotation {

    public static void main(String[] args) {
        ImageRotation rotation = new ImageRotation();
        rotation.rotate("input.png", 45, "output.png");
    }

    public void rotate(String inputImageFilename, double angle, String outputImageFilename) {

        try {
            BufferedImage inputImage = ImageIO.read(new File(inputImageFilename));
            BufferedImage outputImage = rotateImage(inputImage, angle);
            ImageIO.write(outputImage, "PNG", new File(outputImageFilename));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private BufferedImage rotateImage(BufferedImage sourceImage, double angle) {
        int width = sourceImage.getWidth();
        int height = sourceImage.getHeight();
        BufferedImage destImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = destImage.createGraphics();

        AffineTransform transform = new AffineTransform();
        transform.rotate(angle / 180 * Math.PI, width / 2 , height / 2);
        g2d.drawRenderedImage(sourceImage, transform);

        g2d.dispose();
        return destImage;
    }
}

Update

While the above code works for most PNGs, it does not work for the image that alexanoid is using. I've analyzed the image:

  • It's a grayscale image without a color palette (PNG color type 0) .
  • It uses simple transparency with a 2 byte long tRNS chunk.

As far as I can tell that's perfectly legal. However, ImageIO does not implement this combination. If the image has no palette, it simply ignores the tRNS chunk and therefore ignores the transparency information. That's most likely a bug.

You basically have two options now:

  1. Look for an alternative library to read PNG files.
  2. Fix the transparency after you have read the PNG file. This only works if know that the image used the particular problematic format.

Input and output for working PNG files

Input image:

Ouptput Image:

这篇关于旋转具有透明背景的BufferedImage的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆