Blur background android studio

Динамический blur на Android

Информации о том как быстро размыть картинку на Android существует предостаточно.
Но можно ли сделать это настолько эффективно, чтобы без лагов перерисовывать размытый bitmap при любом изменении контента, как это реализовано в iOS?

Итак, что хотелось бы сделать:

  1. ViewGroup, которая сможет размывать контент, который находится под ней и отображать в качестве своего фона. Назовем ее BlurView
  2. Возможность добавлять в нее детей (любые View)
  3. Не зависеть от какой-либо конкретной реализации родительской ViewGroup
  4. Перерисовывать размытый фон, если контент под нашей View меняется
  5. Делать полный цикл размытия и отрисовки менее чем за 16ms
  6. Иметь возможность изменять стратегию размытия

В статье я постараюсь обратить внимание только на ключевые моменты, за деталями прошу сюда.

Как получить bitmap с контентом под BlurView?

Создадим Canvas, Bitmap для него, и скажем всей View-иерархии нарисоваться на этом канвасе.

Теперь в internalBitmap нарисованы все View, которые видны на экране.

Проблемы:
Если у вашего rootView нет заданного фона, нужно предварительно нарисовать на канвасе фон Activity, иначе он будет прозрачным на битмапе.

Хотелось бы рисовать только ту часть иерархии, которая нам нужна. То есть под нашей BlurView, с соответствующим размером.
Кроме того, было бы неплохо уменьшить Bitmap, на котором будет происходить отрисовка. Это ускорит отрисовку View иерархии, сам blur, а так же уменьшит потребление памяти.
Добавляем поле scaleFactor, желательно, чтобы этот коэффициент был степенью двойки.

Уменьшаем bitmap в 8 раз и настраиваем матрицу канваса так, чтобы корректно на нем рисовать, учитывая позицию, размер и scale factor:

Теперь при вызове rootView.draw(internalCanvas), мы будем иметь на internalBitmap уменьшенную копию всей View-иерархии. Выглядеть она будет страшно, но это меня не очень волнует, т.к. дальше я все равно буду ее размывать.

Проблемы:
rootView скажет всем своим детям нарисоваться на канвасе, в том числе и BlurView. Этого хотелось бы избежать, BlurView не должна размывать сама себя. Для этого можно переопределить метод draw(Canvas canvas) в BlurView и делать проверку на каком канвасе ее просят отрисоваться.
Если это системный канвас — разрешаем отрисовку, если это internalCanvas — запрещаем.

Собственно, blur

Я сделал интерфейс BlurAlgorithm и возможность настройки алгоритма.
Добавил 2 реализации, StackBlur (by Mario Klingemann) и RenderScriptBlur. Вариант с RenderScript выполняется на GPU.
Чтобы сэкономить память, я записываю результат в тот же bitmap, который мне пришел на вход. Это опционально.
Так же можно попробовать кэшировать outAllocation и переиспользовать его, если размер входного изображения не изменился.

Когда перерисовывать blur?

Есть несколько вариантов:

  1. Вручную делать апдейт, когда вы точно знаете, что контент изменился
  2. Завязаться на события скролла, если BlurView находится над скроллящимся контейнером
  3. Слушать вызовы draw() через ViewTreeObserver

Я выбрал 3 вариант, используя OnPreDrawListener. Стоит заметить, что его метод onPreDraw дергается каждый раз, когда любая View в иерархии рисует себя. Это, конечно, не идеал, т.к. придется перерисовывать BlurView на каждый чих, но зато это не требует никакого контроля со стороны программиста.

Проблемы:
onPreDraw будет так же вызван, когда будет происходить отрисовка всей иерархии на internalCanvas, а так же при отрисовке BlurView.
Чтобы избежать этой проблемы, я завел флаг isMeDrawingNow.

Вроде все очевидно, кроме одного момента. Ставить его в false нужно через handler, т.к. диспатч отрисовки происходит асинхронно через очередь событий UI потока. Поэтому нужно так же добавить этот таск в очередь событий, чтобы он выполнился именно в конце отрисовки.

Производительность

Много статистики я не насобирал, но на Nexus 4, Nexus 5 весь цикл отрисовки занимает 1-4мс на экранах из демо-проекта.
Galaxy nexus — около 10мс.
Sony Xperia Z3 compact почему-то справляется хуже — 8-16мс.
Тем не менее, производительностью я удовлетворен, FPS держится на хорошем уровне.

Источник

Background Blur in Android

We have all seen the background blurring effects of iOS and have always wondered it does look great, it should be in Android also. I was wondering there could be an easier way to do this without actually blurring the image. Have you ever looked from blurred lens? You see blurry images. Well, that was it!

