I need to apply mask (3x3
) to image manually by iterating through it and calculating new values for each pixel. My code seems to work, but there is an issue - new value might not be between 0 and 255, it can be higher or lower. Such values are not acceptable. And now I don't know how to correctly solve it.
Apparently normalization to 0-255 will work, but here I need to normalize whole set of values which are known after loop is finished. This means I need to iterate through entire image twice.
You can also rate my code, maybe something can be improved, and maybe it actually doesn't work correctly despite compiling and creating processed images.
public Image<Rgba32> ApplyMask3x3(int[,] mask, Image<Rgba32> image)
{
Image<Rgba32> result = new Image<Rgba32>(image.Width, image.Height);
for(int row = 0; row < image.Height; row )
{
for(int col = 0; col < image.Width; col )
{
byte R = 0, G = 0, B = 0;
//temporary - forcefully throw new values to 0-255
int valR = ApplyMaskR3x3(col, row, image, mask); //code below
int valG = ApplyMaskG3x3(col, row, image, mask); //identical code as R but uses G attribute
int valB = ApplyMaskB3x3(col, row, image, mask); //identical code as R but uses B attribute
if (valR > 255) valR = 255;
if (valR < 0) valR = 0;
if (valG > 255) valG = 255;
if (valG < 0) valG = 0;
if (valB > 255) valB = 255;
if (valB < 0) valB = 0;
R = Convert.ToByte(valR);
G = Convert.ToByte(valG);
B = Convert.ToByte(valB); ;
result[col, row] = new Rgba32(R,G,B);
}
}
return result;
}
private int ApplyMaskR3x3(int col, int row, Image<Rgba32> image, int[,] mask)
{
int a, b, c;
int d, e, f;
int g, h, i;
if (col == 0 || row == 0)
a = 0;
else
a = image[col - 1, row - 1].R * mask[0, 0];
if (row == 0)
b = 0;
else
b = image[col, row - 1].R * mask[0, 1];
if (row == 0 || col == image.Width - 1)
c = 0;
else
c = image[col 1, row - 1].R * mask[0, 2];
if (col == 0)
d = 0;
else
d = image[col - 1, row].R * mask[1, 0];
e = image[col, row].R * mask[1, 1];
if (col == image.Width - 1)
f = 0;
else
f = image[col 1, row].R * mask[1, 2];
if (col == 0 || row == image.Height - 1)
g = 0;
else
g = image[col - 1, row 1].R * mask[2, 0];
if (row == image.Height - 1)
h = 0;
else
h = image[col, row 1].R * mask[2, 1];
if (col == image.Width - 1 || row == image.Height - 1)
i = 0;
else
i = image[col 1, row 1].R * mask[2, 2];
return a b c d e f g h i;
}
CodePudding user response:
You should be able to make use of the Filter
processor built in to ImageSharp
From your code sample you should be able to do this
public Image<Rgba32> ApplyMask3x3(int[,] mask, Image<Rgba32> image)
{
var matrix = new ColorMatrix(
mask[0,0],
mask[0,1],
mask[0,2],
mask[1,0],
mask[1,1],
mask[1,2],
mask[2,0],
mask[2,1],
mask[2,2]
);
image.Mutate(x=>x.Filter(matrix));
return image;
}
replace .Mutate()
with .Clone()
if you actually need a 2nd image and don't want to mutate in place.
If you Clone
you need to make sure that both source and output images are disposed of correctly otherwise you can end up causing memory issues.