How to Use -Webkit-Filter: Blur(); on Background-Image

css blend/blur/merge backgrounds images

this can be done using mask.

Here is a simplified example:

.box {
height:60vh;
font-size:50px;
text-align:center;
color:#fff;
position:relative;
z-index:0;
}
.box:before {
content:"";
position:absolute;
z-index:-1;
left:0;
right:0;
top:-50px;
bottom:-50px;
background:var(--img) center/cover;
-webkit-mask:linear-gradient(transparent ,#fff 50px calc(100% - 50px),transparent);
mask:linear-gradient(transparent ,#fff 50px calc(100% - 50px),transparent);
}
<div class="box" style="--img:url(https://picsum.photos/id/1002/800/800.jpg)">text 1</div>
<div class="box" style="--img:url(https://picsum.photos/id/109/800/800.jpg)">text 2</div>
<div class="box" style="--img:url(https://picsum.photos/id/107/800/800.jpg)">text 3</div>
<div class="box" style="--img:url(https://picsum.photos/id/177/800/800.jpg)">text 4</div>

How to blur the background behind a control

If want to blur the image behind the Button (or a transparent control in general) you have to follow a different approach.

You need the exact tile of the image in order to blur it using the BlurEffect.

In order to not blur the Button itself, you must add alayer beneath the button that has the BlurEffect applied.

The following example extends a ContentControl named BlurHost that renders the Content e.g., the Button, on top of a Border element that will actualy blur the background using a VisualBrush.

The brush itself has a tile defined that is located at the position of the BlurHost which hosts the Button (or any other transparent control).

The basic steps to implement a blurred background:

  1. Add the background image
  2. Create a blur layer beneath the element
  3. Get the bounds of the element e.g., the Button which is located relative to the parent of the Image (preferably the root container)
  4. Use the bounding rectangle to define the tile of the VisualBrush (the actual section of the image)
  5. Apply the brush on the blur layer

Usage example

MainWindow.xaml

<Window>
<!-- Allow the root grid to stretch accross the Window -->
<Grid>
<Image x:Name="img" Source="/someImage.png" />

<!--
Optionally override the default BlurEffect
by setting the BlurHost.BlurEffect property
-->
<local:BlurHost BlurBackground="{Binding ElementName=img}"
BlurOpacity="1"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Button Background="Transparent"
FontSize="48"
Content="Acquista ora- $23.99" />
</local:BlurHost>
</Grid>
</Window>

Sample Image

Implementation example

The implementation is simple. You have to add property changed handlers in order to make the control dynamic.

BlurHost.cs

The ContentControl serves as a container. The blurred background is visible at the transparent areas of the content.

public class BlurHost : ContentControl
{
public Visual BlurBackground
{
get => (Visual)GetValue(BlurBackgroundProperty);
set => SetValue(BlurBackgroundProperty, value);
}

public static readonly DependencyProperty BlurBackgroundProperty =
DependencyProperty.Register(
"BlurBackground",
typeof(Visual),
typeof(BlurHost),
new PropertyMetadata(default(Visual), OnBlurBackgroundChanged));

public double BlurOpacity
{
get => (double)GetValue(BlurOpacityProperty);
set => SetValue(BlurOpacityProperty, value);
}

public static readonly DependencyProperty BlurOpacityProperty =
DependencyProperty.Register(
"BlurOpacity",
typeof(double),
typeof(BlurHost),
new PropertyMetadata(1.0));

public BlurEffect BlurEffect
{
get => (BlurEffect)GetValue(BlurEffectProperty);
set => SetValue(BlurEffectProperty, value);
}

public static readonly DependencyProperty BlurEffectProperty =
DependencyProperty.Register(
"BlurEffect",
typeof(BlurEffect),
typeof(BlurHost),
new PropertyMetadata(
new BlurEffect()
{
Radius = 10,
KernelType = KernelType.Gaussian,
RenderingBias = RenderingBias.Performance
}));

private Border PART_BlurDecorator { get; set; }
private VisualBrush BlurDecoratorBrush { get; set; }

static BlurHost()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(BlurHost), new FrameworkPropertyMetadata(typeof(BlurHost)));
}

public BlurHost()
{
Loaded += OnLoaded;

// TODO::Update Opacity of VisualBrush when property BlurOpacity changes
this.BlurDecoratorBrush = new VisualBrush()
{
ViewboxUnits = BrushMappingMode.Absolute,
Opacity = this.BlurOpacity
};
}

private void DrawBlurredElementBackground()
{
if (!TryFindVisualRootContainer(this, out FrameworkElement rootContainer))
{
return;
}

// Get the section of the image where the BlurHost element is located
Rect elementBounds = TransformToVisual(rootContainer)
.TransformBounds(new Rect(this.RenderSize));

// Use the section bounds to actually "cut out" the image tile
this.BlurDecoratorBrush.Viewbox = elementBounds;
}

private void OnLoaded(object sender, RoutedEventArgs e)
{
if (TryFindVisualRootContainer(this, out FrameworkElement rootContainer))
{
rootContainer.SizeChanged += OnRootContainerElementResized;
}

DrawBlurredElementBackground();
}

public override void OnApplyTemplate()
{
base.OnApplyTemplate();
this.PART_BlurDecorator = GetTemplateChild("PART_BlurDecorator") as Border;
this.PART_BlurDecorator.Effect = this.BlurEffect;
this.PART_BlurDecorator.Background = this.BlurDecoratorBrush;
}

private static void OnBlurBackgroundChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var this_ = d as BlurHost;
this_.BlurDecoratorBrush.Visual = e.NewValue as Visual;
this_.DrawBlurredElementBackground();
}

