Effective way of making negative of image without external dlls

前端 未结 2 643
误落风尘
误落风尘 2021-01-03 05:38

That is the solution to make a negative from a image in C# Windows Forms without any dlls and in a effective, fast way?

相关标签:
2条回答
  • 2021-01-03 05:56

    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);
               }
        }
    
    0 讨论(0)
  • 2021-01-03 06:00

    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);
            }
        }
    
    0 讨论(0)
提交回复
热议问题