我有原图:
我使用以下 Java 代码旋转图像:
BufferedImage bi = ImageHelper.rotateImage(bi, -imageSkewAngle);
ImageIO.write(bi, "PNG", new File("out.png"));
结果我得到了以下图像:
如何删除图像周围的黑色边界并使其成为适当的白色矩形并且不花费太多空间..仅使用所需的大小进行转换...等于原始大小或更大(如果需要)?
最佳答案
以下程序包含一个方法rotateImage
,该方法应与问题中使用的rotateImage
方法等效:它计算旋转图像的边界,创建一个具有所需尺寸的新图像,并将原始图像绘制到新图像的中心。
该方法还接收一个确定背景颜色的Color backgroundColor
。在示例中,将其设置为 Color.RED
以说明效果。
该示例还包含一个方法rotateImageInPlace
。此方法将始终创建一个与输入图像大小相同的图像,并且还会将(旋转的)原始图像绘制到该图像的中心。
该程序创建两个面板,左侧面板显示 rotateImage
的结果,右侧面板显示 rotateImageInPlace
的结果,以及一个允许更改旋转角度的 slider 。所以这个程序的输出如下所示:
(同样,Color.RED
仅用于说明。根据您的应用程序将其更改为 Color.WHITE
)
正如评论中所讨论的,不改变图像大小的目标可能并不总是可以实现,具体取决于图像的内容和旋转角度。因此,对于某些角度,旋转的图像可能不适合最终的图像。但对于问题的用例,这应该没问题:用例是原始图像已经包含旋转的矩形“感兴趣区域”。因此,输出中未出现的部分通常应该是输入图像中无论如何不包含相关信息的部分。
(否则,有必要提供有关输入图像结构、边框大小或旋转角度的更多信息,或者必须通过检查图像、像素来手动计算出所需的大小按像素,查看哪些像素是黑色的,哪些是白色的)
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
public class RotateImageWithoutBorder
{
public static void main(String[] args) throws Exception
{
BufferedImage image =
ImageIO.read(new URL("/image/tMtFh.png"));
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ImagePanel imagePanel0 = new ImagePanel();
imagePanel0.setBackground(Color.BLUE);
ImagePanel imagePanel1 = new ImagePanel();
imagePanel1.setBackground(Color.BLUE);
JSlider slider = new JSlider(0, 100, 1);
slider.addChangeListener(e ->
{
double alpha = slider.getValue() / 100.0;
double angleRad = alpha * Math.PI * 2;
BufferedImage rotatedImage = rotateImage(
image, angleRad, Color.RED);
imagePanel0.setImage(rotatedImage);
BufferedImage rotatedImageInPlace = rotateImageInPlace(
image, angleRad, Color.RED);
imagePanel1.setImage(rotatedImageInPlace);
f.repaint();
});
slider.setValue(0);
f.getContentPane().add(slider, BorderLayout.SOUTH);
JPanel imagePanels = new JPanel(new GridLayout(1,2));
imagePanels.add(imagePanel0);
imagePanels.add(imagePanel1);
f.getContentPane().add(imagePanels, BorderLayout.CENTER);
f.setSize(800,500);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private static BufferedImage rotateImage(
BufferedImage image, double angleRad, Color backgroundColor)
{
int w = image.getWidth();
int h = image.getHeight();
AffineTransform at = AffineTransform.getRotateInstance(
angleRad, w * 0.5, h * 0.5);
Rectangle rotatedBounds = at.createTransformedShape(
new Rectangle(0, 0, w, h)).getBounds();
BufferedImage result = new BufferedImage(
rotatedBounds.width, rotatedBounds.height,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = result.createGraphics();
g.setColor(backgroundColor);
g.fillRect(0, 0, rotatedBounds.width, rotatedBounds.height);
at.preConcatenate(AffineTransform.getTranslateInstance(
-rotatedBounds.x, -rotatedBounds.y));
g.transform(at);
g.setRenderingHint(
RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(image, 0, 0, null);
g.dispose();
return result;
}
private static BufferedImage rotateImageInPlace(
BufferedImage image, double angleRad, Color backgroundColor)
{
int w = image.getWidth();
int h = image.getHeight();
AffineTransform at = AffineTransform.getRotateInstance(
angleRad, w * 0.5, h * 0.5);
Rectangle rotatedBounds = at.createTransformedShape(
new Rectangle(0, 0, w, h)).getBounds();
BufferedImage result = new BufferedImage(
w, h,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = result.createGraphics();
g.setColor(backgroundColor);
g.fillRect(0, 0, w, h);
at.preConcatenate(AffineTransform.getTranslateInstance(
-rotatedBounds.x - (rotatedBounds.width - w) * 0.5,
-rotatedBounds.y - (rotatedBounds.height - h) * 0.5));
g.transform(at);
g.setRenderingHint(
RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(image, 0, 0, null);
g.dispose();
return result;
}
static class ImagePanel extends JPanel
{
private BufferedImage image;
public void setImage(BufferedImage image)
{
this.image = image;
repaint();
}
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
if (image != null)
{
g.drawImage(image, 0, 0, null);
}
}
}
}
关于java - 旋转 BufferedImage 并删除黑色边界,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48587644/