如何弯曲在Java中的图像 [英] How to bend an Image in java
问题描述
有没有办法在Java中弯曲 BufferedImage
?
我认为,如果我将图像裁剪成更小的部分并旋转它们,那么我会基本上弯曲图像,但它似乎不起作用。
以下是我创建的方法:
/ **
*这是一种递归方法,它将接受一个图像,即弯曲开始点和弯曲结束点,以及弯曲角度
*
* @param original :原始图像
* @param startingPoint:弯曲开始点
* @param endingPoint:弯曲结束的点
* @param radiands:角度
*返回弯曲的图像
* /
public static BufferedImage getBentImage(BufferedImage original,int startingPoint,int endingPoint,double radians){$ b $ if(startingPoint> = endingPoint)
返回原文;
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);
}
这是原始图片:
这是 getBentImage的结果(image,200,220 ,Math.toRadians(1))
:
关于如何实际实现 getBentImage()
方法的任何想法?
正如评论中所建议的,一个简单的方法是将图像分成三部分: inal。
下面是一个快速而有点混乱的例子,它显示了原始形状和其下面的结果形状。我只是使用图片的标签图标而不是自定义绘画。 (我也没有遵守Java命名约定,因为它是数学而不是典型的编码,所以最终
变量。)
<由于计算代码中有很多变量,因此我在末尾添加了一个草图,以显示变量代表的内容。
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()); (int x = 0; x for(int y = 0; y int rgb = image
.getRGB(x,y);
img2.setRGB(x,y,rgb); (int x = x1; x for(int y = 0; 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); (int x = x2; 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;
}
}
至于计算,我会把它留给你作为功课;它只是在Math.SE上属于SO的几何/三角函数。如果你无法弄清楚,我会给你一个方向。
请注意,这种方法可能并不快,当然可以优化,我会把它留给你也是。哦,并且不小心将 double
s舍入为 int
s,所以结果不是像素完美的。
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:
And this is the result of this getBentImage(image, 200, 220, Math.toRadians(1))
:
I was expecting something closer to:
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.
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 double
s to int
s carelessly, so the result is not pixel-perfect.
这篇关于如何弯曲在Java中的图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!