反转图像返回黑色图像

时间:2012-08-02 14:38:32

标签: c# .net image-processing gdi+

我想反转一个Image对象。目前我的代码如下所示:

    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;
    }

然而,当我运行它并在PictureBox中显示时,结果是黑色图像。我在Windows 8 Release预览版的Visual Studio 2012中运行它。如果有更好的方法,请告诉我。感谢。

8 个答案:

答案 0 :(得分:8)

试试这个: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;
}

答案 1 :(得分:3)

使用ColorMatrix进行像素操作的快速替代方法:

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);
}

答案 2 :(得分:0)

通过倒置你的意思是创造一个负面的?如果是,这里是一个片段:

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));
        }
    }

}

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

如果您想了解有关问题和颜色矩阵的更多信息,请继续以下链接:http://www.bobpowell.net/negativeimage.htm

答案 3 :(得分:0)

您没有设置Matrix33Matrix44。我的理解是Matrix33将是alpha组件,因此我怀疑你是在使整个图像透明。

尝试设置Matrix33 = 1

答案 4 :(得分:0)

我使用WPF和this library来创建反转(负面)效果。

答案 5 :(得分:0)

丹的答案的VB版本。它就像一个魅力!!

 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

答案 6 :(得分:0)

我使用“SIMD支持的向量”使代码比指针更快。它在System.Numerics namespace.But下使用这些类之前,你需要从NuGet获取System.Numerics的更新。只需搜索System.Numerics。无论如何,我的班级反转图像

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:要从向量中获得最佳性能,您需要在发布模式下运行代码:

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

答案 7 :(得分:-1)

var gfxPicture = Graphics.FromImage(img); 

==&GT;

var gfxPicture = Graphics.FromImage(bmpPicture); 

DrawImage可能会扭曲图像,GetPixel很慢,请尝试WPF成像API