I thought if I could get a good blurry black and white image and I could just use it as an overlay and reduce opacity, it would work. I looked for images of gaussian filters in fourier space. It looked ideal for this. It sort of gave the background some gradient and vignette effect but not the blur. Frosted glass! That’s what was on the list next. Found a nice image and applied it as overlay with 70% opacity. The screen just looked dirty. No blur effect.

Читайте также:  Omacp what is android

I was wrong to begin with. Frosted glass and blurry lens product blurry images because they actually deflect light at different angles. So unless, there was some problem with my phone screen or glasses, this approach was not going to work.

So what’s next? Well, I could actually try blurring the background. What do I need?

  • A bitmap of whatever is on the screen
  • Something to blur the bitmap

As far as the latter part is concerned, we can just easily use Renderscript. Android provides a blur script which we can use. Now, coming to the first part. How to get the view into a bitmap. We know two things.

  1. View uses canvas to draw
  2. A canvas can be created from Bitmap and anything we draw on the canvas will be drawn on the bitmap.

Getting Bitmap Ready

This will give us the bitmap with the data that you actually see on the screen if you pass your rootview to it. Make sure that the view has been rendered, otherwise it will throw error as width and height would be zero.

Blur it!

If you’re not using support version of renderscript, blur scripts were included from API 17 so you need to check for that.

You can set the blurred bitmap to an ImageView or to a view’s background via BitmapDrawable.

Here’s the program in action.

Original Blurred

P.S. A blogpost coming up about the cards viewpager in the image. It’s up. Check it out — ViewPager Cards.

Playing around with Android UI

Articles focusing on Android UI — playing around with ViewPagers, CoordinatorLayout, meaningful motions and animations, implementing difficult customized views, etc.

Источник

A library for Blurring the background of a View

Blur-LIB-Android

A library for Blurring the background of a View.

How it works

The blurring is really fast since everything is fully hardware accelerated. The background View that is to be blurred is rendered into a SurfaceTexture using Surface.lockHardwareCanvas(). The SurfaceTexture is then blurred using a Guassian blur algorithm and rendered in a SurfaceView or TextureView using OpenGL.

Download

Basics

Create a BlurBehindLayout from XML

Then you need to setup the View that is behind the BlurBehindLayout (the one that will be blurred).

Blur radius

Determines how strong the blur is. Should be a float value between 0f-200f. Default is 40f.

Update mode

Determines how the BlurBehindLayout is updated. When updateMode is UpdateMode.CONTINUOUSLY, the renderer is called repeatedly to re-render the scene. When updateMode is UpdateMode.ON_SCROLL, the renderer only renders when a View is Scrolled. When updateMode is UpdateMode.MANUALLY, the renderer only renders when the surface is created and when updateForMilliSeconds(..) is called manually. This is useful when animating the background or during a transition.

Use TextureView

This can only be changed in the constructor of the BlurBehindLayout either from xml or using the regular constructor from code. Default value is false. Using TextureView should only be used when SurfaceView is’nt an option, either because the Z-ordering breaks or if you animate the BlurBehindLayout’s alpha value. Using TextureView instead of SurfaceView has a small impact on performance.

Blur texture scale

Should be a value between 0.1f-1f. It’s recommended to downsample at least to 0.5f. The scale has a big impact on performance, so try keeping it as low as possible. Default is 0.4f. This can only be set in the constructor of the BlurBehindLayout either from xml or using the regular constructor from code.

Padding vertical

You can use this to make the Blur Texture larger than the BlurBehindLayout in the vertical direction. For instance when the background View is scrolled up and down it looks better with a padding, because it reduces flicker when new pixels enter the blurred area.

Use child as alpha mask

When this is true the first child View of the BlurBehindLayout is rendered into a texture. The alpha value of that texture is then used as mask for the Blur texture. When useChildAlphaAsMask is true, useTextureView will be forced to true as well in order to support transparency.
This effect can be used for creating text with blurred background and so on. See the DialogFragment for an example.

Источник

Blur background android studio

What Is BlurKit?

BlurKit is an extraordinarily easy to use and performant utility to render real time blur effects in Android.

BlurKit is faster than other blurring libraries due to a number of bitmap retrieval and drawing optimizations. We’ve been logging benchmarks for the basic high-intensity tasks for a 300dp x 100dp BlurView:

Task BlurKit time Avg. time without BlurKit
Retrieve source bitmap 1-2 ms 8-25 ms
Blur and draw to BlurView 1-2 ms 10-50ms

This results in an average work/frame time of 2-4ms, which will be a seamless experience for most users and apps.

