How to bend an Image in java

一曲冷凌霜 提交于 2019-12-04 15:04:16

As suggested in the comments, a simple approach is to divide the image into 3 parts:

  1. Identical to the original.
  2. Bent according to the bending transformation.
  3. Constant diagonal continuation.

Here is a quick and a bit messy example that shows the original shape and the resulting shape below it. I just used a label icon for the images instead of doing custom painting. (Also I didn't adhere to the Java naming conventions with final variables because it's math and not typical coding.)

Since there are quite a few variables in the calculation code, I added a sketch at the end that shows what the variables represent.

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

As for the calculations, I'll leave it for you as homework; it's just geometry/trigonometry which belongs on Math.SE more than on SO. If you can't figure it out I'll give you a direction.

Note that this method might not be fast at all and could certainly be optimized, I'll leave that to you also. Oh, and rounding doubles to ints carelessly, so the result is not pixel-perfect.

I dont know what you mean by bending but essentially you have a rectangle and you break one piece of it and rotate it:

so the algorithm is as follows:

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

So essentially you are looking for rotate line.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!