That is the solution to make a negative from a image in C# Windows Forms without any dlls and in a effective, fast way?
Effective way of making negative of image without external dlls
The best way to do this is directly accessing the pixels with bitmap data.
Just to add some timing details:
Performing Negate on an 8 Megapixel Image (on a 2.4 Ghz Core 2 Duo):
- SetPixel (~22 seconds) - 220 Times slower
- Color Matrix, Matajon's method below (~750 milliseconds) - 7 times slower
- Directly accesing the bitmap data (~100 milliseconds) - Fastest
So, if you can't have unsafe code, then Color Matrix is much better than SetPixel.
public static void Negate(Bitmap image)
{
const int RED_PIXEL = 2;
const int GREEN_PIXEL = 1;
const int BLUE_PIXEL = 0;
BitmapData bmData = currentImage.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, image.PixelFormat);
try
{
int stride = bmData.Stride;
int bytesPerPixel = (currentImage.PixelFormat == PixelFormat.Format24bppRgb ? 3 : 4);
unsafe
{
byte* pixel = (byte*)(void*)bmData.Scan0;
int yMax = image.Height;
int xMax = image.Width;
for (int y = 0; y < yMax; y++)
{
int yPos = y * stride;
for (int x = areaSize.X; x < xMax; x++)
{
int pos = yPos + (x * bytesPerPixel);
pixel[pos + RED_PIXEL] = (byte)(255 - pixel[pos + RED_PIXEL]);
pixel[pos + GREEN_PIXEL] = (byte)(255 - pixel[pos + GREEN_PIXEL]);
pixel[pos + BLUE_PIXEL] = (byte)(255 - pixel[pos + BLUE_PIXEL]);
}
}
}
}
finally
{
image.UnlockBits(bmData);
}
}
If you are interested, here is the code for Color Matrix:
public static void Negate(Bitmap image)
{
Bitmap clone = (Bitmap) image.Clone();
using (Graphics g = Graphics.FromImage(image))
{
// negation ColorMatrix
ColorMatrix colorMatrix = new ColorMatrix(
new float[][]
{
new float[] {-1, 0, 0, 0, 0},
new float[] {0, -1, 0, 0, 0},
new float[] {0, 0, -1, 0, 0},
new float[] {0, 0, 0, 1, 0},
new float[] {0, 0, 0, 0, 1}
});
ImageAttributes attributes = new ImageAttributes();
attributes.SetColorMatrix(colorMatrix);
g.DrawImage(clone, new Rectangle(0, 0, clone.Width, clone.Height),
0, 0, clone.Width, clone.Height, GraphicsUnit.Pixel, attributes);
}
}
improvement: put the ode after the LockBits in a try block and the UnlockBits in a finally block. –
Dragone
One addition I'd add. In my C++ code, I use Bitmap::ApplyEffect() and the matrix shown here produces a black image since negative colors get clamped to zero. The proper matrix for me is: {{-1,0,0,0,0},{0,-1,0,0,0},{0,0,-1,0,0},{0,0,0,1,0},{1,1,1,0,1}} –
Kal
Go through all the pixels one by one (Bitmap.GetPixel() or something) and subtract the RGB values from 0xff to create a pixel of negative color. Save this pixel to a new image or onto the same image using (Bitmap.SetPixel()) at the same position.
// Retrieve the image.
var image1 = new Bitmap(@"C:\Documents and Settings\All Users\"
+ @"Documents\My Music\music.bmp", true);
int x, y;
// Loop through the images pixels to reset color.
for(x=0; x<image1.Width; x++)
{
for(y=0; y<image1.Height; y++)
{
Color pixelColor = image1.GetPixel(x, y);
Color newColor = Color.FromArgb(0xff - pixelColor.R
, 0xff - pixelColor.G, 0xff - pixelColor.B);
image1.SetPixel(x, y, newColor);
}
}
I would recommend to mark Kris Erickson approach as the final answers. its a lot faster! –
Dragone
© 2022 - 2024 — McMap. All rights reserved.