如何在java中弯曲图像

时间:2016-07-21 11:01:03

标签: java swing graphics bufferedimage affinetransform

有没有办法在Java中弯曲BufferedImage

我认为如果我将图像裁剪成小块并旋转它们,那么我基本上会弯曲图像,但它似乎不起作用。

这是我创建的方法:

/**
 * This is a recursive method that will accept an image the point where the bending will start and the point where the bending will end, as well as the angle of bending
 * 
 * @param original:the original image
 * @param startingPoint: the point where the bending should start
 * @param endingPoint: the point where the bending should end
 * @param radiands: the angle
 * @return the bent image
 */
public static BufferedImage getBentImage(BufferedImage original, int startingPoint, int endingPoint, double radians) {
    if (startingPoint >= endingPoint)
        return original;

    int type = BufferedImage.TYPE_INT_ARGB;
    int width = original.getWidth();
    int height = original.getHeight();

    BufferedImage crop = original.getSubimage(0, 0, startingPoint, height);
    BufferedImage crop0 = original.getSubimage(startingPoint, 0, width - startingPoint, height);
    BufferedImage bendCrop = new BufferedImage(width, height, type);
    BufferedImage image = new BufferedImage(width, height, type);

    AffineTransform rotation = new AffineTransform();
    rotation.translate(0, 0);
    rotation.rotate(radians);

    Graphics2D g = bendCrop.createGraphics();
    g.drawImage(crop0, rotation, null);
    g.dispose();

    g = image.createGraphics();
    g.drawImage(crop, 0, 0, null);
    g.drawImage(bendCrop, startingPoint, 0, null);
    g.dispose();

    return getBentImage(image, startingPoint + 1, endingPoint, radians);
}

这是原始图片:

original Image

这是getBentImage(image, 200, 220, Math.toRadians(1))

的结果

result

我期待更接近的事情:

expected result

有关如何实际实施getBentImage()方法的任何想法?

2 个答案:

答案 0 :(得分:4)

正如评论中所建议的,一种简单的方法是将图像分为3个部分:

  1. 与原作相同。
  2. 根据弯曲变形弯曲。
  3. 恒定对角线延续。
  4. 这是一个快速且有点混乱的例子,它显示了原始形状和它下面的结果形状。我只是用图像的标签图标而不是自定义绘画。 (另外,我没有遵守final变量的Java命名约定,因为它是数学而不是典型的编码。)

    由于计算代码中有很多变量,我在末尾添加了一个草图,显示了变量代表的内容。

    enter image description here

    public class Main extends JFrame {
    
        static BufferedImage image;
    
        public static void main(String[] args) {
    
            try {
                image = ImageIO.read(ClassLoader.getSystemResource("img.png"));
            } catch (IOException e) {
                e.printStackTrace();
            }
            new Main();
        }
    
        public Main() {
    
            getContentPane().setLayout(new BorderLayout(5, 10));
            BufferedImage img2 = transform(15, 100, 300);
    
            JLabel label1 = new JLabel(new ImageIcon(image));
            label1.setHorizontalAlignment(JLabel.LEFT);
            label1.setOpaque(true);
            label1.setBackground(Color.YELLOW);
            add(label1, BorderLayout.NORTH);
    
            JLabel label2 = new JLabel(new ImageIcon(img2));
            label2.setHorizontalAlignment(JLabel.LEFT);
            label2.setOpaque(true);
            label2.setBackground(Color.CYAN);
            add(label2);
    
            pack();
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            setVisible(true);
        }
    
        static BufferedImage transform(int t, int x1, int x2) {
    
            final double TH = Math.toRadians(t);
            final int D = x2 - x1;
            final int W = image.getWidth();
            final int H = image.getHeight();
    
            final int dD = (int) (D / (2 * TH) * Math.sin(2 * TH));
            final int dH = (int) (D / TH * Math.pow(Math.sin(TH), 2));
            final int pH = (int) ((W - x2) * Math.tan(2 * TH));
    
            final int width = W - (D - dD);
            final int height = (int) (H + dH + pH);
    
            System.out.println(W + " " + H + " -> " + width + " " + height);
    
            BufferedImage img2 = new BufferedImage(width, height, image.getType());
    
            for (int x = 0; x < x1; x++) {
                for (int y = 0; y < H; y++) {
                    int rgb = image.getRGB(x, y);
                    img2.setRGB(x, y, rgb);
                }
            }
    
            for (int x = x1; x < x2; x++) {
                for (int y = 0; y < H; y++) {
                    int rgb = image.getRGB(x, y);
                    int dx = (int) (D / (2 * TH) * Math.sin(2 * (x-x1) * TH / D));
                    int dy = (int) (D / TH * Math.pow(Math.sin((x-x1) * TH / D), 2));
                    img2.setRGB(x1 + dx, y + dy, rgb);
                }
            }
    
            for (int x = x2; x < W; x++) {
                for (int y = 0; y < H; y++) {
                    int rgb = image.getRGB(x, y);
                    int dp = (int) ((x - x2) * Math.tan(2 * TH));
                    img2.setRGB(x - (D - dD), y + dH + dp, rgb);
                }
            }
    
            return img2;
        }
    }
    

    enter image description here

    至于计算,我会把它作为家庭作业留给你;它只是几何/三角,它属于Math.SE而不是SO。如果你无法弄明白,我会给你一个方向。

    请注意,此方法可能不会很快,当然可以优化,我也会留给您。哦,并且不小心将double舍入到int s,所以结果不是像素完美的。

答案 1 :(得分:-1)

我不知道你的意思是弯曲,但基本上你有一个矩形,你打破它的一部分并旋转它:

所以算法如下:

rotate line(x, 0, width-1, 0)
rotate line(x, height-1, width-1, height-1)
connect the pieces

所以基本上你正在寻找旋转线。