Add BlurKit to the dependencies block of the app level build.gradle :

Add a BlurLayout to your XML layout just like any other view.

In the Main_Activity.java you need to override the onStart() and onStop() methods to include the BlurLayout functionality.

The layout background will continuously blur the content behind it. If you know your background content will be somewhat static, you can set the layout fps to 0 . At any time you can re-blur the background content by calling invalidate() on the BlurLayout .

Other attributes you can configure are the blur radius and the downscale factor. Getting these to work together well can take some experimentation. The downscale factor is a performance optimization; the bitmap for the background content will be downsized by this factor before being drawn and blurred.

Creating BlurKit Outside Of A Layout

You can use the BlurKit class which has a few useful blurring utilities. Before using this class outside of a BlurLayout , you need to initialize BlurKit .

You can blur a View , or a Bitmap directly.

You can also fastBlur a View . This optimizes the view blurring process by allocating a downsized bitmap and using a Matrix with the bitmaps Canvas to prescale the drawing of the view to the bitmap.

  • SurfaceView support
  • Support for use outside of an Activity (dialogs, etc.)
  • Enhance retrieval of background content to only include views drawn behind the BlurLayout .

Blurkit is a sister project of CameraKit and maintained by the CameraKit team.

About

The missing Android blurring library. Fast blur-behind layout that parallels iOS.

Источник

Пишем эффективный blur на Android


Сегодня мы попытаемся разобраться с методами размытия (blur) доступными для Android разработчиков. Прочитав определенное число статей и постов на StackOverflow, можно сказать, что мнений и способов выполнить эту задачу достаточно много. Я попытаюсь собрать все это в кучу.

И так, зачем?

Все чаще и чаще можно заметить эффект размытия в приложениях появляющихся на просторах Google Play Store. Взять хотя бы замечательное приложение Muzei от +RomanNurik или тот же Yahoo Weather. Глядя на эти приложения можно заметить, что при умелом обращении размытием можно добиться очень впечатляющих результатов.

На написание данной статьи меня подтолкнула серия статей Blurring Images, поэтому первая часть статьи будет очень схожа. На самом деле я попытаюсь копнуть немного глубже.

Вот примерно то, чего мы будем пытаться добиться:

Приступим

Для начала хочу показать с чем мы работаем. Я создал 1 activity, внутри которой расположен ViewPager . ViewPager перелистывает фрагменты. Каждый фрагмент — отдельная реализация размытия.
Вот как выглядит мой main_layout.xml :

И вот как выглядит layout фрагмента (fragment_layout.xml):

Как видим, ничего военного — обычная картинка на весь экран с текстом посередине. Также можно заметить дополнительный LinearLayout — я буду его использовать для отображения всякой служебной информации.

Наша цель — размыть фон текста, тем самым подчеркнув его. Вот общий принцип того, как мы это будем делать:

  • Из картинки вырезаем тот участок, который находится непосредственно за TextView
  • Размываем
  • Получившийся результат ставим как фон для TextView

Renderscript

Наверное, самым популярным ответом сегодня на вопрос «как быстро размыть картинку в Android» является Renderscript. Это очень мощный инструмент для работы с изображениями. Несмотря на его кажущуюся сложность, многие его части очень даже просты в использовании. К счастью, blur — это одна из подобных частей.

Давайте разберемся что же здесь происходит:

  • При создании фрагмента — создается layout, добавляется TextView в мою «сервисную панель»(я ее буду использовать чтобы отображать скорость работы алгоритма) и запускается размытие
  • Внутри applyBlur() я регистрирую onPreDrawListener . Делаю я это потому, что на момент вызова этой функции мои UI элементы еще не готовы, поэтому и размывать-то особо нечего. Поэтому мне надо дождаться момента когда мой layout будет измерян и готов к отрисовке. Этот колбэк будет вызван непосредственно перед отрисовкой первого фрейма
  • Внутри onPreDraw() первым делом что я обычно делаю — это меняю возвращаемое значение на true. Дело в том, что IDE генерирует false по умолчанию, а это значит, что отрисовка первого фрейма будет пропущена. В данном случае меня интересует первый фрейм, поэтому ставим true.
  • Далее убираем наш колбек — нас больше не интересуют onPreDraw события
  • Теперь мне надо вытащить Bitmap из моей ImageView. Заставляю ее создать drawing cache и забираю его
  • Ну и, собственно, размытие. Рассмотрим этот процесс подробнее

