AffineTransform обрезает изображение, что я не так делаю? - PullRequest
2 голосов
/ 04 января 2012

У меня есть черно-белый png-файл размером 2156x1728, который я хочу повернуть на 90 градусов с помощью AffineTransform.Полученное изображение не имеет правильных пропорций.Вот пример кода (если я успешно загрузил png-файл в BufferedImage):

public BufferedImage transform(BufferedImage image){

    System.out.println("Input width: "+ image.getWidth());
    System.out.println("Input height: "+ image.getHeight());

    AffineTransform affineTransform = new AffineTransform();
    affineTransform.setToQuadrantRotation(1, image.getWidth() / 2, image.getHeight() / 2);

    AffineTransformOp opRotated = new AffineTransformOp(affineTransform, AffineTransformOp.TYPE_BILINEAR);
    BufferedImage transformedImage = opRotated.createCompatibleDestImage(image, image.getColorModel());
    System.out.println("Resulting width: "+ transformedImage.getWidth());
    System.out.println("Resulting height: "+ transformedImage.getHeight());

    transformedImage = opRotated.filter(image, transformedImage);
    return transformedImage;
}

Вывод:

Ширина ввода: 2156

Высота ввода: 1728

Результирующая ширина: 1942

Результирующая высота: 1942

Почему вращение возвращает такие совершенно не связанные размеры?

Ответы [ 3 ]

6 голосов
/ 04 января 2012

Я не профессионал в этом, но почему бы просто не создать BufferedImage правильного размера?Также обратите внимание, что ваш центр вращения неверен.Вам нужно будет вращаться по центру [w / 2, w / 2] или [h / 2, h / 2] (w - ширина, а h - высота), в зависимости от того, к какому квадранту вы поворачиваетесь, 1 или 3и относительная высота и ширина изображения.Например:

import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;

public class RotateImage {
   public static final String IMAGE_PATH = "http://duke.kenai.com/"
         + "models/Duke3DprogressionSmall.jpg";

   public static void main(String[] args) {
      try {
         URL imageUrl = new URL(IMAGE_PATH);
         BufferedImage img0 = ImageIO.read(imageUrl);
         ImageIcon icon0 = new ImageIcon(img0);

         int numquadrants = 1;
         BufferedImage img1 = transform(img0, numquadrants );
         ImageIcon icon1 = new ImageIcon(img1);

         JOptionPane.showMessageDialog(null, new JLabel(icon0));
         JOptionPane.showMessageDialog(null, new JLabel(icon1));

      } catch (MalformedURLException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      }
   }

   public static BufferedImage transform(BufferedImage image, int numquadrants) {
      int w0 = image.getWidth();
      int h0 = image.getHeight();
      int w1 = w0;
      int h1 = h0;

      int centerX = w0 / 2;
      int centerY = h0 / 2;

      if (numquadrants % 2 == 1) {
         w1 = h0;
         h1 = w0;
      }

      if (numquadrants % 4 == 1) {
         if (w0 > h0) {
            centerX = h0 / 2;
            centerY = h0 / 2;
         } else if (h0 > w0) {
            centerX = w0 / 2;
            centerY = w0 / 2;
         }
         // if h0 == w0, then use default
      } else if (numquadrants % 4 == 3) {
         if (w0 > h0) {
            centerX = w0 / 2;
            centerY = w0 / 2;
         } else if (h0 > w0) {
            centerX = h0 / 2;
            centerY = h0 / 2;
         }
         // if h0 == w0, then use default
      }

      AffineTransform affineTransform = new AffineTransform();
      affineTransform.setToQuadrantRotation(numquadrants, centerX, centerY);

      AffineTransformOp opRotated = new AffineTransformOp(affineTransform,
            AffineTransformOp.TYPE_BILINEAR);

      BufferedImage transformedImage = new BufferedImage(w1, h1,
            image.getType());

      transformedImage = opRotated.filter(image, transformedImage);
      return transformedImage;
   }
}

Изменить 1
Вы спросили:

Можете ли вы объяснить мне, почему это должно быть [w / 2, w/ 2] или [ч / 2, ч / 2]?

