Preface

I know, many of you were expecting a next post on RxVMS but you will need a bit more patience. I didn’t have time for most of this year due to projects and my repeatedly manifesting depression. I’m very open with that because I know many in our industry struggle with mental issues and they should know they are not alone.

The other reason is that I continuously collect experience with RxVMS in projects and want to consolidate this experience before updating and extending the blog series.

So here comes a post about a totally different topic that I had to solve not long ago and about that I’m really exited because it features a widely unknown Widget.

ColorFilters

Some weeks ago I was looking for a way to invert the colours of a monochrome icon and at first it looked like that it wouldn’t be possible with Flutter. Luckily one of my Twitter followers mentioned a ColorFiltered widget, a thing I never had heard of before.

Looking at the API docs I had no clue how to use it. In the mean time the docs got a bit extended after I reported it to the Flutter team, but still I think it might be worth to give you a more thorough explanation.

In short ColorFiltered applies a ColorFilter on its child (who would have guessed that 😉 ). So far so good, but what is a ColorFilter . A ColorFilter can be created by numerous constructors from which ColorFilter.matrix is the most powerful and versatile. It applies 4×5 matrix on every pixel of the child’s screen area.

Instead of trying to explain how this works with words or maths, I have some examples that should make the principle clear:

Identity Filter

The easiest one is the identity which doesn’t change the content at all. I include it because it makes the principle easier to understand:

Radical different colour

This one modifies all components of the colours

Inverting

And finally the inverting filter

Sample App

To let you get some experience with matrix filters, I made a small sample App that lets you apply filters to your own images

The important parts of the code are where the filters are defined

Map<String, List<double>> predefinedFilters = { 'Identity': [ //R G B A Const 1, 0, 0, 0, 0, // 0, 1, 0, 0, 0, // 0, 0, 1, 0, 0, // 0, 0, 0, 1, 0, // ], 'Grey Scale': [ //R G B A Const 0.33, 0.59,0.11, 0,0,// 0.33,0.59,0.11, 0,0,// 0.33, 0.59,0.11, 0,0,// 0, 0, 0, 1, 0, // ], 'Invers': [ //R G B A Const -1, 0, 0, 0, 255, // 0, -1, 0, 0, 255, // 0, 0, -1, 0, 255, // 0, 0, 0, 1, 0, // ], 'Sepia': [ //R G B A Const 0.393, 0.769, 0.189, 0,0, // 0.349,0.686,0.168, 0,0, // 0.272,0.534,0.131,0,0, // 0, 0, 0, 1, 0, // ], };

The matrixes are defined as List<double> that is in row-major order which means the rows are concatenated to one large list.

Using the Filter is as easy as any other widget:

child: GestureDetector( onTap: pickImage, child: imageFile != null ? ColorFiltered( colorFilter: ColorFilter.matrix(matrixValues .map<double>((entry) => entry.value) .toList()), child: Image.file( imageFile, fit: BoxFit.cover, ), ) : Center(child: Text('Tap here to select image')), ),

As a side note, you can apply this filter to any type of child widget, not only to an Image .

The code of the demo app can be found here:

https://github.com/escamoteur/color_filtered_demo

Have fun with it. Just to mention I tried to make the layout responsive and not based on any fixed values.

Contact me: