Я предлагаю изучить API Java Advanced Imaging (JAI).Возможно, вы сейчас используете BufferedImage, который хранит все в памяти: исходные изображения, а также выходные изображения.Это называется обработкой в «немедленном режиме».Когда вы вызываете метод для изменения размера изображения, это происходит немедленно.В результате вы по-прежнему сохраняете изображения в памяти.
С JAI вы можете воспользоваться двумя преимуществами.
- Обработка в отложенном режиме.
- Вычисление плитки.
Отложенный режим означает, что выходные изображения не вычисляются правильно, когда вы вызываете методы для изображений.Вместо этого, вызов для изменения размера изображения создает небольшой объект «оператор», который может выполнить изменение размера позже.Это позволяет вам создавать цепочки, деревья или конвейеры операций.Таким образом, ваша работа будет создавать дерево операций, таких как «обрезать, изменять размер, составлять» для каждого изображения.Приятной особенностью является то, что операции являются просто объектами команд, поэтому вы не расходуете всю память, пока вы создаете свои команды.
Этот API основан на извлечении.Он откладывает вычисления до тех пор, пока какое-либо выходное действие не вытянет пикселей из операторов.Это быстро помогает сэкономить время и память, избегая ненужных операций с пикселями.
Например, предположим, что вам нужно выходное изображение с разрешением 2048 x 2048 пикселей, масштабированное по сравнению с кадрированием 512x512 из исходного изображения с разрешением 1600x512 пикселей.Очевидно, что не имеет смысла увеличивать все исходное изображение 1600x512, просто отбрасывая 2/3 пикселей.Вместо этого у оператора масштабирования будет «область интереса» (ROI), основанная на его выходных измерениях.Оператор масштабирования проецирует область интереса на исходное изображение и вычисляет только эти пиксели.
Команды в конечном итоге должны быть оценены.Это происходит в нескольких ситуациях, в основном связанных с выводом конечного изображения.Таким образом, запрос BufferedImage для отображения вывода на экране заставит все команды выполнить оценку.Аналогично, запись выходного изображения на диск приведет к принудительной оценке.
В некоторых случаях вы можете сохранить второе преимущество JAI - рендеринг на основе плиток.Принимая во внимание, что BufferedImage выполняет всю свою работу сразу, по всем пикселям, рендеринг тайлов одновременно работает только с прямоугольными участками изображения.
Используя предыдущий пример, выходное изображение 2048x2048 будет разбито на тайлы.Предположим, что это 256x256, тогда все изображение разбивается на 64 фрагмента.Объекты оператора JAI знают, как работать с плиткой на плитке.Таким образом, масштабирование 512x512 фрагментов исходного изображения действительно происходит 64 раза для исходных пикселей 64x64 за раз.
Одновременное вычисление фрагмента означает циклический переход между фрагментами, что, по-видимому, займет больше времени.Тем не менее, две вещи работают в вашу пользу при выполнении вычисления плитки.Во-первых, плитки могут оцениваться в нескольких потоках одновременно.Во-вторых, использование переходной памяти намного, намного ниже, чем вычисление в непосредственном режиме.
Все это длинное объяснение того, почему вы хотите использовать JAI для этого типа обработки изображений.
Несколько замечаний и предостережений:
- Вы можете победить рендеринг на основе плиток, даже не осознавая этого.Везде, где у вас есть BufferedImage в рабочем потоке, он не может выступать в качестве источника плитки или приемника.
- Если вы выполняете рендеринг на диск с помощью операторов ввода-вывода JAI или JAI Image для JPEG, то вы находитесь вхорошая фигура.Если вы попытаетесь использовать встроенные в JDK классы изображений, вам понадобится вся память.(По сути, избегайте смешивания двух типов манипуляций с изображениями. Непосредственный режим и отложенный режим плохо сочетаются.)
- Все интересные вещи с областями интереса, плитками и отложенным режимом прозрачны для программы.Вы просто делаете вызов API в классе JAI.Вы имеете дело с оборудованием только в том случае, если вам нужен больший контроль над такими вещами, как размеры листов, кэширование и параллелизм.