Во время сохранения растрового изображения произошла общая ошибка в GDI + - PullRequest
0 голосов
/ 20 октября 2018

Когда я запускаю этот код

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 + .`

Я почти уверен, что это не вызвано правами доступа к файлам, когда я даю разрешение администратора программы и удаляю изображение, чтобы сбросить разрешения, которые он все еще выдает.Я могу подтвердить, что этот код поменялся с BitmapSetPixel() на RGB работает.

Я подозреваю, что я испортил указатели, но я не совсем уверен.Кроме того, как ни странно, он создает пустые png-файлы, хотя и генерирует их.

Цель этого кода - создать треугольник Серпинского, используя метод игры в хаос.

1 Ответ

0 голосов
/ 20 октября 2018

Ваша проблема в 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

Вы можете преобразовать его по факту, если хотите, добавьте перец и соль по вкусу

Также, если вы избавитесь от всех точек и кешируете цвета, это будетнемного быстрее

...