2016-07-21 7 views
1

Y at-il un moyen de plier un BufferedImage en Java?Comment faire pour plier une image dans Java

Je pensais que si je recadre l'image en plus petits morceaux et que je la fais pivoter, alors je plierais essentiellement l'image, mais cela ne semble pas fonctionner.

Voici la méthode que je crée:

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

Ceci est l'image originale:

original Image

Et ceci est le résultat de cette getBentImage(image, 200, 220, Math.toRadians(1)):

result

Je me attendais quelque chose de plus proche de:

expected result

Toutes les idées sur la façon de mettre en œuvre en fait une méthode getBentImage()?

+0

On ne sait pas vraiment ce que vous entendez par "plier". Veuillez fournir une définition précise de la transformation que vous essayez d'appliquer. –

+0

@AndyTurner ne pas les images ci-dessous l'expliquer? –

+0

Non, c'est pourquoi j'ai demandé. Quels sont les paramètres de la déformation? Que signifient le point de départ, le point final et les paramètres radians? Par exemple, vous passez en 1 radian comme paramètre, mais rien n'a pivoté de 57 degrés. A quoi ressemblerait-il si vous "pliez" une grille rectangulaire? –

Répondre

3

Comme suggéré dans les commentaires, une approche simple consiste à diviser l'image en 3 parties:

  1. identique à l'original.
  2. Courbé selon la transformation en flexion.
  3. Continuation diagonale constante.

Voici un exemple rapide et un peu brouillon qui montre la forme originale et la forme résultante en dessous. J'ai juste utilisé une icône d'étiquette pour les images au lieu de faire de la peinture personnalisée. (De plus, je n'ai pas respecté les conventions de nommage Java avec les variables final parce que ce sont des maths et pas un codage typique.)

Comme il y a pas mal de variables dans le code de calcul, j'ai ajouté un croquis à la fin qui montre ce que les variables représentent.

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

En ce qui concerne les calculs, je vous laisse pour vous les devoirs; c'est juste la géométrie/trigonométrie qui appartient à Math.SE plus qu'à SO. Si vous ne pouvez pas comprendre, je vais vous donner une direction.

Notez que cette méthode peut ne pas être rapide du tout et pourrait certainement être optimisée, je vais vous laisser aussi. Oh, et arrondi double s à int s négligemment, de sorte que le résultat n'est pas parfait.

-1

Je ne sais pas ce que vous entendez par flexion, mais essentiellement vous avez un rectangle et vous casser un morceau de celui-ci et faites-le pivoter:

si l'algorithme est comme suit:

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

Donc, essentiellement, vous cherchez une ligne de rotation.

+0

Cela n'entraîne pas de flexion continue. Si vous ne comprenez pas la question, demandez dans les commentaires au lieu de poster des suppositions. – user1803551