Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Safely create System.Drawing.Bitmap from managed int[]

Safely create System.Drawing.Bitmap from managed int[]

Scheduled Pinned Locked Moved C#
graphicsalgorithmshelptutorial
5 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • N Offline
    N Offline
    N O R B E R T
    wrote on last edited by
    #1

    I am searching for a few days now, but I didn't find any examples of creating a System.Drawing.Bitmap without using unsafe code. I've an int[] with one pixel in BGRA per int. The pixel values are created in my program, so I don't have any loadable bitmap so far. I tried to create a bitmap via new Bitmap(Int32 width, Int32 heigth, int32 stride, System.Drawing.Imaging.PixelFormat format, IntPtr scan0); but I didn't get the IntPtr to refer to the data correctly. If anyone has an idea how to correctly create that bitmap, I'd appreciate your help. thanks in advance, Norbert

    L 1 Reply Last reply
    0
    • N N O R B E R T

      I am searching for a few days now, but I didn't find any examples of creating a System.Drawing.Bitmap without using unsafe code. I've an int[] with one pixel in BGRA per int. The pixel values are created in my program, so I don't have any loadable bitmap so far. I tried to create a bitmap via new Bitmap(Int32 width, Int32 heigth, int32 stride, System.Drawing.Imaging.PixelFormat format, IntPtr scan0); but I didn't get the IntPtr to refer to the data correctly. If anyone has an idea how to correctly create that bitmap, I'd appreciate your help. thanks in advance, Norbert

      L Offline
      L Offline
      Luc Pattyn
      wrote on last edited by
      #2

      Hi, I have not done this for bitmaps yet, but passing a sound array to the unmanaged function PlaySound() requires a pointer to a data object (array) that can not be moved by the GC; see GCHandle and pinning in code snippet below.

      // play sound from a sound resource
      Stream stream=type.Assembly.GetManifestResourceStream(resourceName);
      int len=(int)stream.Length;
      byte\[\] buf=new byte\[len\];
      stream.Read(buf, 0, len);
      GCHandle handle=GCHandle.Alloc(buf);
      IntPtr ptr=Marshal.UnsafeAddrOfPinnedArrayElement(buf, 0);
      int res=sndPlaySound(ptr, 4);	// SND\_MEMORY
      handle.Free();
      

      I expect what you need is very similar to the above. Don't forget to free the handle when the pinning is no longer needed (otherwise the GC can not collect or even move it, possibly ending up in out-of-memory problems). :)

      Luc Pattyn

      N 1 Reply Last reply
      0
      • L Luc Pattyn

        Hi, I have not done this for bitmaps yet, but passing a sound array to the unmanaged function PlaySound() requires a pointer to a data object (array) that can not be moved by the GC; see GCHandle and pinning in code snippet below.

        // play sound from a sound resource
        Stream stream=type.Assembly.GetManifestResourceStream(resourceName);
        int len=(int)stream.Length;
        byte\[\] buf=new byte\[len\];
        stream.Read(buf, 0, len);
        GCHandle handle=GCHandle.Alloc(buf);
        IntPtr ptr=Marshal.UnsafeAddrOfPinnedArrayElement(buf, 0);
        int res=sndPlaySound(ptr, 4);	// SND\_MEMORY
        handle.Free();
        

        I expect what you need is very similar to the above. Don't forget to free the handle when the pinning is no longer needed (otherwise the GC can not collect or even move it, possibly ending up in out-of-memory problems). :)

        Luc Pattyn

        N Offline
        N Offline
        N O R B E R T
        wrote on last edited by
        #3

        Thanks for your reply. I'm getting a valid (non zero) IntPtr with your help, so I can create a new System.Drawing.Bitmap. The saved image is not what I did expect, but that's a problem with the PixelFormat. So thank you very much for your help. Norbert

        L 1 Reply Last reply
        0
        • N N O R B E R T

          Thanks for your reply. I'm getting a valid (non zero) IntPtr with your help, so I can create a new System.Drawing.Bitmap. The saved image is not what I did expect, but that's a problem with the PixelFormat. So thank you very much for your help. Norbert

          L Offline
          L Offline
          Luc Pattyn
          wrote on last edited by
          #4

          Hi Norbert, I've just found an article that may be relevant for you: http://www.codeproject.com/useritems/ImageConverter.asp[^] It seems to prove GCHandle is totally unnecessary for your needs ... Greetings,

          Luc Pattyn

          N 1 Reply Last reply
          0
          • L Luc Pattyn

            Hi Norbert, I've just found an article that may be relevant for you: http://www.codeproject.com/useritems/ImageConverter.asp[^] It seems to prove GCHandle is totally unnecessary for your needs ... Greetings,

            Luc Pattyn

            N Offline
            N Offline
            N O R B E R T
            wrote on last edited by
            #5

            No it wasn't. I knew that article, but I didn't get that code working. Also the ImageConverter which is mentioned in the articles message board didn't work for me. My code, as nasty as it is by now looks like this:using System.Runtime.InteropServices; using System.Drawing; ... public void saveImage(String filename) { List byteList = new List(); lock (this) { foreach (int color in m_data) { byteList.AddRange(System.BitConverter.GetBytes(color)); } } byte[] byteData = byteList.ToArray(); GCHandle handle = GCHandle.Alloc(byteData); ; try { IntPtr imgDataPtr = Marshal.UnsafeAddrOfPinnedArrayElement(byteData, 0); if(imgDataPtr != IntPtr.Zero) { Bitmap img = new Bitmap(this.Height, this.Width, byteData.Length, PixelFormat.Format32bppArgb, imgDataPtr); Random rnd = new Random(); img.Save(filename, System.Drawing.Imaging.ImageFormat.Tiff); } else { System.Diagnostics.Debugger.Break(); } } catch(Exception e) { System.Diagnostics.Debugger.Break(); } finally { handle.Free(); } }
            The creation of the Bitmap always threw ArgumentExceptions, when the PixelFormat is anything else than Format32bppArgb. It took me quite a time to figure out, that PixelFormat was the parameter which caused the problem, since I don't see any obvious differences between Format32bppArgb and Canonical which are both 32 Bits / pixel and should at maximum cause some mixed up channels when stated wrong. So maybe I'd get the Bitmap creation running with one of the linked examples above, if I check again for the correct PixelFormat, but by now I think I better use that maybe unnecessarily complicated version you helped me to figure out. If I get a shorter and less complicated version running, I'll post it here. Norbert

            1 Reply Last reply
            0
            Reply
            • Reply as topic
            Log in to reply
            • Oldest to Newest
            • Newest to Oldest
            • Most Votes


            • Login

            • Don't have an account? Register

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • World
            • Users
            • Groups