位图创建问题 (无效参数) C#

3
好的。以下是源代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;

namespace PictureMaker
{
class Program
{
    static void Main()
    {
        int[] WorkingSet = new int[2] { 1, 1 }; //used for rng
        int[] Pixel = new int[3] { 0, 0, 0 }; // rgb value of pixel from rng
        byte[] Data; //raw data to be put into memory
        int Height; //height of final image
        int Width; //width of final image
        Bitmap Picture; //picture to save
        string Input; //input storage string
        int RandomNumber = 0; //inital random number
        byte[] MinorData; //temporary data storage

        Console.WriteLine("Seed 1 (100 to 999, whole numbers only):");
        Input = Console.ReadLine(); //gets input
        WorkingSet[0] = int.Parse(Input); //parses to variable
        Console.WriteLine("Seed 2 (100 to 999, whole numbers only):");
        Input = Console.ReadLine();
        WorkingSet[1] = int.Parse(Input);
        Console.WriteLine("Height (whole numbers only):");
        Input = Console.ReadLine();
        Height = int.Parse(Input);
        Console.WriteLine("Width (whole numbers only):");
        Input = Console.ReadLine();
        Width = int.Parse(Input);

        Data = new byte[Height * Width * 4]; //width times height times pixel byte depth makes total bytes required to store the image.

        for (int i = (Height * Width * 4) - 1; i >= 0; i = i - 4) //each loop makes a single pixel, so it creates 4 bytes. Starting with the last pixel and moving to the first pixel.
        {
            WorkingSet = GenerateRandomNumber(WorkingSet);
            RandomNumber = WorkingSet[1]; //uses the second (fresh) number from the working set to use in making the pixel.
            MinorData = GeneratePixel(RandomNumber); //assigns pixel data to the temporary storage

            Data[i] = (byte)0;  //alpha channel is always 0 (I hope)
            Data[i - 1] = MinorData[2];
            Data[i - 2] = MinorData[1]; //remember this is backwards. last pixel to first pixel.
            Data[i - 3] = MinorData[0];
        }

        IntPtr Pointer = System.Runtime.InteropServices.Marshal.AllocHGlobal((Height * Width) * 4); //?? assigns the proper number of bytes to be stored in memory at this location ?? no idea honestly
        for (int i = (Height * Width * 4) - 1; i >= 0; i = i - 1) //iderates through each byte in the data...
        {
            System.Runtime.InteropServices.Marshal.WriteByte(Pointer, i + 1, Data[i]); //... and writes them one at a time to the 'reserved memory'; also hopefully moves the writer to a 'fresh' memory byte each time. No idea.
        }

        try //put all this here because it was crashing.
        {
            Picture = new Bitmap(Width, Height, Width * 4, System.Drawing.Imaging.PixelFormat.Canonical, Pointer); //invalid parameter. 
            Picture.Save("MyPicture.bmp");
        }
        catch (ArgumentException s)
        {
            Console.WriteLine(s);
        }
        Console.ReadLine(); //keeps program from closing on completion.
    }

    static byte[] GeneratePixel(int RandomNumber)
    {
        //*28
        char[] CharArray; //for working with the number
        byte[] PixelData = new byte[3]; //for return
        CharArray = (RandomNumber.ToString().ToCharArray()); //converts number to string then breaks down to chars
        PixelData[0] = (byte)(int.Parse(CharArray[0].ToString())*28); //converts chars to string to number and multiplies by 28 then converts the 255 RGB int to a byte
        PixelData[1] = (byte)(int.Parse(CharArray[1].ToString())*28);
        PixelData[2] = (byte)(int.Parse(CharArray[2].ToString())*28);
        return PixelData;
    }

    static int[] GenerateRandomNumber(int[] WorkingSet)
    {
        int[] RandomNumber = new int[2]; //for return
        string RandomString; //for working
        RandomNumber[0] = WorkingSet[1]; //makes 2nd working set number the first
        RandomString = (WorkingSet[0] + WorkingSet[1]).ToString(); //generates next number
        RandomNumber[1] = int.Parse(RandomString.Substring(RandomString.Length - 3)); //gets last 3 numbers and assigns it to 2nd slot
        return RandomNumber; //returns as the new working set
    }
}
}

我正在尝试通过程序生成一张图片(称之为抽象艺术),并将其写入磁盘。我不需要有关程序生成部分的帮助,我需要的是将我的图像写入磁盘的帮助。
Visual Studio 给出的唯一信息如下:
System.ArgumentException: Parameter is not valid. at System.Drawing.Bitmap..ctor(Int32 width, Int32 height, Int32 stride, PixelFormat format, IntPtr scan0)

你给的宽度和高度是多少? - CharithJ
我尝试过1x1和4x4两种方式。 - UpTide
2个回答

1
可能您的宽度和高度太大了。尝试使用较小的宽度和高度(600x800)并查看。 .NET 可能会拒绝创建一张同时使用那么多连续内存的图像。

我曾经输入的最大高度/宽度是4。 - UpTide
@UpTide:尝试使用实际值600x800。 - CharithJ
它会导致vhost.exe崩溃,但我不知道是什么原因。有什么我忽略的东西可以帮助我调试吗? - UpTide
我已经追踪到了2125像素或8500字节的数据。一旦我尝试将位图设置为超过此值的单个像素,程序就会崩溃。我的代码中是否有明显的硬限制?编辑:数组可以有多少个条目? - UpTide

1

好的,我开始用100x200的大小和sids 200-300运行你的代码。我没有捕捉到你的错误,但发现了另一个:

System.AccessViolationException:试图读取或写入受保护的内存

为了解决这个问题,我将PixelFormat更改为Format32bppRgb

 Picture = new Bitmap(Width, Height, Width * 4, System.Drawing.Imaging.PixelFormat.Format32bppRgb, Pointer); //invalid parameter. 

这是由于某些类型的PixelFormat在传递给新的Bitmap()时会引发ArgumentException。以下是这些类型的列表:

  • Gdi
  • Alpha
  • PAlpha
  • Extended
  • Canonical
  • Undefined
  • DontCare

我还没有检查过那么大的尺寸,因为我的米老鼠数字解析器无法处理低于100的随机数。(这可能是由于我生成数字的方式。) - UpTide
使用您的尺寸(例如4x4),它也可以正常工作。请检查一下。 - Artem Kulikov
更改像素格式解决了问题。我会继续改进我的“方法”来解析数字,但我仍然困惑为什么我的像素格式会导致问题。 - UpTide
由于某些类型的PixelFormat会导致此错误。我在我的答案中添加了这些类型的列表。 - Artem Kulikov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接