Обработка изображений в Kotlin: resize и crop с библиотекой ImageMagick

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

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

Начать курс

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

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

Что такое ImageMagick и JMagick?

ImageMagick — это кроссплатформенное программное обеспечение с открытым исходным кодом для создания, редактирования и преобразования растровых изображений. Оно поддерживает более 200 форматов (JPEG, PNG, GIF, WebP, TIFF и другие). Для работы с ImageMagick из Java/Kotlin используется библиотека JMagick, предоставляющая Java Native Interface (JNI) к функциям ImageMagick.

Преимущества использования ImageMagick в Kotlin:

  • Высокая производительность (нативный код C/C++)
  • Богатый функционал: resize, crop, rotate, фильтры, конвертация форматов
  • Поддержка потоковой обработки больших изображений
  • Точный контроль качества при сжатии

Установка и подключение

Для работы с JMagick необходимо установить нативный ImageMagick на вашу систему. Затем добавьте зависимость в build.gradle.kts (для Gradle):

dependencies {
    implementation("org.im4java:im4java:1.4.0") // Альтернативная обёртка
    // Или используйте JMagick:
    implementation("org.jmagick:jmagick:6.6.9")
}

Примечание: JMagick требует установки ImageMagick версии 6.x (не 7). Для простоты в примерах мы будем использовать im4java — более современную обёртку, не требующую JNI.

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

Операция resize изменяет размеры изображения с сохранением пропорций (или без). В im4java это делается через класс ConvertCmd.

Пример: уменьшить изображение до ширины 300 пикселей, сохранив пропорции:

import org.im4java.core.ConvertCmd
import org.im4java.core.IMOperation

fun resizeImage(inputPath: String, outputPath: String, targetWidth: Int) {
    val cmd = ConvertCmd()
    val op = IMOperation()

    op.addImage(inputPath)
    op.resize(targetWidth, null) // null = авто-высота по пропорции
    op.addImage(outputPath)

    cmd.run(op)
}

fun main() {
    resizeImage("input.jpg", "output_resized.jpg", 300)
    println("Изображение уменьшено до ширины 300px")
}

Параметры resize:

  • resize(width, height) — если один параметр null, пропорции сохраняются
  • resize(width, height, "^") — минимальное заполнение области
  • resize(width, height, "!") — принудительное изменение без сохранения пропорций

Кадрирование изображения (Crop)

Crop вырезает прямоугольную область из изображения. Указываются координаты верхнего левого угла и размеры области.

Пример: вырезать центральный квадрат размером 200x200 пикселей:

import org.im4java.core.ConvertCmd
import org.im4java.core.IMOperation

fun cropImage(inputPath: String, outputPath: String, 
              x: Int, y: Int, width: Int, height: Int) {
    val cmd = ConvertCmd()
    val op = IMOperation()

    op.addImage(inputPath)
    op.crop(width, height, x, y)
    op.addImage(outputPath)

    cmd.run(op)
}

fun main() {
    // Вырезаем область: левый верхний угол (100,50), размер 400x300
    cropImage("input.jpg", "output_cropped.jpg", 100, 50, 400, 300)
    println("Изображение обрезано")
}

Для автоматического центрирования можно вычислить координаты:

fun cropCenter(inputPath: String, outputPath: String, cropSize: Int) {
    // Получаем размеры оригинального изображения (упрощённо)
    val identify = IdentifyCmd()
    val opId = IMOperation()
    opId.addImage(inputPath)
    val output = identify.run(opId) // возвращает строку с размерами

    // Парсим ширину и высоту (упрощённо)
    val dimensions = output.split(" ")[2].split("x")
    val origW = dimensions[0].toInt()
    val origH = dimensions[1].toInt()

    val x = (origW - cropSize) / 2
    val y = (origH - cropSize) / 2

    cropImage(inputPath, outputPath, x, y                    

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