Как обрезать изображение без загрузки его в память с помощью Java


Есть ли способ обрезать изображение без необходимости загружать все изображение в память и обрезать его?

Сценарий заключается в том, что у меня есть очень большой файл изображения, и у меня есть список прямоугольных координат, которые мне нужно обрезать из большого изображения. Изображение настолько огромное, что я не могу сразу загрузить его в память. Есть ли техника, с помощью которой я могу передавать изображение и находить начальную и конечную точки для обрезки? Не возражайте, если мне придется выполнять этот шаг много раз для каждого набора координирует. О да, предполагая, что изображения имеют формат JPG / PNG/TIFF, с которым всегда проще всего работать.

Должен быть в состоянии работать на Windows и Linux, если есть какие-либо зависимости от собственных библиотек.

Спасибо.

1 2

1 ответ:

Для этого можно использовать libvips - он доступен для Linux, OSX и Windows.

Чтобы настроить, давайте используем ImageMagick для создания большого изображения (10 000x10 000), которое трудно сжать, потому что оно полно случайных шумов:

convert -size 10000x10000 xc:gray +noise random  \
   -fill red  -draw "rectangle 0,0 100,100"      \
   -fill blue -draw "rectangle 9900,9900 10000,10000" BigBoy.tif
Уменьшенный в размере, он выглядит так, с красным прямоугольником в левом верхнем углу и синим прямоугольником в правом нижнем углу, если вы посмотрите внимательно:

Введите описание изображения здесь

И весит в 800 МБ:

-rw-r--r--@  1 mark  staff  800080278  5 May 12:08 BigBoy.tif

Теперь давайте использовать libvips (только в командной строке), чтобы извлечь верхний левый и нижний правый углы (которые легко опознаваемы - вы видели, что я там сделал?):

vips im_extract_area BigBoy.tif topleft.jpg 0 0 200 200 --vips-leak
memory: high-water mark 118.85 MB

Введите описание изображения здесь

vips im_extract_area BigBoy.tif bottomright.jpg 9800 9800 200 200 --vips-leak
memory: high-water mark 118.85 MB

Введите описание изображения здесь

Обе команды использовали около 120 МБ памяти. Я не верю, что существуют привязки Java для libvips, но я предполагаю, что вы можете fork() и exec() вещи или использовать что-то вроде функции C system().