none
Convert integer array into bitmap RRS feed

  • Question

  • I have a cam that is returning 10 bits  pixels.  I get an array that is double the size of the picture because it is using two 8 bit bytes to make one 10 bit integer.

    so one pixel = two bytes .

    So I have a working convert for that part. however, I need to display an array of integers in to a bitmap.

    how do I do that ?  

         
    Thursday, June 6, 2019 9:52 PM

All replies

  • Hello,

    A good start would be to show the code you currently have written.


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Friday, June 7, 2019 1:10 AM
    Moderator
  • here is my code:

    public  Bitmap InttoBitmap( int[] blob)
            {
                Bitmap bm = new Bitmap(keepWidth, keepHeight, System.Drawing.Imaging.PixelFormat.Format16bppRgb555);
    
    
                int i = 0;
                for (int x =0; x < keepWidth ; x++)
                {
                    for( int y =0; y < keepHeight; y++ )
                    {
                        Color color = new Color();
                        color = Color.FromArgb(blob[i]);
                        i++;
                        bm.SetPixel(x, y, color);
                    }
                   
                }
                return bm;
            }

    right now,

    I am just getting the color blue or black back.

    my camera is a mono one, so I should get black white to black 

    Monday, June 17, 2019 2:47 PM
  • also this code runs so slow
    Monday, June 17, 2019 2:48 PM
  • I responded to your other thread.  Doing a SetPixel one at a time is always going to be slow.  If you want it to be faster, you'll need to use Format.PixelFormat16bppGrayScale.  That means you'll have to create the array of pixels yourself, by scaling your 0..1023 values to 0..65535, and then using the final Bitmap constructor, which accepts a width, a height, a pixel format, and an array of bytes.  Sort of like this:

        public Bitmap InttoBitmap( int[] blob )
        {
    
            short[] pixels = new short[](blob.Length);
            for( int i = 0; i < keepWidth * keepHeight; i++ )
            {
                pixels[i] = blob[i] * 64;
            }
    
            IntPtr pixptr = Marshal.AllocHGlobal( keepWidth * keepHeight * 2 );
            Marshal.Copy( pixels, 0, pixptr, keepWidth * keepHeight );
            Bitmap bitmap = new Bitmap( keepWidth, keepHeight, 2 * keepWidth, Format.PixelFormat16bppGrayScale, pixptr );
        }
    
    This code has a problem, in that the memory assigned to the IntPtr will leak.  The Bitmap keeps the pointer throughout its like, so the block cannot be released until the Bitmap goes away.  If you need to do this multiple times, you will probably want to put the IntPtr into a class variable.



    Tim Roberts | Driver MVP Emeritus | Providenza &amp; Boekelheide, Inc.

    Monday, June 17, 2019 5:32 PM
  • Tim your code have some errors in it, I was able to fix most of them, but I am not sure about this one :

    pixels[i] = blob[i] * 64

    you cannot set a int to a short.

    did you mean to use short?

    Tuesday, June 18, 2019 5:58 PM
  • ok I just tried this :

            public Bitmap InttoBitmap(int[] blob)
            {
    
                int[] pixels = new int[blob.Length];
                for (int i = 0; i < keepWidth * keepHeight; i++)
                {
                    pixels[i] = blob[i] * 64;
                }
    
                IntPtr pixptr = Marshal.AllocHGlobal(keepWidth * keepHeight * 2);
                Marshal.Copy(pixels, 0, pixptr, keepWidth * keepHeight);
                Bitmap bitmap = new Bitmap(keepWidth, keepHeight, 2 * keepWidth, System.Drawing.Imaging.PixelFormat.Format16bppGrayScale, pixptr);
                return bitmap;
            }

    but I got an runtime error at 

        Marshal.Copy(pixels, 0, pixptr, keepWidth * keepHeight);

    it says :

    System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'

    Tuesday, June 18, 2019 6:00 PM
  • I also tried this, 

    but I am getting the same error :

    unsafe
                {
                    int[] pixels = new int[blob.Length];
                    for (int i = 0; i < keepWidth * keepHeight; i++)
                    {
                        pixels[i] = blob[i] * 64;
                    }
                    IntPtr pixptr = Marshal.AllocHGlobal(keepWidth * keepHeight * 2);
                    Marshal.Copy(pixels, 0, pixptr, keepWidth * keepHeight);
                    Bitmap bitmap = new Bitmap(keepWidth, keepHeight, 2 * keepWidth, System.Drawing.Imaging.PixelFormat.Format16bppGrayScale, pixptr);
    
                    return bitmap;
                }

    Tuesday, June 18, 2019 6:04 PM
  • Hi Btb4198,

    Thanks for the feedback.

    I think it is related to keepwidth and keepheight value, you could try to change their value to set break point to see what error is.

    Best Regards,

    Jack 


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, June 21, 2019 9:57 AM
    Moderator
  • I didn't actually compile it, since it was only a snippet.  The pixels array MUST be a short for a 16-bit bitmap.  You just have to cast the result to a short.  I'll try a live compile and let you know what I find.

    Tim Roberts | Driver MVP Emeritus | Providenza &amp; Boekelheide, Inc.

    Friday, June 21, 2019 7:45 PM
  • The pixels array has to be short!  In a 16-bit bitmap, each pixel is 16-bits, and the only type that is 16 bits wide is a short.  By making it "int", you're creating 32-bit pixels.  Nothing will line up.

    Unsafe is not required.  The following code works; I have compiled it and executed it, and it does create a bitmap.

        public Bitmap InttoBitmap( int[] blob )
        {
            short[] pixels = new short[blob.Length];
            for( int i = 0; i < keepWidth * keepHeight; i++ )
            {
                pixels[i] = (short)(blob[i] * 64);
            }
    
            IntPtr pixptr = Marshal.AllocHGlobal( keepWidth * keepHeight * 2 );
            Marshal.Copy( pixels, 0, pixptr, keepWidth * keepHeight );
            Bitmap bitmap = new Bitmap( keepWidth, keepHeight, 2 * keepWidth, PixelFormat.Format16bppGrayScale, pixptr );
            return bitmap;
        }
    
    Now, it turns out there's not an awful lot you can do with a 16bpp grayscale bitmap in Windows.  You can't even save it to disk.  What are you expecting to do with this data?  If you're going to be doing data analysis, then you can do it on the integer array that you started out with.  If you plan to save it to disk or display it to the screen, you'll need to convert it to some other format, and that means you're going to lose the bottom two bits.



    Tim Roberts | Driver MVP Emeritus | Providenza &amp; Boekelheide, Inc.

    Friday, June 21, 2019 8:04 PM
  • Tim,

    I need to display it to the use in a bitmap. I think it is so weird that you cannot display it or save.

    why do they even give it to us? 

    Wednesday, June 26, 2019 1:23 PM