Чтобы лучше это объяснить, лучше всего визуализировать и физически манипулировать прямоугольником:

Вырезать прямоугольный лист бумаги и положить его на лист бумаги так, чтобы его левый верхний уголнаходится в верхнем левом углу листа бумаги - это ваше изображение на экране.Теперь проверьте, где вам нужно повернуть этот прямоугольник на 1 или 3 квадранта так, чтобы его новый верхний левый угол вышел за пределы листа, и вы поймете, почему вам нужно использовать [w / 2, w / 2] или[ч / 2, ч / 2].

4 голосов
/ 07 сентября 2012

Приведенное выше решение имело проблемы с шириной и высотой изображений код ниже не зависит от w> h || h> w

public static BufferedImage rotateImage(BufferedImage image, int quadrants) {

    int w0 = image.getWidth();
    int h0 = image.getHeight();
    int w1 = w0;
    int h1 = h0;
    int centerX = w0 / 2;
    int centerY = h0 / 2;

    if (quadrants % 2 == 1) {
        w1 = h0;
        h1 = w0;
    }

    if (quadrants % 4 == 1) {
        centerX = h0 / 2;
        centerY = h0 / 2;
    } else if (quadrants % 4 == 3) {
        centerX = w0 / 2;
        centerY = w0 / 2;
    }

    AffineTransform affineTransform = new AffineTransform();
    affineTransform.setToQuadrantRotation(quadrants, centerX, centerY);
    AffineTransformOp opRotated = new AffineTransformOp(affineTransform,
            AffineTransformOp.TYPE_BILINEAR);
    BufferedImage transformedImage = new BufferedImage(w1, h1,
            image.getType());
    transformedImage = opRotated.filter(image, transformedImage);

    return transformedImage;

}
0 голосов
/ 23 июня 2017
Ответ

furykid великолепен и очень мне помог.Но это не так идеально.Если изображение является прямоугольным, полученное повернутое изображение может содержать несколько дополнительных черных пикселей с одной стороны.

Я пробовал с фотографией Марти Фельдмана, оригинал и результаты можно посмотреть по этой ссылке: Марти Фельдмантесты вращения

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

public BufferedImage rotateImage(BufferedImage image, int quadrants) {

    int w0 = image.getWidth();
    int h0 = image.getHeight();
    /* These are not necessary anymore
    * int w1 = w0;
    * int h1 = h0;
    */
    int centerX = w0 / 2;
    int centerY = h0 / 2;

    /* This is not necessary anymore
    * if (quadrants % 2 == 1) {
    *     w1 = h0;
    *     h1 = w0;
    * }
    */

    //System.out.println("Original dimensions: "+w0+", "+h0);
    //System.out.println("Rotated dimensions: "+w1+", "+h1);

    if (quadrants % 4 == 1) {
        centerX = h0 / 2;
        centerY = h0 / 2;
    } else if (quadrants % 4 == 3) {
        centerX = w0 / 2;
        centerY = w0 / 2;
    }

    //System.out.println("CenterX: "+centerX);
    //System.out.println("CenterY: "+centerY);

    AffineTransform affineTransform = new AffineTransform();
    affineTransform.setToQuadrantRotation(quadrants, centerX, centerY);
    AffineTransformOp opRotated = new AffineTransformOp(affineTransform,
            AffineTransformOp.TYPE_BILINEAR);

    /*Old code for comparison
    //BufferedImage transformedImage = new BufferedImage(w1, h1,image.getType());
    //transformedImage = opRotated.filter(image, transformedImage);
    */
    BufferedImage transformedImage = opRotated.filter(image, null);
    return transformedImage;

}

ВНИМАНИЕ: Мнение впереди.Я не уверен в причине, почему это происходит, но у меня есть предположение. Если вы можете объяснить лучше, пожалуйста, отредактируйте.

Я считаю, что причина этого«глюк» из-за странных размеров.При расчете размеров для нового BufferedImage высота 273 сгенерирует центр Y 136, например, когда правильное значение равно 136,5.Это может привести к повороту в немного смещенном от центра месте.Однако, отправив null на filter в качестве целевого изображения, создается «BufferedImage с источником ColorModel», и это, кажется, работает лучше всего.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...