Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bitmap Creation Problems (Invalid Parameter) C#

Okay. Here is the source code:

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
    }
}
}

I am trying to procedurally generate a picture (call it abstract art), and write it to the disk. I don't really want help on the procedurally generated part. I want help getting my image to the disk.

The only thing that Visual Studio gives me is this:

System.ArgumentException: Parameter is not valid. at System.Drawing.Bitmap..ctor(Int32 width, Int32 height, Int32 stride, PixelFormat format, IntPtr scan0)

like image 889
UpTide Avatar asked Nov 21 '25 21:11

UpTide


1 Answers

Well, I started your code with 100x200 size. And sids 200-300. I didn't catch your error, but found another :

System.AccessViolationException: Attempted to read or write protected memory

To fix it I changed PixelFormat to Format32bppRgb:

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

It occured because some types of PixelFormat causes ArgumentException when passed to new Bitmap(). Here is list of these types:

  • Gdi
  • Alpha
  • PAlpha
  • Extended
  • Canonical
  • Undefined
  • DontCare
like image 128
Artem Kulikov Avatar answered Nov 23 '25 10:11

Artem Kulikov



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!