Java图像弯曲处理,如何弯曲在Java中的图像

Is there any way to bend a BufferedImage in Java?

I thought that if I crop the image into smaller pieces and rotate them then I would essentially bend the image, but it doesn't seem to work.

Here is the method I created:

/**

* 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);

}

This is the original Image:

KRCd0.png

And this is the result of this getBentImage(image, 200, 220, Math.toRadians(1)):

jXP9g.png

I was expecting something closer to:

Sasqm.png

Any ideas on how to actually implement a getBentImage() method?

解决方案

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

Identical to the original.

Bent according to the bending transformation.

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.

fcey7.png

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;

}

}

ea4W4.png

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.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值