简体   繁体   English

旋转具有透明背景的BufferedImage

[英]Rotate BufferedImage with transparent background

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: 我用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. 但是生成的image.png的背景是白色。 What am I doing wrong and how to properly keep the transparent background for image.png? 我在做错什么以及如何正确保持image.png的透明背景?

I'm a bit puzzled about the behavior of Graphics.drawImage() . 我对Graphics.drawImage()的行为有些疑惑。 Maybe somebody else can comment about it. 也许其他人可以对此发表评论。

However, Graphics2D.drawRenderedImage() works a treat. 但是, Graphics2D.drawRenderedImage()可以处理。 It takes an AffineTransform to control the rotation. 它需要一个AffineTransform来控制旋转。 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. 尽管以上代码适用于大多数PNG,但不适用于蝶形动物正在使用的图像 I've analyzed the image: 我分析了图像:

  • It's a grayscale image without a color palette (PNG color type 0) . 它是没有调色板的灰度图像(PNG颜色类型0)。
  • It uses simple transparency with a 2 byte long tRNS chunk. 它使用具有2个字节长的tRNS块的简单透明性。

As far as I can tell that's perfectly legal. 据我所知这是完全合法的。 However, ImageIO does not implement this combination. 但是,ImageIO没有实现此组合。 If the image has no palette, it simply ignores the tRNS chunk and therefore ignores the transparency information. 如果图像没有调色板,则它只会忽略tRNS块,因此会忽略透明度信息。 That's most likely a bug. 这很可能是一个错误。

You basically have two options now: 现在,您基本上有两个选择:

  1. Look for an alternative library to read PNG files. 寻找替代库来读取PNG文件。
  2. Fix the transparency after you have read the PNG file. 阅读PNG文件后,请修复透明度。 This only works if know that the image used the particular problematic format. 这仅在知道图像使用特定问题格式的情况下才有效。

Input and output for working PNG files 有效的PNG文件的输入和输出

Input image: 输入图片:

输入图像

Ouptput Image: 输出图像:

输出图像

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM