Создание квадратных эскизов в java путем вырезания (без нарушения соотношения сторон)?

Я ищу способ создать квадратную миниатюру (250 пикселей × 250 пикселей) в Java без нарушения соотношения сторон, это означает, что если изображение прямоугольное с одной стороной длиннее другой, оно должно просто отрезать все, что не подходит площадь. Сейчас делаю вот что:

public static void createThumbnail(File file, String extension)
        throws IOException {
    BufferedImage img = new BufferedImage(
            250, 250, BufferedImage.TYPE_INT_RGB);
    img.createGraphics().drawImage(
            ImageIO.read(file).getScaledInstance(
                    250, 250, Image.SCALE_SMOOTH), 0, 0, null);
    ImageIO.write(img, extension, new File(
            "./public/images/thumbs/" + file.getName()));
}

Однако это не вырезание частей изображения, а его сжатие, чтобы поместиться внутри квадрата 250 × 250.

Отрежьте то, что делает его прямоугольным, чтобы получился квадрат. Затем уменьшите его до размера значка.

Alfe 31.10.2018 13:37
0
1
326
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы используете getScaledInstance(), который просто расширяет или сжимает ваше изображение, чтобы оно соответствовало размеру, который вы ему задаете.

Взгляните на getSubimage(). Скорее всего, вы захотите сначала получить вспомогательное изображение с таким же соотношением сторон вашего целевого размера (квадрат), а затем применить к нему getScaledInstance(). Таким образом, вы просто сжимаетесь с тем же соотношением сторон и не получаете эффекта сжатия.

Так что что-то вроде этого должно работать. Предполагая, что вы хотите сохранить среднюю часть при обрезке.

Image getThumbnail(File file) {

  BufferedImage original = ImageIO.read(file);
  //assuming we want a square thumbnail here
  int side = Math.min(original.getWidth(), original.getHeight());

  int x = (original.getWidth() - side) / 2;
  int y = (original.getHeight() - side) / 2;

  BufferedImage cropped = original.getSubimage(x, y, side, side);
  return cropped.getScaledInstance(250, 250, Image.SCALE_SMOOTH);
}

(Сам не пробовал, дайте знать, если с этим возникнут проблемы.)

Затем вы можете передать его на свой drawImage(), создав новый визуализированный BufferedImage, и сохранить его в файл.

BufferedImage img = new BufferedImage(250, 250, BufferedImage.TYPE_INT_RGB);
img.createGraphics().drawImage(getThumbnail(file), 0, 0, null);
ImageIO.write(img, extension, new File("./public/images/thumbs/" + file.getName()));

Не забывайте о ресемплинге. g.setRenderingHint(KEY_INTERPOLATION, VALUE_INTERPOLATION_BICUBIC); немного улучшает качество. Для лучшего качества используйте библиотеку передискретизации, например imgscalr или мою собственную ImageUtilities.

Mark Jeronimus 31.10.2018 13:25

Как я могу записать его обратно на диск, поскольку getScaledInstance возвращает изображение вместо BufferedImage?

Klausar 31.10.2018 14:17

@Klausar Делай то же, что и раньше. Выполните рендеринг образа в новый BufferedImage с помощью createGraphics().drawImage()

jbx 31.10.2018 15:27

Другие вопросы по теме