2

我想反转一个 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;
    }

但是,当我运行它并在 a 中显示它时PictureBox,结果是黑色图像。我在 Windows 8 Release preview 下的 Visual Studio 2012 中运行它。如果有更好的方法来做到这一点,请告诉我。谢谢。

4

7 回答 7

11

试试这个: 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;
}
于 2012-08-02T16:09:55.653 回答
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);
}
于 2014-06-23T23:41:59.767 回答
1

丹的答案的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
于 2015-10-19T23:41:55.720 回答
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/

如果您想了解更多关于您的问题和颜色矩阵的信息,请继续访问以下链接:https ://web.archive.org/web/20141230042200/http://bobpowell.net/negativeimage.aspx

于 2012-08-02T14:42:13.183 回答
0

你没有设置Matrix33Matrix44。我的理解是这Matrix33将是 alpha 组件,所以我怀疑你正在让你的整个图像透明。

尝试设置Matrix33 = 1

于 2012-08-02T14:44:23.900 回答
0

我使用“SIMD 支持的向量”使代码比指针更快。它在 System.Numerics 命名空间下。但在使用这些类之前,您需要从 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.   
        }
于 2017-06-09T23:04:36.020 回答
-1
var gfxPicture = Graphics.FromImage(img); 

==>

var gfxPicture = Graphics.FromImage(bmpPicture); 

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

于 2012-08-02T14:51:28.357 回答