2016-07-21 3 views
1

Есть ли способ сгибать BufferedImage в Java?Как согнуть изображение в java

Я думал, что если я обрезаю изображение на более мелкие кусочки и поверну их, я бы по существу сгибал изображение, но он, похоже, не работает.

Вот метод, который я создал:

/** 
* 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():Я что-то ближе к ожидали?

+0

Непонятно, что вы на самом деле имеете в виду под «изгибом». Пожалуйста, предоставьте точное определение преобразований, которые вы пытаетесь применить. –

+0

@ AndyTurner, не объясняют ли они изображения ниже? –

+0

Нет, вот почему я спросил. Каковы параметры деформации? Что означают параметры начальной точки, конечной точки и радиан? Например, вы передаете 1 радиан в качестве параметра, но ничто не повернулось на 57 градусов. Как бы это выглядело, если вы «согнули» прямоугольную сетку? –

ответ

3

Как указывается в комментариях, простой подход заключается в разделении изображения на 3 части:

  1. идентична оригиналу.
  2. Изгиб в соответствии с изгибом трансформации.
  3. Постоянное продолжение по диагонали.

Это быстрый и немного грязный пример, который показывает исходную форму и результирующую фигуру ниже нее. Я просто использовал значок метки для изображений вместо того, чтобы делать обычную покраску. (Также я не придерживался соглашений об именах Java с переменными final, потому что это математическое и нестандартное кодирование.)

Поскольку в коде вычисления имеется немало переменных, я добавил эскиз в конце, который показывает, что переменные представляют.

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 s до int s небрежно, поэтому результат не пиксель-совершенен.

-1

Я не знаю, что вы имеете в виду, сгибая, но по существу у вас есть прямоугольник и вы нарушаете одну часть его и повернуть его:

поэтому алгоритм выглядит следующим образом:

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

Поэтому в основном вы ищут вращающуюся линию.

+0

Это не обеспечивает непрерывный изгиб. Если вы не понимаете вопрос, спросите в комментариях, а не публикуете догадки. – user1803551