none
How to display a 1024 int value as a color for a bitmap RRS feed

  • Question

  • I have an array of integers with values from 0-1024 that I can get from a mono camera. I need to turn this into a color to be used in a bitmap. how do I do this ?

       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 only seeing the color blue, and I am getting back the value 84. I have code to draw a box on my video and display the values in that box, and I am just seeing 84 back. not 1024

     
     public double[,] imageToByteArray(Bitmap _image)
            {
                Bitmap b = new Bitmap(_image);
    
                BitmapData bData = b.LockBits(new Rectangle(0, 0, _image.Width, _image.Height), ImageLockMode.ReadWrite, b.PixelFormat);
    
                /* GetBitsPerPixel just does a switch on the PixelFormat and returns the number */
                byte bitsPerPixel = GetBitsPerPixel(bData.PixelFormat);
    
                /*the size of the image in bytes */
                int size = bData.Stride * bData.Height;
    
                /*Allocate buffer for image*/
                byte[] data = new byte[size];
                double[,] returndata = new double[_image.Height, _image.Width];
                /*This overload copies data of /size/ into /data/ from location specified (/Scan0/)*/
                System.Runtime.InteropServices.Marshal.Copy(bData.Scan0, data, 0, size);
                int i = 0;
                for (int y = 0; y < _image.Height; y++)
                {
    
                    for (int x = 0; x < _image.Width; x++)
                    {
    
                        double magnitude = 1 / 3d * (data[i] + data[i + 1] + data[i + 2]);
    
                        returndata[y, x] = magnitude;
                        i += bitsPerPixel / 8;
                    }
                }
    
                return returndata;
    
            }

    Monday, June 17, 2019 3:38 PM

All replies

  • You have created a 16bpp RGB bitmap, which only allows for 32 shades of gray.  The pixel is divided into 5 bits red, 5 bits green, 5 bits blue.  For a first strike, try changing your bitmap to PixelFormat.Format16bppGrayScale.  When you do that, you can't use SetPixel any more, because a Color value is limited to 8 bits per component.  You'd have to create the bitmap bits yourself.  Be sure to copy your grayscale values by 64 to match the range of the pixels.

    Alternatively, you could use PixelFormat.Format24bppRgb.  Then, you could use the SetPixel loop:

        int i = 0;
        for (int x =0; x < keepWidth ; x++)
        {
            for( int y =0; y < keepHeight; y++ )
            {
                int gray = blob[i] / 4; // scale to 0..255
                Color color = new Color();
                color = Color.FromArgb(gray, gray, gray);
                i++;
                bm.SetPixel(x, y, color);
            }
        }

    It's certainly not necessary to use floating point to convert a 24-bit pixel to 8-bit.  You can do it in integer:

        int magnitude = (data[i] + data[i+1] + data[i+2]) / 3;

    However, your code ASSUMES there are 3 bytes per pixel.  If you are passing in the bitmap you created (Format16bppRgb555) that won't be true.  There are only 2 bytes per pixel, and the 3 components aren't on byte boundaries.  The bytes in memory are stored as:

        GGGRRRRR 0BBBBBGG    GGGRRRRR 0BBBBBGG

    so it takes shifting and masking to extract the RGB values.  A 24-bit bitmap is easier to handle.


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

    Monday, June 17, 2019 5:17 PM
  • Tim,

    your code did not work, it die on setpixel.

    which it funny because you said it would but you still put it in your code sample.

    so I can really confused 

    Monday, June 17, 2019 7:04 PM
  • also I did used PixelFormat.Format24bppRgb

    but  bm.SetPixel(x, y, color);

    did not work

    Monday, June 17, 2019 7:06 PM
  • also, is there a way to make it run faster ?

    right now 

    int i = 0;
        for (int x =0; x < keepWidth ; x++)
        {
            for( int y =0; y < keepHeight; y++ )
            {
                int gray = blob[i] / 4; // scale to 0..255
                Color color = new Color();
                color = Color.FromArgb(gray, gray, gray);
                i++;
                bm.SetPixel(x, y, color);
            }
        }

    take a very long time

    Monday, June 17, 2019 7:11 PM
  • Hi Btb4198,

    Thank you for posting here.

    For your last reply, you want to make the code run faster.

    I think it 's best for you to provide the value of keepWidth and keepHeight, which will make differences between my result and yours.

    The following is my test code and result.

    int keepWidth = 20;
    int keepHeight = 30;
     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++)
                    {
                        int gray = blob[i] / 4; // scale to 0..255
                        Color color = new Color();
                        color = Color.FromArgb(gray, gray, gray);
                        i++;
                        bm.SetPixel(x, y, color);
                    }
                }
                return bm;
            }
    
    
            private void Form1_Load(object sender, EventArgs e)
            {
                List<int> list = new List<int>();
                for (int i = 0; i < 1024; i++)
                {
                    list.Add(i);
                }
                int[] m = list.ToArray();
                Stopwatch stop = new Stopwatch();
                stop.Start();
                Bitmap b = InttoBitmap(m);
                stop.Stop();
                MessageBox.Show(stop.Elapsed.ToString()) ;
                pictureBox1.Image = b;
            }

    Result:

    As you see in the above picture, it will take a very short time.

    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.

    Tuesday, June 18, 2019 2:27 AM
    Moderator
  • What did it do?  There is no one on earth who can diagnose "did not work".  And I replied in another thread to say that a SetPixel loop will always be slow, suggesting a better plan by creating an array in memory first.

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

    Tuesday, June 18, 2019 6:37 AM