private void OnRootContainerElementResized(object sender, SizeChangedEventArgs e)
=> DrawBlurredElementBackground();

private bool TryFindVisualRootContainer(DependencyObject child, out FrameworkElement rootContainerElement)
{
rootContainerElement = null;
DependencyObject parent = VisualTreeHelper.GetParent(child);
if (parent == null)
{
return false;
}

if (parent is not Window visualRoot)
{
return TryFindVisualRootContainer(parent, out rootContainerElement);
}

rootContainerElement = visualRoot.Content as FrameworkElement;
return true;
}
}

Generic.xaml

The default Style for the BlurHost. The Generic.xaml file is located in the Themes folder of the application (project).

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Net.Wpf">

<Style TargetType="local:BlurHost">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:BlurHost">
<Grid>

<!-- Blur layer beneath the hosted element (ContentPresenter) -->
<Border x:Name="PART_BlurDecorator"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"/>
<ContentPresenter />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

How to blur background images in Android

The easiest way to do that is use a library. Take a look at this one: https://github.com/wasabeef/Blurry

With the library you only need to do this:

Blurry.with(context)
.radius(10)
.sampling(8)
.color(Color.argb(66, 255, 255, 0))
.async()
.onto(rootView);

How to detect luminance of a container with background blur to change the colour of the text

I made a widget as a fun exercise and a proof-of-concept, called PixelDataOverlay. It has a background builder and an overlay builder.

When being used, it'll call background builder first to build the underlying widget (a picture or whatever). And then it will extract pixel data from what's built. Then it will call overlay builder and pass the pixel data back to you, so you can decide how to build the overlay based on the information you received.

Key Usage:

PixelDataOverlay(
background: (BuildContext context) {
return ImageFiltered( /* ... */ );
},
overlay: (BuildContext context, Uint8List? bytes) {
final score = PixelDataOverlay.getBrightnessFromBytes(bytes);
return Text('Background is ${score > 0 ? 'bright' : 'dark'}');
},
)

Demo:

demo gif

Full source:

import 'dart:typed_data';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Demo(),
),
),
);
}
}

class Demo extends StatefulWidget {
const Demo({Key? key}) : super(key: key);

@override
_DemoState createState() => _DemoState();
}

class _DemoState extends State<Demo> {
final List<double> _sliderValues = [0.8, 0.8, 0.2, 1.0];

@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
PixelDataOverlay(
background: (BuildContext context) {
return ClipRect(
child: ImageFiltered(
imageFilter: ImageFilter.blur(sigmaX: 20.0, sigmaY: 20.0),
child: Container(
color: Color.fromARGB(
(_sliderValues[3] * 255).clamp(0, 255).round(),
(_sliderValues[0] * 255).clamp(0, 255).round(),
(_sliderValues[1] * 255).clamp(0, 255).round(),
(_sliderValues[2] * 255).clamp(0, 255).round(),
),
child: FlutterLogo(size: 100),
),
),
);
},
overlay: (BuildContext context, Uint8List bytes) {
final score = PixelDataOverlay.getBrightnessFromBytes(bytes);
return Center(
child: Text(
'Brightness: \n${score.toStringAsFixed(2)}',
style: TextStyle(
color: score > 0 ? Colors.black : Colors.white,
),
),
);
},
),
const SizedBox(height: 48),
_buildControls(),
],
);
}

