Your Ad Here

Posted By

jimfred on 07/02/10


Tagged

DIB SystemDrawingBitmap


Versions (?)

Who likes this?

2 people have marked this snippet as a favorite

Vordreller
Tyster


Convert a DIB* to a System.Drawing.Bitmap


 / Published in: C#
 

URL: http://www.eggheadcafe.com/forumarchives/NETFrameworkdrawing/Nov2005/post24263016.asp

Convert a DIB* to a System.Drawing.Bitmap

This is useful for scanner APIs that provide a DIB*. A dot.net app can more easily work with System.Drawing.Bitmap.

SetDIBitsToDevice... Bob Powell posted an approach here: http://www.eggheadcafe.com/forumarchives/NETFrameworkdrawing/Nov2005/post24263016.asp My code below is an implementation of his approach.

TwainGui ... I found code with namespace TwainGui and class DibToImage. It had 3 public static functions. WithStream worked and is shown below. Google for \"TwainGui.dibtoimage.withstream\" to find what I was looking at. I\'m using this for grayscale and 24-bit color bitmaps returned from a proprietary scanner API.

  1. public class DibToBitmap
  2. {
  3.  
  4. /// <summary>
  5. /// Convert DIB to Bitmap.
  6. /// </summary>
  7. /// <param name="dibPtrArg">Pointer to memory DIB, starting with BITMAPINFOHEADER.</param>
  8. /// <returns>A Bitmap</returns>
  9. public static Bitmap Convert(IntPtr dibPtrArg)
  10. {
  11. BITMAPINFOHEADER bmi;
  12. IntPtr pixptr;
  13.  
  14. GetPixelInfo(dibPtrArg, out pixptr, out bmi );
  15.  
  16. Bitmap bitMap = new Bitmap(bmi.biWidth, bmi.biHeight);
  17.  
  18. Graphics scannedImageGraphics = Graphics.FromImage(bitMap);
  19.  
  20. IntPtr hdc = scannedImageGraphics.GetHdc();
  21.  
  22. SetDIBitsToDevice(
  23. hdc,
  24. 0, // XDest
  25. 0, // YDest
  26. bmi.biWidth,
  27. bmi.biHeight,
  28. 0, // XSrc
  29. 0, // YSrc
  30. 0, // uStartScan
  31. bmi.biHeight, // cScanLines
  32. pixptr, // lpvBits
  33. dibPtrArg, // lpbmi
  34. 0); // 0 = literal RGB values rather than palette
  35.  
  36. scannedImageGraphics.ReleaseHdc(hdc);
  37.  
  38. const float inchPerMeter = 39.3700787F;
  39. bitMap.SetResolution(bmi.biXPelsPerMeter/inchPerMeter, bmi.biYPelsPerMeter/inchPerMeter);
  40.  
  41. // bitMap.Save(@"c:\0\2.bmp", ImageFormat.Bmp); // debug code
  42.  
  43. return bitMap;
  44. }
  45.  
  46.  
  47. static private void GetPixelInfo(IntPtr bmpptr, out IntPtr pix, out BITMAPINFOHEADER bmi)
  48. {
  49.  
  50. bmi = new BITMAPINFOHEADER();
  51. Marshal.PtrToStructure(bmpptr, bmi); // copy into struct.
  52.  
  53. if (bmi.biSizeImage == 0)
  54. {
  55. bmi.biSizeImage = ((((bmi.biWidth * bmi.biBitCount) + 31) & ~31) >> 3) * bmi.biHeight;
  56. }
  57.  
  58. int p = bmi.biClrUsed;
  59.  
  60. if ((p == 0) && (bmi.biBitCount <= 8))
  61. {
  62. p = 1 << bmi.biBitCount;
  63. }
  64.  
  65. pix = (IntPtr)((p * 4) + bmi.biSize + (int)bmpptr);
  66.  
  67. }
  68.  
  69. [StructLayout(LayoutKind.Sequential, Pack=2)]
  70. private class BITMAPINFOHEADER
  71. {
  72. public int biSize;
  73. public int biWidth;
  74. public int biHeight;
  75. public short biPlanes;
  76. public short biBitCount;
  77. public int biCompression;
  78. public int biSizeImage;
  79. public int biXPelsPerMeter;
  80. public int biYPelsPerMeter;
  81. public int biClrUsed;
  82. public int biClrImportant;
  83. }
  84.  
  85. [DllImport("gdi32.dll", ExactSpelling = true)]
  86. internal static extern int SetDIBitsToDevice(
  87. IntPtr hdc,
  88. int xdst,
  89. int ydst,
  90. int width,
  91. int height,
  92. int xsrc,
  93. int ysrc,
  94. int start,
  95. int lines,
  96. IntPtr bitsptr,
  97. IntPtr bmiptr,
  98. int color);
  99.  
  100. } // class DibToImage
  101.  
  102.  
  103.  
  104.  
  105. //////////////////////// Another approach....
  106.  
  107. [StructLayout(LayoutKind.Sequential, Pack=2)]
  108. private class BITMAPINFOHEADER
  109. {
  110. public int biSize;
  111. public int biWidth;
  112. public int biHeight;
  113. public short biPlanes;
  114. public short biBitCount;
  115. public int biCompression;
  116. public int biSizeImage;
  117. public int biXPelsPerMeter;
  118. public int biYPelsPerMeter;
  119. public int biClrUsed;
  120. public int biClrImportant;
  121. }
  122.  
  123. /// <summary>
  124. /// Get .NET 'Bitmap' object from memory DIB via stream constructor.
  125. /// This should work for most DIBs.
  126. /// </summary>
  127. /// <param name="dibPtr">Pointer to memory DIB, starting with BITMAPINFOHEADER.</param>
  128. public static Bitmap WithStream( IntPtr dibPtr )
  129. {
  130. BITMAPFILEHEADER fh = new BITMAPFILEHEADER();
  131. Type bmiTyp = typeof(BITMAPINFOHEADER);
  132. BITMAPINFOHEADER bmi = (BITMAPINFOHEADER) Marshal.PtrToStructure( dibPtr, bmiTyp );
  133. if( bmi.biSizeImage == 0 )
  134. bmi.biSizeImage = ((((bmi.biWidth * bmi.biBitCount) + 31) & ~31) >> 3) * Math.Abs( bmi.biHeight );
  135. if( (bmi.biClrUsed == 0) && (bmi.biBitCount < 16) )
  136. bmi.biClrUsed = 1 << bmi.biBitCount;
  137.  
  138. int fhSize = Marshal.SizeOf( typeof(BITMAPFILEHEADER) );
  139. int dibSize = bmi.biSize + (bmi.biClrUsed * 4) + bmi.biSizeImage; // info + rgb + pixels
  140.  
  141. fh.Type = new Char[] { 'B', 'M' }; // "BM"
  142. fh.Size = fhSize + dibSize; // final file size
  143. fh.OffBits = fhSize + bmi.biSize + (bmi.biClrUsed * 4); // offset to pixels
  144.  
  145. byte[] data = new byte[ fh.Size ]; // file-sized byte[]
  146. RawSerializeInto( fh, data ); // serialize BITMAPFILEHEADER into byte[]
  147. Marshal.Copy( dibPtr, data, fhSize, dibSize ); // mem-copy DIB into byte[]
  148.  
  149. MemoryStream stream = new MemoryStream( data ); // file-sized stream
  150. Bitmap tmp = new Bitmap( stream ); // 'tmp' is wired to stream (unfortunately)
  151. Bitmap result = new Bitmap( tmp ); // 'result' is a copy (stand-alone)
  152. tmp.Dispose(); tmp = null;
  153. stream.Close(); stream = null; data = null;
  154. return result;
  155. }

Report this snippet  

You need to login to post a comment.