Вопрос о скорости/памяти AffineTransformOp
-
12-09-2019 - |
Вопрос
Я уже задавал этот вопрос раньше, но хотел перефразировать/уточнить некоторые моменты и расширить его.У меня есть фрагмент кода, который преобразует 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);
Однако это намного медленнее, чем первая версия.Мне нужна скорость первой версии при использовании памяти второй.
- Как можно почистить после первой версии?В частности, где хранятся промежуточные BufferedImages и как их удалить?
- Почему вторая версия медленнее первой?Что я могу сделать, чтобы ускорить его?
Спасибо за вашу помощь!!!
Решение
Как ты поживаешь displayImage
и что ColorModel
оно использует?
Если это IndexColorModel
, это может многое объяснить.
Первый фрагмент кода вернет BufferedImage
используя DirectColorModel
.Для этого потребуется 4 байта на пиксель вместо обычно 1 байта на пиксель для индексированного изображения.Расширение 1:4 может быть причиной нехватки памяти.
Второй фрагмент кода делает BufferedImage
с той же моделью, что и источник.Когда это IndexColorModel
и интерполяция не NEAREST_NEIGHBOR
, filter()
вызов создаст временный BufferedImage
с DirectColorModel
.Он будет использовать это как место назначения операции фильтра, затем повторно квантовать временный буфер и перерисовать его в свой displayImage2
.Итак, в два раза больше битблитов.
Если вы выполняете только одно преобразование, я бы посоветовал использовать вторую форму.
Если вы выполняете несколько операций, выделите пару BufferedImage
с DirectColorModel
.достаточно большой, чтобы вместить самое большое изображение.Нарисуйте исходное изображение в одном из них и применяйте фильтры между ними.Затем, когда вы закончите, используйте ColorConvertOp
для повторного квантования обратно в индексированное изображение.Таким образом, вам нужно будет конвертировать цвета только один раз, а не при каждом вызове фильтра.
Другие советы
Я согласен с комментарием о том, что если вы не получаете OutOfMemoryErrors, то это нормально, и сборщик мусора будет собирать изображения, когда сочтет нужным.Вот глупый тест, который я проводил иногда, когда у меня возникали опасения:поместите это в цикл в основной функции и наблюдайте за использованием памяти в профилировщике (он должен создавать зигзагообразный узор или что-то в этом роде), но не всегда сможет завершиться успешно.