【问题标题】:Inverting image returns a black image反转图像返回黑色图像
【发布时间】:2012-08-02 14:38:32
【问题描述】:

我想反转一个 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 preview 下的 Visual Studio 2012 中运行它。如果有更好的方法来做到这一点,请告诉我。谢谢。

【问题讨论】:

  • 您还需要设置 Matrix33 = 1 和 Matrix44 = 1 以保留这些项目的标识
  • 如果图像是 8bpp,你可以反转它的调色板。

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


【解决方案1】:

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

【讨论】:

  • 我复制粘贴了它。它创建了相同的黑色图像!
  • 您是向下滚动到实际解决方案,还是只是复制第一个看起来像代码的东西?
  • 反转图形颜色怎么样?比如,在 OnPaint 事件中反转图像。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    丹的答案的 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
    

    【讨论】:

      【解决方案4】:

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

      尝试设置Matrix33 = 1

      【讨论】:

        【解决方案5】:

        我使用“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.   
                }
        

        【讨论】:

          【解决方案6】:

          通过反转,您的意思是创建负数吗?如果是,这里是一个 sn-p:

          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

          【讨论】:

          • -1 表示通过每个像素的超慢迭代; +1 链接到鲍勃鲍威尔。
          • 如前所述,这是超级慢!还是谢谢
          • 这非常慢。详情:codeproject.com/Articles/406045/…
          【解决方案7】:
          var gfxPicture = Graphics.FromImage(img); 
          

          ==>

          var gfxPicture = Graphics.FromImage(bmpPicture); 
          

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

          【讨论】:

          • 我改变了它,但它没有帮助。你能发布一个WPF代码sn-p吗?谢谢。
          • 为了清楚起见,我正在尝试创建应用程序的倒置屏幕截图。
          猜你喜欢
          • 2014-04-27
          • 1970-01-01
          • 2011-08-08
          • 1970-01-01
          • 2019-07-13
          • 2016-11-06
          • 1970-01-01
          • 2015-09-12
          • 2019-06-21
          相关资源
          最近更新 更多