AffineTransformOp скорость / память вопрос

Я задавал этот вопрос раньше, но я хотел перефразировать / уточнить некоторые моменты и расширить его. У меня есть кусок кода, который преобразует BufferedImage с помощью AffineTransform.

op = new AffineTransformOp(atx, interactive ? interpolationInteractive : interpolationNormal);
displayImage = op.filter(displayImage, null);

Этот код работает нормально, однако вызывает накопление памяти. В частности, каждый раз, когда этот фрагмент кода вызывается, накапливается больше памяти. Я пробовал и другую форму фильтра.

op = new AffineTransformOp(atx, interactive ? interpolationInteractive : interpolationNormal);
displayImage2 = op.createCompatibleDestImage(displayImage, displayImage.getColorModel());
op.filter(displayImage, displayImage2);

Однако это намного медленнее, чем в первой версии. Я хочу скорость первой версии с использованием памяти второй.

  1. Как я могу очистить после первой версии? В частности, где хранятся промежуточные BufferedImages и как их удалить?
  2. Почему вторая версия медленнее первой? Что я могу сделать, чтобы ускорить его?

Спасибо за вашу помощь!!!

2 ответа

Решение

Как ты поживаешь displayImage и что ColorModel это использует?

Если это IndexColorModel, это может многое объяснить.

Первый фрагмент кода вернет BufferedImage используя DirectColorModel, Это потребует 4 байта на пиксель против обычно 1 байта на пиксель для индексированного изображения. Это расширение 1:4 может быть причиной вашей нехватки памяти.

Второй фрагмент кода делает BufferedImage с той же моделью, что и источник. Когда это IndexColorModel и интерполяция не NEAREST_NEIGHBOR, filter() вызов создаст временный BufferedImage с DirectColorModel, Он будет использовать это в качестве места назначения операции фильтрации, затем переквалифицирует временный буфер и перетянет его в ваш displayImage2, Итак, в два раза больше битблитов.

Если вы делаете только одно преобразование, я бы сказал, что перейти ко второй форме.

Если вы делаете несколько операций, выделите пару BufferedImageс DirectColorModel, достаточно большой, чтобы вместить ваше самое большое изображение. Нарисуйте исходное изображение в одном из них и выполняйте фильтры вперед и назад между ними. Затем, когда вы закончите, используйте ColorConvertOp пересмотреть обратно к проиндексированному изображению. Таким образом, вам нужно всего лишь конвертировать цвета один раз вместо каждого вызова фильтра.

Я согласен с комментарием, что если вы не получаете OutOfMemoryErrors, то это нормальная вещь, и GC будет собирать изображения всякий раз, когда сочтет нужным. Вот глупый тест, который я иногда проводил, когда у меня были проблемы: поместите его в цикл в основной функции и наблюдайте за использованием памяти в профилировщике (он должен создавать зигзагообразный шаблон или что-то в этом роде), но не всегда сможете выполнить его успешно.

Другие вопросы по тегам