Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用透明背景旋转BuffereImage_Java_Bufferedimage - Fatal编程技术网

Java 使用透明背景旋转BuffereImage

Java 使用透明背景旋转BuffereImage,java,bufferedimage,Java,Bufferedimage,我有一个透明背景的图像。我想将这张图片旋转到一个特定的角度,并为生成的图片保留透明的背景。为此,我使用以下方法: public static BufferedImage rotateImage(BufferedImage image, double angle, Color backgroundColor) { System.out.println(image.getType()); double theta = Math.toRadians(angle); double

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

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;
}
我使用background=null调用它:

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

但是结果image.png的背景是白色的。我做错了什么?如何正确地保持image.png的透明背景?

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

但是,
Graphics2D.drawRenderImages()
起到了作用。它需要一个
仿射变换
来控制旋转。下面的例子很好地工作。您可能对最终图像大小和旋转图像的位置有其他要求

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

虽然上面的代码适用于大多数PNG,但它不适用于alexanoid正在使用的。我分析了图像:

  • 这是一个没有调色板的灰度图像(PNG颜色类型0)
  • 它使用2字节长的tRNS块的简单透明性
据我所知,这是完全合法的。但是,ImageIO没有实现这种组合。如果图像没有调色板,它只会忽略tRNS块,从而忽略透明度信息。这很可能是个bug

您现在基本上有两个选择:

  • 寻找另一个库来读取PNG文件
  • 在读取PNG文件后修复透明度。只有知道图像使用了特定的有问题的格式时,这才有效
  • 工作PNG文件的输入和输出

    输入图像:

    输出图像:


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

    但是,
    Graphics2D.drawRenderImages()
    起到了作用。它需要一个
    仿射变换
    来控制旋转。下面的例子很好地工作。您可能对最终图像大小和旋转图像的位置有其他要求

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

    虽然上面的代码适用于大多数PNG,但它不适用于alexanoid正在使用的。我分析了图像:

    • 这是一个没有调色板的灰度图像(PNG颜色类型0)
    • 它使用2字节长的tRNS块的简单透明性
    据我所知,这是完全合法的。但是,ImageIO没有实现这种组合。如果图像没有调色板,它只会忽略tRNS块,从而忽略透明度信息。这很可能是个bug

    您现在基本上有两个选择:

  • 寻找另一个库来读取PNG文件
  • 在读取PNG文件后修复透明度。只有知道图像使用了特定的有问题的格式时,这才有效
  • 工作PNG文件的输入和输出

    输入图像:

    输出图像:


    它不起作用。这样,我的图像只有黑色背景。您可以检查
    image.getType()的值吗?您的源和alpha通道真的有支持透明度的alpha通道吗;type等于12(type_BYTE_BINARY)是的,这个图像不工作。在调试器中进行分析后,似乎ImageIO出现故障。图像使用索引颜色模型,只有两种颜色:黑色和透明。但是在ImageIO读取它之后,颜色模型说它是不透明的,并且没有一种颜色是透明的。那是不对的。需要进一步调查。我已经更详细地分析了这个问题。请查看我的更新。它不工作。这样,我的图像只有黑色背景。您可以检查
    image.getType()的值吗?您的源和alpha通道真的有支持透明度的alpha通道吗;type等于12(type_BYTE_BINARY)是的,这个图像不工作。在调试器中进行分析后,似乎ImageIO出现故障。图像使用索引颜色模型,只有两种颜色:黑色和透明。但是在ImageIO读取它之后,颜色模型说它是不透明的,并且没有一种颜色是透明的。那是不对的。需要进一步调查。我已经更详细地分析了这个问题。请看我的更新。