Skisharp ColorMatrix Invert black/white

858 Views Asked by At

I try to draw an image and after the first drawing i want invert the color of the drawing. If the background of my new square is black i need white and if it white i need black. In my example i draw 3 squares and make a offset of 10 pixel in the x.

Unfortunately, it does not produce the wanted result.

using var skBitmap = new SKBitmap(100, 40);
using var skCanvas = new SKCanvas(skBitmap);
skCanvas.Clear(SKColors.White);

var color = SKColors.Black;
float[] invertMatrix = {
    -1.0f,  0.0f,  0.0f,  0.0f,  255.0f,
    0.0f,  -1.0f,  0.0f,  0.0f,  255.0f,
    0.0f,  0.0f,  -1.0f,  0.0f,  255.0f,
    0.0f,  0.0f,  0.0f,  1.0f,  0.0f
};

using var skPaint = new SKPaint();
skPaint.Color = color;
skPaint.Style = SKPaintStyle.Fill;

skCanvas.DrawRect(10, 10, 20, 20, skPaint);

skPaint.ColorFilter = SKColorFilter.CreateColorMatrix(invertMatrix);

//move +10 in x
skCanvas.DrawRect(20, 10, 20, 20, skPaint);

//move +10 in x
skCanvas.DrawRect(30, 10, 20, 20, skPaint);

drawing

3

There are 3 best solutions below

0
Tino Hager On BEST ANSWER

I have found a solution for my problem unfortunately without a matrix.

using var skBitmap = new SKBitmap(100, 40);
using var skCanvas = new SKCanvas(skBitmap);
skCanvas.Clear(SKColors.White);

var color = SKColors.Black;

using var skPaint = new SKPaint();
skPaint.Color = color;
skPaint.Style = SKPaintStyle.Fill;

skCanvas.DrawRect(10, 10, 20, 20, skPaint);

DrawInvertRectangle(20, 10, 20, 20, skBitmap);
DrawInvertRectangle(30, 10, 20, 20, skBitmap);
private static void DrawInvertRectangle(int x, int y, int width, int height, SKBitmap skBitmap)
{
    using var skPaint = new SKPaint();
    skPaint.Color = SKColors.Black;
    skPaint.Style = SKPaintStyle.Fill;

    using var skBitmapInvert = new SKBitmap(skBitmap.Width, skBitmap.Height);
    using var skCanvas = new SKCanvas(skBitmapInvert);
    skCanvas.DrawRect(x, y, width, height, skPaint);

    for (var row = 0; row < skBitmapInvert.Height; row++)
    {
        for (var column = 0; column < skBitmapInvert.Width; column++)
        {
            var pixel = skBitmap.GetPixel(column, row);
            var pixelInvert = skBitmapInvert.GetPixel(column, row);
            if (pixelInvert.Alpha == 255 && pixelInvert.Blue == 0 && pixel.Blue == 255)
            {
                skBitmap.SetPixel(column, row, SKColors.Black);
            }
            if (pixelInvert.Alpha == 255 && pixelInvert.Blue == 0 && pixel.Blue == 0)
            {
                skBitmap.SetPixel(column, row, SKColors.White);
            }
        }
    }
}
1
Gregory William Bryant On

It looks like after making your second call to skCanvas.DrawRect you are not updating the colour.

Further, in your drawing 20 pixel wide rectangles, and overlapping them, as your only shifting your new rectangle 10 pixels to the right.

Following your wanted example, your need to make the 4th call to changing the colour back to black, then make a call to skCanvas.DrawRect(40, 10, 20, 20, skPaint).

Given that you are shifting your rectangles by 10 pixels and overlapping them, I suggest you update your calls to produce a thinner initial rectangle at 10 pixels wide.

0
Artfunkel On

The format of colour matrices changed slightly at some point. Inversion now looks like this:

var inverter = new float[20] {
    -1f,  0f,  0f, 0f, 1f,
    0f, -1f,  0f, 0f, 1f,
    0f,  0f, -1f, 0f, 1f,
    0f,  0f,  0f, 1f, 0f
};