Inverting image returns a black image

↘锁芯ラ 提交于 2019-12-17 21:08:33

问题


I want to invert an Image object. Currently my code looks like this:

    private Image Invert(Image img)
    {
        var bmpPicture = new Bitmap(img.Width, img.Height);
        var iaPicture = new ImageAttributes();
        var cmPicture = new ColorMatrix { Matrix00 = -1, Matrix11 = -1, Matrix22 = -1 };
        iaPicture.SetColorMatrix(cmPicture);
        var gfxPicture = Graphics.FromImage(img);
        var rctPicture = new Rectangle(0, 0, img.Width, img.Height);
        gfxPicture.DrawImage(img, rctPicture, 0, 0, img.Width, img.Height, GraphicsUnit.Pixel, iaPicture);
        return bmpPicture;
    }

However, when I run this, and show it in a PictureBox, the result is a black image. I'm running this in Visual Studio 2012 under Windows 8 Release preview. If there is a better way to do this, please let me know. Thanks.


回答1:


Try this: http://mariusbancila.ro/blog/2009/11/13/using-colormatrix-for-creating-negative-image/

public Bitmap Transform(Bitmap source)
{
    //create a blank bitmap the same size as original
    Bitmap newBitmap = new Bitmap(source.Width, source.Height);

    //get a graphics object from the new image
    Graphics g = Graphics.FromImage(newBitmap);

    // create the negative color matrix
    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[] {1, 1, 1, 0, 1}
    }); 

    // create some image attributes
    ImageAttributes attributes = new ImageAttributes();

    attributes.SetColorMatrix(colorMatrix);

    g.DrawImage(source, new Rectangle(0, 0, source.Width, source.Height),
                0, 0, source.Width, source.Height, GraphicsUnit.Pixel, attributes);

    //dispose the Graphics object
    g.Dispose();

    return newBitmap;
}



回答2:


Fast alternative to using a ColorMatrix for pixel manipulation:

