如何弯曲在Java中的图像 [英] How to bend an Image in java

查看:180
本文介绍了如何弯曲在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.setHorizo​​ntalAlignment(JLabel.LEFT);
    label1.setOpaque(true);
    label1.setBackground(Color.YELLOW);
    add(label1,BorderLayout.NORTH);

    JLabel label2 = new JLabel(new ImageIcon(img2));
    label2.setHorizo​​ntalAlignment(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:

    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.

    这篇关于如何弯曲在Java中的图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