Сразу хочу отметить, что данный код имеет ряд недостатков, о которых следует обязательно помнить:

  • Данный код не «переразмывает» при изменениях layout’a. По-хорошему необходимо зарегистрировать onGlobalLayoutListener и перезапускать алгоритм при получении этого события
  • Размытие производится в главном потоке. Не пытайтесь делать это в своих приложениях — подобного рода операции надо «выгружать» в отдельный поток, чтобы не блокировать UI. AsyncTask или что-то подобное справятся с этой задачей

Вернемся к blur() :

  • Создается пустой Bitmap, по размеру соответствующий нашему TextView — сюда мы скопируем кусок нашего фона
  • Создаем Canvas, чтобы можно было в этот Bitmap рисовать
  • Смещаем систему координат на позицию, на которой находится TextView
  • Рисуем кусок фона
  • На этом этапе у нас есть Bitmap, который содержит кусок фона, находящийся непосредственно за TextView
  • Создаем Renderscript объект
  • Копируем наш Bitmap в структуру, с которой работает Renderscript
  • Создаем скрипт для размытия (ScriptIntrinsicBlur)
  • Выставляем параметры размытия (в моем случае радиус 20) и запускаем скрипт
  • Копируем результат обратно в наш Bitmap
  • Отлично, у нас есть размытый Bitmap — устанавливаем его как фон для нашего TextView

Вот что получилось:

Как видим, результат довольно неплох на вид и занял у нас 57ms. Учитывая, что на отрисовку одного фрейма не должно уходить больше 16мс (

60fps), можно посчитать, что frame rate в нашем случае упадет до 17fps на период пока выполняется размытие. Я бы сказал, неприемлимо. Имеено поэтому необходимо сгрузить размытие в отдельный поток.

Хочу также заметить, что ScriptIntrinsicBlur доступен в API > 16. Безусловно, можно использовать renderscript support library, что позволит снизить необходимый уровень API.
Но, как нетрудно догадаться, на renderscript’e свет клином не сошелся, поэтому давайте рассмотрим одну из альтернатив.

FastBlur

На самом деле размытие — ничто иное как манипуляция с пикселями, поэтому что нам мешает самим этими самыми пикселями и поманипулировать? Благо, на просторах интернета доступно довольно большое кол-во реализаций всевозможных алгоритмов размытия, поэтому наша задача сводится к тому, чтобы выбрать наиболее оптимальный.
На всезнающем StackOverflow (а точнее тут), я наткнулся на неплохую реализацию алгоритма размытия.

Давайте посмотрим что из этого получилось. Весь код приводить не буду, потому что отличаться будет только функция blur():

И вот результат:

Как видим, по качеству сложно заметить разницу с renderscript. Но вот производительность оставляет желать лучшего — 147ms! И это далеко не самый медленный алгоритм! Боюсь даже пробовать размывать по Гауссу.

Оптимизируем

Давайте на секунду задумаемся что из себя представляет размытие. По своей сути размытие очень тесно связано с «потерей» пикселей (здесь хотел бы попросить сильно не ругаться знатоков математики и графики, потому что описываю больше основываясь на свое понимание проблемы, чем на конкретные факты 🙂 ). Что же еще может легко нам помочь «потерять» пиксели? Уменьшение картинки!

Что если мы уменьшим картинку сначала, размоем ее, а потом увеличим обратно?

И так, имеем 13ms renderscript и 2ms FastBlur. Довольно неплохо, учитывая, что качество размытия осталось сравнимо по качеству с предыдущими результатами.

Давайте взглянем на код. Я опишу только вариант с FastBlur, т.к. код для Renderscript будет аналогичен (ссылка на полную версию кода доступна в конце статьи):

  • scaleFactor определяет насколько сильно будем уменьшать картинку. В моем случае уменьшать будем в 8 раз. Причем учитывая что львиную долю пикселей мы потеряем при уменьшении/увеличении картинки, можно смело уменьшать радиус размытия основного алгоритма. Путем научного тыка я уменьшил до 2х
  • Создаем Bitmap. В этот раз он будет меньше — в данном случае в 8 раз.
  • Заметим, что при отрисовке, я выставил флаг FILTER_BITMAP_FLAG , что позволит применить сглаживание при изменении размера картинки
  • Как и прежде, применяем размытие, но теперь ко много меньшей картинке и с меньшим радиусом, что позволяет ускорить алгоритм
  • Ставим эту маленькую картинку как фон для TextView — она автоматически будет увеличена.

Довольно интересно, что Renderscript отработал медленнее, чем FastBlur. Произошло это из-за того, что мы сэкономили время на копировании Bitmap в Allocation и обратно.

Как результат, мы получили довольно шустрый метод размытия картинок на Android

Источник

Читайте также:  Hello neighbor indir android
Оцените статью