Java Image I/O API: resize и crop изображений | Руководство

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Работа с изображениями на Java: изменение размера (resize) и обрезка (crop)

В современной веб- и десктопной разработке на Java часто возникает необходимость программно обрабатывать изображения: уменьшать их для превью, обрезать лишние края или подгонять под заданные пропорции. В стандартной библиотеке Java (Java SE) нет единого высокоуровневого класса для этих операций, но существует мощный набор инструментов в пакетах java.awt, java.awt.image и javax.imageio. В этой статье мы подробно разберём, как выполнить операции resize (изменение размера) и crop (обрезка) с помощью встроенных средств Java.

Основные классы для работы с изображениями

Перед тем как приступить к коду, познакомимся с ключевыми классами:

  • javax.imageio.ImageIO – чтение и запись изображений (поддерживает PNG, JPEG, BMP, GIF и др.).
  • java.awt.image.BufferedImage – растровое изображение с доступом к пикселям.
  • java.awt.Graphics2D – класс для рисования (масштабирования, обрезки, наложения).
  • java.awt.geom.AffineTransform – матрица трансформации для точного масштабирования.

1. Изменение размера изображения (Resize)

Самый распространённый способ – перерисовать исходное изображение на новое полотно с нужными размерами. Для качественного результата используйте RenderingHints.

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class ImageResizer {

    public static BufferedImage resize(BufferedImage original, int targetWidth, int targetHeight) {
        BufferedImage resized = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = resized.createGraphics();

        // Настройка качества масштабирования
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        g2d.drawImage(original, 0, 0, targetWidth, targetHeight, null);
        g2d.dispose();
        return resized;
    }

    public static void main(String[] args) throws IOException {
        File input = new File("input.jpg");
        BufferedImage source = ImageIO.read(input);

        // Уменьшим до 300x200
        BufferedImage output = resize(source, 300, 200);
        ImageIO.write(output, "jpg", new File("resized.jpg"));
        System.out.println("Resize completed!");
    }
}

Важные замечания:

  • Если не задать RenderingHints, результат будет низкого качества (соседние пиксели).
  • Для PNG с прозрачностью используйте BufferedImage.TYPE_INT_ARGB.
  • Пропорции не сохраняются автоматически – при необходимости вычисляйте соотношение сторон вручную.

2. Сохранение пропорций (Aspect Ratio)

Чтобы не искажать изображение, вычислите новый размер, сохраняя пропорции:

public static BufferedImage resizeKeepRatio(BufferedImage original, int maxWidth, int maxHeight) {
    int origWidth = original.getWidth();
    int origHeight = original.getHeight();

    double widthRatio = (double) maxWidth / origWidth;
    double heightRatio = (double) maxHeight / origHeight;
    double ratio = Math.min(widthRatio, heightRatio);

    int newWidth = (int) (origWidth * ratio);
    int newHeight = (int) (origHeight * ratio);

    return resize(original, newWidth, newHeight);
}

3. Обрезка изображения (Crop)

Обрезка в Java выполняется с помощью метода getSubimage класса BufferedImage. Укажите координаты и размеры прямоугольной области.

public static BufferedImage crop(BufferedImage source, int x, int y, int width, int height) {
    // Проверка границ
    if (x < 0 || y < 0 || width <= 0 || height <= 0 ||
        x + width > source.getWidth() || y + height > source.getHeight()) {
        throw new IllegalArgumentException("Crop rectangle is out of bounds");
    }
    return source.getSubimage(x, y, width, height);
}

// Пример использования:
BufferedImage cropped = crop(source, 50, 30, 200, 150);
ImageIO.write(cropped, "png", new File("cropped.png"));

Примечание: getSubimage возвращает ссылку на ту же область памяти (не копию

Рекомендаций