_buildControls() {
return Column(
children: [
Text('Adjust the sliders to see the effect of the blur filter.\n'
'The sliders are: Red, Green, Blue, Alpha.'),
for (int i = 0; i < 4; i++)
Slider(
value: _sliderValues[i],
onChanged: (v) => setState(() => _sliderValues[i] = v),
),
],
);
}
}

class PixelDataOverlay extends StatefulWidget {
final WidgetBuilder background;
final Widget Function(BuildContext context, Uint8List bytes) overlay;

const PixelDataOverlay(
{Key? key, required this.background, required this.overlay})
: super(key: key);

@override
_PixelDataOverlayState createState() => _PixelDataOverlayState();

/// Returns the brightness score for the given [bytes] containing raw image
/// data. A positive score indicates that the image is (on average) bright,
/// while a negative score indicates that the image is dark.
static double getBrightnessFromBytes(Uint8List bytes) {
// Keep track of total brightness of the image.
// For each pixel, assign positive value if it's bright.
// For example: +1 for #FFFFFF, -1 for #000000.
// So for neutral grey, its score will be close to 0.
// However, if alpha is not FF, the score is discounted accordingly.
// For example: `Colors.black.withOpacity(0.5)` has a score of `-0.5`.
double totalScore = 0.0;

for (int i = 0; i < bytes.length; i += 4) {
final r = bytes[i];
final g = bytes[i + 1];
final b = bytes[i + 2];
final a = bytes[i + 3];
final brightness = (0.2126 * r + 0.7152 * g + 0.0722 * b); // 0 to 255
final normalized = (brightness / 127.5 - 1) * (a / 255); // -1 to 1
totalScore += normalized;
}
return totalScore;
}
}

class _PixelDataOverlayState extends State<PixelDataOverlay> {
final _globalKey = GlobalKey();
Uint8List? _bytes;

@override
void initState() {
super.initState();
}

@override
void didUpdateWidget(covariant PixelDataOverlay oldWidget) {
super.didUpdateWidget(oldWidget);
WidgetsBinding.instance!.addPostFrameCallback((_) {
_capture();
});
}

@override
Widget build(BuildContext context) {
return Stack(
children: [
RepaintBoundary(
key: _globalKey,
child: widget.background(context),
),
if (_bytes != null)
Positioned(
top: 0,
left: 0,
bottom: 0,
right: 0,
child: widget.overlay(context, _bytes!),
),
],
);
}

void _capture() async {
final render = (_globalKey.currentContext!.findRenderObject()
as RenderRepaintBoundary);
final imageBytes = (await (await render.toImage())
.toByteData(format: ImageByteFormat.rawStraightRgba))!
.buffer
.asUint8List();
setState(() => _bytes = imageBytes);
}
}

I want to blur only the image but it affects everything

Using the code given in the question, and assuming it's the body that the background is required on, you can add a pseudo before element to the body and put the background on that and blur it.

That way only the image gets blurred, not everything else.

body {
font-size: 15pt;
width: 500px;
height: 500px;
}

body::before {
background-image: url("https://picsum.photos/id/1015/1024/768");
filter: blur(8px);
background-size: cover;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: inline-block;
content: '';
z-index: -1;
}

.trbp {
width: 500px;
height: 40px;
border: black;
}

.trb {
position: relative;
left: 440px;
width: 60px;
background-color: cyan;
border-radius: 5px;
display: inline-block;
}

.btp {
position: relative;
top: 120px;
left: 30px;
}

.bth {
position: relative;
top: 100px;
left: 30px;
}

.blb {
position: relative;
top: 80px;
left: 60px;
border-radius: 4px;
background-color: #0731D2;
}
<div class="trbp"><button class="trb">sign up</button></div>
<div class="aio">
<h2 class="btp">welcom to</h2>
<h2 class="bth">our site</h2>
<button class="blb">about us</button></div>
<script src="main.js"></script>


Related Topics



Leave a reply



Submit