保存位图期间在GDI +中发生一般错误

时间:2018-10-19 22:57:18

标签: c# .net pointers bitmap gdi+

当我运行这段代码

Bitmap im = new Bitmap(600, 600, PixelFormat.Format16bppGrayScale);
int height = im.Height;
int width = im.Width;
Point p1 = new Point(0, 0);
Point p2 = new Point(im.Size.Width, 0);
Point p3 = new Point(im.Width / 2, im.Height);
Random r = new Random();
Point p = new Point(r.Next(0, im.Size.Width), r.Next(0, im.Size.Height));
BitmapData data = im.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format16bppGrayScale);
const int stride = 2;
int wsrtide = data.Stride;
unsafe
{
   IntPtr osc0 = data.Scan0;
   ushort* sc0 = (ushort*)data.Scan0;
   for (int y = 0; y < height; y++)
   {
      for (int x = 0; x < width; x++)
      {
         *sc0 = 0;
         sc0 += 1;
      }
   }
   for (long i = 0; i < width * height; i++)
   {
      if (i % 1_000_000 == 0)
      {
         Console.WriteLine(i);
      }
      var ran = r.Next(0, 3);
      Point tp;
      switch (ran)
      {
         case 0:
            tp = new Point((p1.X + p.X) / 2, (p1.Y + p.Y) / 2);
            sc0 = (ushort*)((int)osc0 + (wsrtide * tp.Y + (tp.X * stride)));
            *sc0 = ushort.MaxValue;
            p = tp;
            break;
         case 1:
            tp = new Point((p2.X + p.X) / 2, (p2.Y + p.Y) / 2);
            sc0 = (ushort*)((int)osc0 + (wsrtide * tp.Y + (tp.X * stride)));
            *sc0 = ushort.MaxValue;
            p = tp;
            break;
         case 2:
            tp = new Point((p3.X + p.X) / 2, (p3.Y + p.Y) / 2);
            sc0 = (ushort*)((int)osc0 + (wsrtide * tp.Y + (tp.X * stride)));
            *sc0 = ushort.MaxValue;
            p = tp;
            break;
      }
   }
   im.UnlockBits(data);
   im.Save(Environment.CurrentDirectory + "\\img.png");
   im.Dispose();

它会抛出我保存位图的位置

  

System.Runtime.InteropServices.ExternalException:一般错误   发生在GDI +中。

我几乎可以肯定这不是由文件权限引起的,当我授予程序admin权限并删除映像以重置它仍然会抛出的权限时。我可以确认此代码在RGB上与BitmapSetPixel()互换了。

我的怀疑是我弄乱了指针,但是我不确定。而且,很奇怪的是,即使抛出该文件,它也会生成空白的png文件。

此代码的目的是使用混沌游戏方法生成Sierpinski三角形。

1 个答案:

答案 0 :(得分:1)

您的问题是Format16bppGrayScale,我认为GDI不太支持它。

基本上,如果您只是在Format16bppGrayScale中创建位图,然后再将其保存,则仍然会显示错误。

我已自由地重写了您的方法Format32bppPArgb

private unsafe static void Main(string[] args)
{
   var height = 600;
   var width = 600;
   var p1 = new Point(0, 0);
   var p2 = new Point(width, 0);
   var p3 = new Point(width / 2, height);
   var r = new Random();
   var p = new Point(r.Next(0, width), r.Next(0, width));

   using (var im = new Bitmap(width, height, PixelFormat.Format32bppPArgb))
   {

      var data = im.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format32bppPArgb);
      var sc0 = (int*)data.Scan0;
      var pLen = sc0 + height * width;

      var black = Color.Black.ToArgb();
      var white = Color.White.ToArgb();

      for (var pI = sc0; pI < pLen; pI++)
         *pI = black;

      for (long i = 0; i < width * height; i++)
      {
         Point tp;
         switch (r.Next(0, 3))
         {
            case 0:
               tp = new Point((p1.X + p.X) / 2, (p1.Y + p.Y) / 2);
               *(sc0 + tp.Y + tp.X * width) = white;
               p = tp;
               break;
            case 1:
               tp = new Point((p2.X + p.X) / 2, (p2.Y + p.Y) / 2);
               *(sc0 + tp.Y + tp.X * width) = white;
               p = tp;
               break;
            case 2:
               tp = new Point((p3.X + p.X) / 2, (p3.Y + p.Y) / 2);
               *(sc0 + tp.Y + tp.X * width) = white;
               p = tp;
               break;
         }
      }
      im.UnlockBits(data);
      im.Save(@"D:\img.png", ImageFormat.Png);
   }
}

结果

enter image description here

您可以根据需要将其转换为事实,添加胡椒粉和盐调味

此外,如果您摆脱了所有的点并缓存了颜色,则速度会更快