Обработка изображений на Java: изменение размера и обрезка (resize, crop)

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

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

Начать курс

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

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

Ключевые классы Java для обработки изображений

Прежде чем перейти к примерам, познакомимся с основными компонентами Java 2D API, которые понадобятся для работы:

  • BufferedImage — основной класс для представления изображения с доступом к пикселям.
  • Graphics2D — контекст отрисовки, позволяющий выполнять трансформации, масштабирование и рисование.
  • AffineTransform — класс для аффинных преобразований (масштабирование, поворот, сдвиг).
  • ImageIO — утилитарный класс для чтения и записи изображений в различных форматах (JPEG, PNG, BMP и др.).

Все эти классы входят в стандартную поставку JDK, поэтому для их использования не требуется подключать дополнительные зависимости (Maven/Gradle).

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

Операция изменения размера (масштабирования) может выполняться двумя основными способами: с использованием Graphics2D (наиболее гибкий метод) или через AffineTransformOp (для более точного контроля интерполяции). Рассмотрим оба подхода.

Метод 1: Через Graphics2D (рекомендуемый для большинства задач)

Этот способ подходит, когда нужно быстро изменить размер с сохранением качества. Мы рисуем исходное изображение на новом полотне BufferedImage нужного размера.

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

public class ImageResizer {

    public static BufferedImage resize(BufferedImage originalImage, int targetWidth, int targetHeight) {
        // Создаём новое изображение с указанными размерами и типом RGB
        BufferedImage resizedImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
        
        // Получаем контекст отрисовки
        Graphics2D graphics2D = resizedImage.createGraphics();
        
        // Включаем сглаживание для более качественного результата
        graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        graphics2D.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        
        // Рисуем исходное изображение, масштабируя его под новые размеры
        graphics2D.drawImage(originalImage, 0, 0, targetWidth, targetHeight, null);
        graphics2D.dispose(); // Освобождаем ресурсы
        
        return resizedImage;
    }

    public static void main(String[] args) throws Exception {
        // Читаем исходное изображение
        BufferedImage original = ImageIO.read(new File("input.jpg"));
        
        // Изменяем размер до 800x600 пикселей
        BufferedImage resized = resize(original, 800, 600);
        
        // Сохраняем результат
        ImageIO.write(resized, "jpg", new File("output_resized.jpg"));
        System.out.println("Изображение изменено и сохранено.");
    }
}

Важно: Используйте RenderingHints для улучшения качества. VALUE_INTERPOLATION_BILINEAR даёт хороший баланс между скоростью и качеством, а VALUE_INTERPOLATION_BICUBIC — максимальное качество при уменьшении.

Метод 2: Через AffineTransformOp (для точного масштабирования)

Этот метод удобен, когда нужно применить однородное масштабирование с сохранением пропорций.

import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;

public class AffineResizer {

    public static BufferedImage resizeWithTransform(BufferedImage source, double scaleX, double scaleY) {
        AffineTransform transform = new AffineTransform();
        transform.scale(scaleX, scaleY);
        
        AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
        return op.filter(source, null);
    }

    public static void main(String[] args) throws Exception {
        BufferedImage original = ImageIO.read(new File("input.jpg"));
        // Уменьшаем в 2 раза по каждой оси
        BufferedImage scaled = resizeWithTransform(original, 0.5, 0.5);
        ImageIO.write(scaled, "jpg                    

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