Reputation: 3
I'm working on a processing image software and now i want to change white balance and add some saturation on my photos, so i have to work with each pixel value. I've tried to transform my BitmapImage to WritableBitmap and then I've tried this code. But if i run it, my image turns to green. I want to take pixels from that image and then set them to new values. I've searched many solutions but found none, so maybe someone can help me with my code. Thanks.
public static WriteableBitmap Colors(Bitmap Image)
{
int width = Image.Width;
int height = Image.Width;
byte[,,] pixels = new byte[height, width, 4];
WriteableBitmap wbitmap = new WriteableBitmap(width, height, 96, 96, PixelFormats.Bgra32, null);
var target = new Bitmap(Image.Width, Image.Height);
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
pixels[i, j, 1] -= 30;
pixels[i, j, 3] -= 30;
}
}
byte[] pixels1d = new byte[height * width * 4];
int index = 0;
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++)
{
for (int i = 0; i < 4; i++)
pixels1d[index++] = pixels[row, col, i];
}
}
Int32Rect rect = new Int32Rect(0, 0, width, height);
int stride = 4 * width;
wbitmap.WritePixels(rect, pixels1d, stride, 0);
return wbitmap;
}
And then I'm running it like this:
private void run_OnClick(object sender, RoutedEventArgs e)
{
// Contrastt(BitmapImage2Bitmap(bitmap), 10);
// MedianFilter(BitmapImage2Bitmap(bitmap),5);
WriteableBitmap writeableBitmap = new WriteableBitmap(imageX);
BitmapImage colored = ConvertWriteableBitmapToBitmapImage(Colors((BitmapImage2Bitmap(bitmap))));
ImageBrush brush = new ImageBrush();
brush.ImageSource = imageX ;
CanvasProcessedImage.Background = brush;
}
Upvotes: 0
Views: 653
Reputation: 128136
Assuming that you already have a BitmapSource (or an instance of a derived class like BitmapImage) in a source
variable, you would first create a BitmapSource with a known pixel format, and then create a WritabelBitmap from that:
// source is a BitmapSource with whatever PixelFormat
var format = PixelFormats.Bgra32;
var temp = new FormatConvertedBitmap(source, format, null, 0); // force BGRA
var bitmap = new WriteableBitmap(temp);
Now you could either directly manipulate the data in the WriteableBitmap's BackBuffer
property, or first do it a bit simpler and create a copy of the buffer like this:
var width = bitmap.PixelWidth;
var height = bitmap.PixelHeight;
var stride = bitmap.BackBufferStride;
var buffer = new byte[stride * height];
bitmap.CopyPixels(buffer, stride, 0);
Then manipulate the buffer and write it back to the WriteableBitmap. Since you have specified the PixelFormat, you know which byte of each 4-byte pixel value is B, G, R and A respectively.
for (int i = 0; i < buffer.Length; i += 4)
{
// Blue
//buffer[i + 0] = ...
// Green
buffer[i + 1] = (byte)Math.Max(buffer[i + 1] - 30, 0);
// Red
buffer[i + 2] = (byte)Math.Max(buffer[i + 2] - 30, 0);
// Alpha
//buffer[i + 3] = ...
}
bitmap.WritePixels(new Int32Rect(0, 0, width, height), buffer, stride, 0);
When you have assigned the WriteableBitmap to the Source
property of an Image element, or the ImageSource
property of an ImageBrush, you can call WritePixels
later (and as often as necessary) without needing to reassign it it to the Source
/ImageSource
property. It is changed "in place".
Upvotes: 1