1

I am trying to figure out how to use an USB Video Camera API which is somewhat not very clear (at least it seems to count on previous knowledge from the developer, and I don't think I understood the "whole picture", pun intended).

I have the following event handler which is successfully receiving data, which I can only print to console at the moment:

    void  _camera_OnPreviewBitmap(IntPtr pbyteBitmap, uint dwBufferSize,
                                  uint dwWidth, uint dwHeight,
                                  uint dwFrameNo, uint dwPreviewPixelFormat) {

        Console.WriteLine(string.Format("{0}, {1}, {2}, {3}, {4}, {5}", pbyteBitmap, dwBufferSize, dwWidth, dwHeight, dwFrameNo, dwPreviewPixelFormat));

        //The callback function gets the image data as “IntPtr” type. 
        //When using “System.Runtime.InteropServices.Marshal.Copy”, the image data can copy to the array. 
        //When using “System.Runtime.InteropServices.Marchal.ReadByte”, the image data can get thedirectory. 
        //Sometimes the process speed is fast when receiving the image data after the image data copy to the array with 
        //“System.Runtime.InteropServices.Marchal.Copy”. 

    } 

This gives me these results:

259129344, 1228800, 1280, 960, 195051, 1
250281984, 1228800, 1280, 960, 195052, 1
259129344, 1228800, 1280, 960, 195053, 1
250281984, 1228800, 1280, 960, 195054, 1
259129344, 1228800, 1280, 960, 195055, 1
250281984, 1228800, 1280, 960, 195056, 1
259129344, 1228800, 1280, 960, 195057, 1
250281984, 1228800, 1280, 960, 195058, 1
259129344, 1228800, 1280, 960, 195059, 1
250281984, 1228800, 1280, 960, 195060, 1
259129344, 1228800, 1280, 960, 195061, 1
250281984, 1228800, 1280, 960, 195062, 1

So, this is consistent with image dimensions (1280 x 960), and 1228800 is the pixel count (buffer size), and the 1 for pixel format means PIXEL_FORMAT_08_MONO_OR_RAW as per the camera API pixel format enum (which is also consistent with this BW camera).

My question is:

How can I take this information and create a System.Drawing.Bitmap object with it?

I have already tried this, without success (apparently the grayscale image is not actually indexed...):

        var bmp = new System.Drawing.Bitmap((int)dwWidth, (int)dwHeight, (int)dwBufferSize,
                                            PixelFormat.Format8bppIndexed, pbyteBitmap);

This eventually produces "Generic GDI+ error".

heltonbiker
  • 26,657
  • 28
  • 137
  • 252
  • possible duplicate of [How do you convert a byte array to a Bitmap instance (.NET)?](http://stackoverflow.com/questions/10213854/how-do-you-convert-a-byte-array-to-a-bitmap-instance-net) – Steve Jun 25 '14 at 21:43
  • Also maybe look at this: http://www.ridgesolutions.ie/index.php/2013/02/13/c-save-grayscale-bytearray-image-byte-as-bitmap-file-bmp-example/ – Steve Jun 25 '14 at 21:44
  • 1
    @Steve if I'm not mistaken, the linked question does not apply, since I have an IntPtr as input, and not a byte array. One thing in common is that both of us are dealing with camera APIs, but I don't think the questions are real duplicates. – heltonbiker Jun 26 '14 at 12:58

1 Answers1

2

You are specifying an indexed format without giving a color palette to it.

If the image is grayscale, instead of using directly the pointer you can create your bitmap with 32bpp, lock bits and then set the RGB byte values to the pixel byte data, here is an example (using unsafe code for ease and speed):

Bitmap bmp = new Bitmap(1280, 960, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
var data = bmp.LockBits(new Rectangle(0, 0, 1280, 960), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb);

byte* srcBmpData = (byte*)pbyteBitmap.ToPointer();
byte* dstBmpData = (byte*)data.Scan0.ToPointer();

for (int buc = 0; buc < 1280 * 960; buc++)
{
    int currentDestPos = buc * 4;
    dstBmpData[currentDestPos] = dstBmpData[currentDestPos + 1] = dstBmpData[currentDestPos + 2] = srcBmpData[buc];
}

bmp.UnlockBits(data);
Bridge
  • 29,818
  • 9
  • 60
  • 82
Gusman
  • 14,905
  • 2
  • 34
  • 50
  • Of course, just add it to the declaration of your function (unsafe void...), and in the properties of your project, under build options check "Allow unsafe code", with that you can use pointers like in traditional c. – Gusman Jun 25 '14 at 21:57
  • One more question: I got the image "tiled" four times in a row. This seem to be a "stride" problem or such. Do you have any suggestion to fix it? – heltonbiker Jun 25 '14 at 21:59
  • Ehm, four times? can you upload the image to somewhere so I can see it? If there were a Stride problem the image should be very distorted (each line displaced X pixels) not "tiled". – Gusman Jun 25 '14 at 22:01
  • Got it. You never used `currentDestPos`. I'm gonna correct it if you don't mind. – heltonbiker Jun 25 '14 at 22:12