Ian Shingler
Ian Shingler

Reputation: 21

Flutter blurring image results in color bleed through rounded corners with ImageFilter.blur(). Full widget blur issue

I am trying to create a simple container widget that has rounded corners and a blurred background image. However the BackdropFilter and ImageFilter.blur() reacts poorly with creating a widget blurred to the edges. I am getting color bleed through the blur from the background color(s).

I have tried many different implementations and public blur libraries, but have not been able to get it to work. Most times the corners are still letting light bleed in.

This is in figma where I scaled the image and clipped to remove the blur: Screenshot from Figma

This is what I am able to do in flutter and it has clear color bleed: Screenshot from Flutter

I'm unsure why I cannot just apply the blur to the image only and clip off the ends like I did in figma. It seems like such an oversight on flutters side. We landed on the moon in 69' but I can't crop a blurred image 60 years later.

    return Scaffold(
      backgroundColor: Colors.red,
      body: Center(
        child: ClipRRect(
          borderRadius: BorderRadius.circular(11),
          child: Stack(
            alignment: Alignment.center,
            children: [
              Container(
                height: 174,
                width: 289,
                decoration: const BoxDecoration(
                    image: DecorationImage(
                        image: AssetImage('assets/temp_images/The_Marias.jpeg'),
                        fit: BoxFit.cover)),
              ),
              ClipRRect(
                child: BackdropFilter(
                  filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
                  child: const SizedBox(
                    height: 174,
                    width: 289,
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

I've tried every sort of stack, transform, clipping, etc I could think of and still get the same result. Could use any help or recommendations possible.

Tried blurring a background image of a container that needs a border radius. Color bleed is being applied to the blur instead of a clean mask.

Upvotes: 2

Views: 176

Answers (2)

Raouf Rahiche
Raouf Rahiche

Reputation: 31386

BackdropFilter will take a snapshot of everything that was drawn on the screen before the child widget as one piece, so the red background is also going to be blurred, which means the red color will be merged into the image. By applying the ClipRRect, the order of operations is Blur and then Clip, so you will always have the red portion mixed with final result.

blur everything

There is an open issue to allow changing this order: https://github.com/flutter/flutter/issues/154801

Assuming you just want to blur the Image, you don't have to use the BackdropFilter widget. You just need an ImageFiltered widget, which is also cheaper. Also, check the tileMode to be mirror or repeated.

class BlurredImageDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.red,
      body: Center(
        child: ClipRRect(
          borderRadius: BorderRadius.circular(11),
          child: Stack(
            alignment: Alignment.center,
            children: [
              ImageFiltered(
                imageFilter: ImageFilter.blur(
                  sigmaX: 25,
                  sigmaY: 25,
                  tileMode: TileMode.mirror,
                ),
                child: Container(
                  height: 200,
                  width: 300,
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(11),
                    image: DecorationImage(
                      image: NetworkImage('https://picsum.photos/id/237/300/200'),
                      fit: BoxFit.cover,
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

This should look like this:

fixed

Upvotes: 1

Yashas Majmudar
Yashas Majmudar

Reputation: 170

Instead of a decoration image try using normal Image.asset widget.

Scaffold(
      backgroundColor: Colors.red,
      body: Center(
        child: ClipRRect(
          borderRadius: BorderRadius.circular(11),
          child: Stack(
            children: [
              Image.asset(
                AppConstants.placeholderAsset,
                height: 174,
                width: 289,
                fit: BoxFit.cover,
              ),
              BackdropFilter(
                filter: ImageFilter.blur(
                  sigmaX: 10,
                  sigmaY: 10,
                ),
                child: const SizedBox(
                  height: 174,
                  width: 289,
                ),
              ),
            ],
          ),
        ),
      ),
    );

Upvotes: 0

Related Questions