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