В настоящее время в приложении для Android, которое я разрабатываю, я зацикливаюсь на пикселях изображения, чтобы размыть его. Это занимает около 30 секунд для изображения 640x480.
Просматривая приложения в Android Market, я наткнулся на одно, которое включает функцию размытия, и их размытие очень быстрое (около 5 секунд), поэтому они должны использовать другой метод размытия.
Кто-нибудь знает более быстрый способ, чем циклический просмотр пикселей?
Ответы:
Это снимок в темноте, но вы можете попробовать уменьшить изображение, а затем снова увеличить его. Это можно сделать с помощью
Bitmap.createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter)
. Убедитесь, что для параметра фильтра установлено значение true. Он будет работать в собственном коде, поэтому он может быть быстрее.источник
Для будущих гуглеров, вот алгоритм, который я перенес из Quasimondo. Это своего рода смесь между размытием рамки и размытием по Гауссу, она очень красивая и довольно быстрая.
Обновление для людей, сталкивающихся с проблемой ArrayIndexOutOfBoundsException: @anthonycr в комментариях предоставляет следующую информацию:
источник
for
цикле непосредственно перед плохим разыменованием, либо вычислениеrbs
переменной, либо вычислениеgsum
,rsum
илиbsum
переменные выполняются неправильно. Я обнаружил , что путем заменыMath.abs
сStrictMath.abs
или какой - либо другойabs
реализацией, аварии не происходят. ПосколькуStrictMath.abs
сам делегатMath.abs
, кажется, что это должна быть плохая оптимизация.Android Blur Guide 2016
с приложением Showcase / Benchmark и источником на Github . Также ознакомьтесь с фреймворком Blur, над которым я сейчас работаю: Dali .
После долгих экспериментов я могу смело дать вам несколько убедительных рекомендаций, которые облегчат вашу жизнь в Android при использовании Android Framework.
Загрузите и используйте уменьшенное изображение (для очень размытых изображений)
Никогда не используйте полный размер растрового изображения. Чем больше изображение, тем больше должно быть размытия, а также чем больше должен быть радиус размытия, и обычно, чем больше радиус размытия, тем дольше длится алгоритм.
Это загрузит растровое изображение с
inSampleSize
8, так что только 1/64 исходного изображения. Проверьте, чтоinSampleSize
соответствует вашим потребностям, но оставьте 2 ^ n (2,4,8, ...), чтобы избежать ухудшения качества из-за масштабирования. Смотрите Google Doc для болееЕще одно большое преимущество заключается в том, что загрузка растровых изображений будет очень быстрой. В моем раннем тесте размытия я понял, что самое длительное время в течение всего процесса размытия была загрузка изображения. Таким образом, чтобы загрузить изображение 1920x1080 с диска, моему Nexus 5 понадобилось 500 мс, а размытие заняло еще 250 мс или около того.
Используйте Renderscript
Renderscript предоставляет
ScriptIntrinsicBlur
фильтр размытия по Гауссу. Он имеет хорошее визуальное качество и является самым быстрым на Android. Google утверждает, что «как правило, в 2-3 раза быстрее, чем многопоточная реализация C, и часто в 10 раз быстрее, чем реализация Java» . Renderscript действительно сложен (использует самое быстрое устройство обработки (GPU, ISP и т. Д.) И т. Д.), И есть библиотека поддержки v8, что делает его совместимым до 2.2, Ну, по крайней мере, теоретически, благодаря моим собственным тестам и отчетам от других разработчиков кажется, что невозможно использовать Renderscript вслепую, поскольку фрагментация аппаратного обеспечения / драйвера, кажется, вызывает проблемы с некоторыми устройствами, даже с более высоким уровнем SDK (например, у меня было проблемы с 4.1 Nexus S), поэтому будьте осторожны и тестируйте на многих устройствах. Вот простой пример, который поможет вам начать:При использовании поддержки v8 с Gradle, что особенно рекомендовано Google «потому что они включают в себя последние улучшения» , вам нужно всего лишь добавить 2 строки в ваш скрипт сборки и использовать
android.support.v8.renderscript
с текущими инструментами сборки ( обновленный синтаксис для плагина Android Gradle v14 + )Простой тест на Nexus 5 - сравнение RenderScript с другими реализациями java и Renderscript:
Среднее время выполнения для размытия на разных размерах изображения
Мегапикселей в секунду, которые могут быть размыты
Каждое значение составляет в среднем 250 раундов.
RS_GAUSS_FAST
естьScriptIntrinsicBlur
(и почти всегда самый быстрый), другие, которые начинаются сRS_
, в основном представляют собой свернутые реализации с простыми ядрами. Подробности алгоритмов можно найти здесь . Это не просто размытие, так как хорошая часть - это сборка мусора, которая измеряется. Это можно увидеть здесь (ScriptIntrinsicBlur
на изображении 100x100 с 500 раундами)Шипы являются gc.
Вы можете проверить сами, приложение для тестирования находится в игровом магазине: BlurBenchmark
Использует растровое изображение везде, где это возможно (если prio: производительность> объем памяти)
Если вам нужно несколько размытий для живого размытия или тому подобного, и ваша память позволяет ему не загружать растровое изображение из рисоваемых объектов несколько раз, а сохранять его «кэшированным» в переменной-члене. В этом случае всегда старайтесь использовать одни и те же переменные, чтобы свести сбор мусора к минимуму.
Также проверьте новую
inBitmap
опцию при загрузке из файла или отрисовки, которая будет повторно использовать растровую память и сэкономит время сборки мусора.Для смешивания от резкого до размытого
Простой и наивный метод состоит в том, чтобы просто использовать 2
ImageViews
, один размытый, и альфа исчезать их. Но если вы хотите более изысканный вид, плавно переходящий от резкого к расплывчатому, посмотрите на пост Романа Нурика о том, как это сделать, как в его приложении Muzei .В основном он объясняет, что он предварительно размывает некоторые кадры с различными степенями размытия и использует их в качестве ключевых кадров в анимации, которая выглядит действительно плавной.
источник
renderscriptSupportModeEnabled true
или он не будет собираться ! Я искал вечно!РЕДАКТИРОВАТЬ (апрель 2014 г.): Это страница вопросов / ответов, которая все еще получает много просмотров, как кажется. Я знаю, что я всегда получаю голоса за этот пост. Но если вы читаете это, вы должны понимать, что ответы, опубликованные здесь (и мой, и принятый ответ), устарели. Если вы хотите реализовать эффективное размытие сегодня , вы должны использовать RenderScript вместо NDK или Java. RenderScript работает на Android 2.2+ (с использованием библиотеки поддержки Android ), поэтому нет причин не использовать его.
Старый ответ следует, но будьте осторожны, поскольку он устарел.
Для будущих пользователей Google, вот алгоритм, который я перенес из порта Яхеля в алгоритм Квазимондо, но с использованием NDK. Конечно, это основано на ответе Яхеля. Но это работает собственный код C, так что это быстрее. Намного быстрее. Мол, в 40 раз быстрее.
Я обнаружил, что использование NDK - это то, как все манипуляции с изображениями должны выполняться на Android ... сначала это несколько раздражает (прочитайте большое руководство по использованию JNI и NDK здесь ), но гораздо лучше и почти в режиме реального времени для много вещей.
Для справки: с помощью Java-функции Yahel потребовалось 10 секунд, чтобы смазать мое изображение размером 480x532 пикселей с радиусом размытия 10. Но при использовании родной версии C потребовалось 250 мс. И я почти уверен, что он еще может быть оптимизирован ... Я просто сделал глупое преобразование кода Java, возможно, есть некоторые манипуляции, которые можно сократить, не хотел тратить слишком много времени на рефакторинг всего этого.
Затем используйте его следующим образом (учитывая класс com.insert.your.package.ClassName и нативную функцию functionToBlur, как показано в коде выше):
Ожидается растровое изображение RGB_8888!
Чтобы использовать растровое изображение RGB_565, либо создайте преобразованную копию перед передачей параметра (yuck), либо измените функцию, чтобы использовать новый
rgb565
тип вместоrgba
:Проблема в том, что если вы делаете то, что не можете прочитать
.red
,.green
и.blue
пикселя больше, вам нужно правильно прочитать байт, да. Когда мне это было нужно раньше, я делал это:Но, вероятно, есть какой-то менее глупый способ сделать это. Боюсь, я не очень низкоуровневый C-кодер.
источник
r[wh]
,g[wh]
иb[wh]
вuint8_t
.pastebin.com
Этот код идеально подходит для меня
источник
Теперь вы можете использовать ScriptIntrinsicBlur из библиотеки RenderScript для быстрого размытия. Вот как получить доступ к API RenderScript. Ниже приведен класс, который я сделал для размытия видов и растровых изображений:
источник
Для меня это работало нормально: как эффективно размыть изображения с помощью Android RenderScript
источник
Используйте скрипт рендеринга, как упомянуто здесь http://blog.neteril.org/blog/2013/08/12/blurring-images-on-android/
источник
Это для всех людей, которым нужно увеличить радиус,
ScriptIntrinsicBlur
чтобы получить более жесткое размытие по Гауссу.Вместо того, чтобы поставить радиус больше 25, вы можете уменьшить изображение и получить тот же результат. Я написал класс под названием
GaussianBlur
. Ниже вы можете увидеть, как использовать и весь класс реализации.Использование:
Класс:
источник
Спасибо @Yahel за код. Публикация того же метода с поддержкой размытия альфа-канала, поскольку мне потребовалось некоторое время, чтобы заставить его работать правильно, чтобы он мог сэкономить чье-то время:
источник
Я использовал это раньше ..
источник
Для будущих Googlers, которые выбирают подход NDK - я нахожу надежный упомянутый алгоритм stackblur. Я нашел реализацию C ++, которая не зависит от SSE здесь - http://www.antigrain.com/__code/include/agg_blur.h.html#stack_blur_rgba32, которая содержит некоторые оптимизации с использованием статических таблиц, таких как:
Я сделал модификацию алгоритма stackblur для многоядерных систем - его можно найти здесь http://vitiy.info/stackblur-algorithm-multi-threaded-blur-for-cpp/ Поскольку все больше и больше устройств имеют 4 ядра, оптимизации дают 4х скоростное преимущество.
источник
Николя ПОМЕПУЙ совет. Я думаю, что эта ссылка будет полезна: эффект размытия для дизайна Android
Пример проекта на GitHub
источник
Мы попытались реализовать размытие RenderScript, как указано выше в разных ответах. Мы были ограничены в использовании версии RenderScript v8, и это доставило нам много хлопот.
Я хочу поделиться нашей грязной версией только для Java, которая медленная и должна быть сделана в отдельном потоке и, если возможно, перед использованием и, следовательно, сохранена.
Это решение далеко от совершенства, но создает разумный эффект размытия, основанный на том факте, что оно рисует высокопрозрачную версию того же изображения поверх едва прозрачной «острой» версии. Альфа зависит от расстояния до начала координат.
Вы можете настроить некоторые "магические числа" в соответствии с вашими потребностями. Я просто хотел поделиться этим «решением» для всех, у кого есть проблемы с версией RenderScript для поддержки v8.
источник
Для тех, у кого все еще есть проблемы с библиотекой поддержки Renderscript на чипсетах x86, пожалуйста, посмотрите на этот пост создателя библиотеки. Похоже, что подготовленное им исправление каким-то образом не помогло Build Tools v20.0.0, поэтому он предоставляет файлы для исправления вручную и краткое объяснение того, как это сделать.
https://code.google.com/p/android/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars&groupby=&sort=&id=71347
источник
из блога Марио Вивиани можно использовать это решение из 17 версии Android:
https://plus.google.com/+MarioViviani/posts/fhuzYkji9zz
или
https://gist.github.com/Mariuxtheone/903c35b4927c0df18cf8
источник
Вот размытое в реальном времени наложение с использованием RenderScript, которое кажется достаточно быстрым.
https://github.com/mmin18/RealtimeBlurView
источник
Я обнаружил, что уменьшение контраста, яркости и насыщенности немного делает размытые изображения более красивыми, поэтому я объединил различные методы от переполнения стека и создал класс размытия, который работает с размытыми изображениями, изменением яркости, насыщенности, контрастности и размера размытых изображений. Он также может конвертировать изображения из растрового в растровое и наоборот.
источник
На I / O 2019 было представлено следующее решение:
источник