public static void BitmapInvertColors(Bitmap bitmapImage)
{
    var bitmapRead   = bitmapImage.LockBits(new Rectangle(0, 0, bitmapImage.Width, bitmapImage.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppPArgb);
    var bitmapLength = bitmapRead.Stride * bitmapRead.Height;
    var bitmapBGRA   = new byte[bitmapLength];
    Marshal.Copy(bitmapRead.Scan0, bitmapBGRA, 0, bitmapLength);
    bitmapImage.UnlockBits(bitmapRead);

    for (int i = 0; i < bitmapLength; i += 4)
    {
        bitmapBGRA[i]     = (byte)(255 - bitmapBGRA[i]);
        bitmapBGRA[i + 1] = (byte)(255 - bitmapBGRA[i + 1]);
        bitmapBGRA[i + 2] = (byte)(255 - bitmapBGRA[i + 2]);
        //        [i + 3] = ALPHA.
    }

    var bitmapWrite = bitmapImage.LockBits(new Rectangle(0, 0, bitmapImage.Width, bitmapImage.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppPArgb);
    Marshal.Copy(bitmapBGRA, 0, bitmapWrite.Scan0, bitmapLength);
    bitmapImage.UnlockBits(bitmapWrite);
}



回答3:


By Inverting do you mean create a negative? if yes here is a snippet:

public void ApplyInvert()
{
    byte A, R, G, B;
    Color pixelColor;

    for (int y = 0; y < bitmapImage.Height; y++)
    {
        for (int x = 0; x < bitmapImage.Width; x++)
        {
            pixelColor = bitmapImage.GetPixel(x, y);
            A = pixelColor.A;
            R = (byte)(255 - pixelColor.R);
            G = (byte)(255 - pixelColor.G);
            B = (byte)(255 - pixelColor.B);
            bitmapImage.SetPixel(x, y, Color.FromArgb((int)A, (int)R, (int)G, (int)B));
        }
    }

}

from: http://www.smokycogs.com/blog/image-processing-in-c-sharp-inverting-an-image/

If you want read more about your problem and color matrix, please proceed with the following link: http://www.bobpowell.net/negativeimage.htm




回答4:


You aren't setting Matrix33 or Matrix44. My understanding is that Matrix33 would be the alpha component, so I suspect you're making your entire image transparent.

Try setting Matrix33 = 1.




回答5:


I used WPF and this library to create the Invert (negative) effect.




回答6:


VB version of Dan's Answer. It works like a charm !!

 Public Function Transform(source As Bitmap) As Bitmap
    'create a blank bitmap the same size as original
    Dim newBitmap As New Bitmap(source.Width, source.Height)

    'get a graphics object from the new image
    Dim g As Graphics = Graphics.FromImage(newBitmap)

    ' create the negative color matrix
    Dim colorMatrix As New ColorMatrix(New Single()() {New Single() {-1, 0, 0, 0, 0}, New Single() {0, -1, 0, 0, 0}, New Single() {0, 0, -1, 0, 0}, New Single() {0, 0, 0, 1, 0}, New Single() {1, 1, 1, 0, 1}})

    ' create some image attributes
    Dim attributes As New ImageAttributes()

    attributes.SetColorMatrix(colorMatrix)

    g.DrawImage(source, New Rectangle(0, 0, source.Width, source.Height), 0, 0, source.Width, source.Height, _
        GraphicsUnit.Pixel, attributes)

    'dispose the Graphics object
    g.Dispose()

    Return newBitmap
End Function



回答7:


I used "SIMD Supported Vectors" to make a code faster then pointers.Its under System.Numerics namespace.But before using these classes you need to get the update for System.Numerics from NuGet.Just search for System.Numerics.Anyways thats my class to invert the image

public class VBitmap : IDisposable
{        

    public short Width { get; private set; }
    public short Height { get; private set; }
    public int Stride { get; private set; }
    public int PixelLenght { get; private set; }
    public byte BytesperPixel { get; private set; }
    public PixelFormat PixelFormat { get; private set; }
    public byte[] Pixels { get; private set; }

    public VBitmap(string path)
    {
        using (Bitmap bmp = new Bitmap(path))
        {
            BitmapData bmpdata = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat);
            Width = checked((short)bmp.Width);
            Height = checked((short)bmp.Height);
            Stride = bmpdata.Stride;
            PixelLenght = Stride * Height;
            BytesperPixel = checked((byte)(Stride / Width));
            PixelLenght = (PixelLenght % 16) != 0 ? PixelLenght + (PixelLenght % 16) : PixelLenght;
            PixelFormat = bmp.PixelFormat;
            Pixels = new byte[PixelLenght];

            Marshal.Copy(bmpdata.Scan0, Pixels, 0, PixelLenght);
            bmp.UnlockBits(bmpdata);
        }
    }
    ~VBitmap()
    {
        Dispose();
    }

    public void InvertPixels()
    {
        byte[] resultarray = Pixels;
        unsafe
        {
            fixed (byte* result_ptr = resultarray)
            {
                for (int i = 0; i < PixelLenght; i += 16)
                    (~new Vector<byte>(Pixels, i)).CopyTo(resultarray, i);
            }
        }
    }

    public void InvertPixels(string name)
    {
        byte[] resultarray = Pixels;
        unsafe
        {
            fixed (byte* result_ptr = resultarray)
            {
                for (int i = 0; i < PixelLenght; i += 16)
                    (~new Vector<byte>(Pixels, i)).CopyTo(resultarray, i);
                SaveImage(name);
            }
        }
    }

    public unsafe void SaveImage(string name)
    {
        fixed (byte* p_ptr = Pixels)
        {
            using (Bitmap resultbmp = new Bitmap(Width, Height, Stride, PixelFormat, (IntPtr)p_ptr))
            {
                resultbmp.Save(name, ImageFormat.Jpeg);
            }
        }
    }

    public void Dispose()
    {
        Width = 0;
        Height = 0;
        Stride = 0;
        PixelLenght = 0;
        BytesperPixel = 0;
        Pixels = null;
        GC.Collect();
    }
}

Usage.Note:To get best performance from vectors you need to run your code on Release Mode:

static void Main(string[] args)
        {
            new VBitmap("testp.png").InvertPixels("qq.jpg");//Inverts the given bitmap and saves it.   
        }



回答8:


var gfxPicture = Graphics.FromImage(img); 

==>

var gfxPicture = Graphics.FromImage(bmpPicture); 

DrawImage could distort image, GetPixel is slow, Try WPF imaging API



来源:https://stackoverflow.com/questions/11779809/inverting-image-returns-a-black-image

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!