Когда я запускаю этот код
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: A generic error occurred in GDI+.`
Я почти уверен, что это не связано с правами доступа к файлам, когда я даю разрешение администратору программы и удаляю изображение, чтобы сбросить разрешения, которые оно все еще создает. Я могу подтвердить, что этот код, замененный на BitmapSetPixel() на RGB, работает.
Я подозреваю, что я испортил указатели, но я не совсем уверен. Кроме того, как ни странно, он создает пустые файлы png, даже если выдает.
Цель этого кода - сгенерировать треугольник Серпинского с использованием метода игры хаоса.





Ваша проблема - 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);
}
}
Результат
Вы можете переделать его постфактум, если хотите, добавьте перец и соль по вкусу.
Также, если вы избавитесь от всех точек и кешируете цвета, это будет немного быстрее
Лично я бы выбрал 8bpp. Тогда у вас есть действительно простой массив из одного байта на пиксель, и вы можете просто поместить туда значение «1» для белого. Просто нужно потом добавить два цвета в палитру.
Кстати, в коде X и Y поменялись местами ... это должно быть *(sc0 + tp.Y*width + tp.X) = white;
@Nyerguds спасибо за внимание, и я тоже согласен с вашим предыдущим комментарием
Фиксированная инициализация цвета