These look like good places to start.
DIBs and Their Uses
DIB to System.Bitmap - CodeProject
From the comments in the 2nd link:
DIB to System.Bitmap - CodeProject
|
|
Hello,
I'm developing a scanning application in VB.NET 2005 using TWAIN. The scanner returns to me a handle to a DIB. I need to save this to a file, but I've been searching everywhere and can't find any information.
Can anyone point me in the right direction? Thanks.
These look like good places to start.
DIBs and Their Uses
DIB to System.Bitmap - CodeProject
From the comments in the 2nd link:
DIB to System.Bitmap - CodeProject
Thanks Matt. Unfortunately I need VB help. I found the CodeProject reference you posted before I posted here. It is not VB code, so unless someone can translate or explain what it is doing...
Didn't think so.
Anyway I tried searching for a api that it uses but couldn't find anything. If anyone knows how to use GdipCreateBitmapFromGdiDib or can point me to a VB example then that may solve my problem.
The microsoft site Matt pointed me too has two more leads, but I can't find any information on them either. CreateDIBitmap or SetDIBits may also work if anyone can point me to any explanations on how to use them or VB examples.
Thanks.
Using: Convert C# to VB.NET - A free code conversion tool - developer Fusion - ASP.NET, C# Programming, VB.NET, .NET Framework, Java and Visual Basic Tutorials
I get:
This seems to compile fine on my system though I don't have anything to test it out on.Code:Imports System.Runtime.InteropServices Imports System.Reflection Imports System.Drawing Public Class Form1 <DllImport("GdiPlus.dll", CharSet:=CharSet.Unicode, ExactSpelling:=True)> _ Private Shared Function GdipCreateBitmapFromGdiDib(ByVal pBIH As IntPtr, ByVal pPix As IntPtr, ByRef pBitmap As IntPtr) As Integer End Function Public Shared Function BitmapFromDIB(ByVal pDIB As IntPtr, ByVal pPix As IntPtr) As Bitmap Dim mi As MethodInfo = GetType(Bitmap).GetMethod("FromGDIplus", BindingFlags.[Static] Or BindingFlags.NonPublic) If mi Is Nothing Then Return Nothing End If ' (permission problem) Dim pBmp As IntPtr = IntPtr.Zero Dim status As Integer = GdipCreateBitmapFromGdiDib(pDIB, pPix, pBmp) If (status = 0) AndAlso (pBmp <> IntPtr.Zero) Then ' success Return DirectCast(mi.Invoke(Nothing, New Object() {pBmp}), Bitmap) Else Return Nothing ' failure End If End Function End Class
It would be advisable to avoid the snarky comments especially when you're coming to a place for help.Didn't think so.
Here's the 2nd one converted:
Code:Imports System Imports System.IO Public Class BitmapFromDibStream Inherits Stream Private dib As Stream = Nothing Private header As Byte() = Nothing Public Sub New(ByVal dib As Stream) Me.dib = dib makeHeader() End Sub Private Sub makeHeader() Dim reader As New BinaryReader(dib) Dim headerSize As Integer = reader.ReadInt32() Dim pixelSize As Integer = CInt(dib.Length) - headerSize Dim fileSize As Integer = 14 + headerSize + pixelSize Dim bmp As New MemoryStream(14) Dim writer As New BinaryWriter(bmp) ' Get the palette size ' * The Palette size is stored as an int32 at offset 32 ' * Actually stored as number of colours, so multiply by 4 ' dib.Position = 32 Dim paletteSize As Integer = 4 * reader.ReadInt32() ' Get the palette size from the bbp if none was specified If paletteSize = 0 Then ' Get the bits per pixel ' * The bits per pixel is store as an int16 at offset 14 ' dib.Position = 14 Dim bpp As Integer = reader.ReadInt16() ' Only set the palette size if the bpp < 16 If bpp < 16 Then paletteSize = 4 * (2 << (bpp - 1)) End If End If ' 1. Write Bitmap File Header: writer.Write(CByte(AscW("B"c))) writer.Write(CByte(AscW("M"c))) writer.Write(fileSize) writer.Write(CInt(0)) writer.Write(14 + headerSize + paletteSize) header = bmp.GetBuffer() writer.Close() dib.Position = 0 End Sub Public Overloads Overrides Function Read(ByVal buffer As Byte(), ByVal offset As Integer, ByVal count As Integer) As Integer Dim dibCount As Integer = count Dim dibOffset As Integer = offset - 14 Dim result As Integer = 0 If _position < 14 Then Dim headerCount As Integer = Math.Min(count + CInt(_position), 14) Array.Copy(header, _position, buffer, offset, headerCount) dibCount -= headerCount _position += headerCount result = headerCount End If If _position >= 14 Then result += dib.Read(buffer, offset + result, dibCount) _position = 14 + dib.Position End If Return CInt(result) End Function Public Overrides ReadOnly Property CanRead As Boolean Get Return True End Get End Property Public Overrides ReadOnly Property CanSeek As Boolean Get Return False End Get End Property Public Overrides ReadOnly Property CanWrite As Boolean Get Return False End Get End Property Public Overrides Sub Flush() End Sub Public Overrides ReadOnly Property Length As Long Get Return 14 + dib.Length End Get End Property Private _position As Long = 0 Public Overrides Property Position As Long Get Return _position End Get Set(ByVal value As Long) _position = value If (_position > 14) Then dib.Position = _position - 14 End If End Set End Property Public Overrides Function Seek(ByVal offset As Long, ByVal origin As System.IO.SeekOrigin) As Long Throw New Exception("The method or operation is not implemented.") End Function Public Overrides Sub SetLength(ByVal value As Long) Throw New Exception("The method or operation is not implemented.") End Sub Public Overrides Sub Write(ByVal buffer() As Byte, ByVal offset As Integer, ByVal count As Integer) Throw New Exception("The method or operation is not implemented.") End Sub End Class
I apologize for that comment. You are correct Matt. I was wrong and a bit cranky, but anyway...
Thanks for that conversion and link. With that I was able to get it to work. That code used a pPix but didn't explain on how to get it. In the comments at the bottom was a link to a spanish site that led me to the line (and function)pPix = GetPixelInfo(pDIB) which works.
I have included the completed code that will convert either a handle or pointer of a DIB to a Bitmap or TIFF file.
Thanks again Matt.Code:Imports microsoft.VisualBasic Imports System.Drawing.Imaging Imports System.Runtime.InteropServices Imports System.Reflection 'DIB structure: '1) BITMAPINFOHEADER '2) ColorTable or Bitfields array, if any(i.e, predicated on bpp of image) '3) Bitmap's bits Module basGraphics Private Declare Function GdipCreateBitmapFromGdiDib Lib "GdiPlus.dll" ( _ ByVal pBIH As IntPtr, _ ByVal pPix As IntPtr, _ ByRef pBitmap As IntPtr) As Integer <StructLayout(LayoutKind.Sequential, Pack:=2)> Public Class BitmapInfoHeader '40 bytes Public biSize As Integer 'Size of the header structure to identify to the API which Bitmap header type we’re passing it. Public biWidth As Integer 'Width of the Bitmap we wish to create Public biHeight As Integer 'Height of the Bitmap we wish to create Public biPlanes As Short 'Colour planes of the Bitmap we wish to create (always 1) Public biBitCount As Short 'Colour depth of the Bitmap we wish to create Public biCompression As Integer 'Compression method used to store the Bitmap data Public biSizeImage As Integer 'Size (in bytes) of the image data Public biXPelsPerMeter As Integer 'Number of horizontal pixels per meter on the source device Public biYPelsPerMeter As Integer 'Number of vertical pixels per meter on the source device Public biClrUsed As Integer 'Number of colours used from palette Public biClrImportant As Integer 'Number of colours from palette that are absolutely required for proper display (seldom used any more) End Class Public Function BitmapFromDIB(ByVal hDIB As Integer) As Bitmap Dim pDIB As IntPtr 'Identify the memory pointer to the DIB Handler (hDIB) pDIB = New IntPtr(hDIB) Return BitmapFromDIB(pDIB) End Function Public Function BitmapFromDIB(ByVal pDIB As IntPtr) As Bitmap Dim intStatus As Integer Dim pBmp As IntPtr Dim pPix As IntPtr Dim mi As MethodInfo 'Call external GDI method mi = GetType(Bitmap).GetMethod("FromGDIplus", BindingFlags.[Static] Or BindingFlags.NonPublic) If mi Is Nothing Then Return Nothing End If 'Get pointer to bitmap header info pPix = GetPixelInfo(pDIB) 'Initialize memory pointer where Bitmap will be saved pBmp = IntPtr.Zero 'Call external methosd that saves bitmap into pointer intStatus = GdipCreateBitmapFromGdiDib(pDIB, pPix, pBmp) 'If success return bitmap, if failed return null If (intStatus = 0) AndAlso (pBmp <> IntPtr.Zero) Then Return DirectCast(mi.Invoke(Nothing, New Object() {pBmp}), Bitmap) Else Return Nothing End If End Function Public Sub SavehDibToTiff(ByVal hDIB As Integer, ByVal strFileName As String, ByVal intXRes As Integer, ByVal intTRes As Integer) Dim pDIB As IntPtr 'Identify the memory pointer to the DIB Handler (hDIB) pDIB = New IntPtr(hDIB) SavehDibToTiff(pDIB, strFileName, intXRes, intTRes) End Sub Public Sub SavehDibToTiff(ByVal pDIB As IntPtr, ByVal strFileName As String, ByVal intXRes As Integer, ByVal intTRes As Integer) Dim lngEV As Long Dim NewBitmap As Bitmap Dim ici As ImageCodecInfo 'Save the contents of DIB pointer into bitmap object NewBitmap = BitmapFromDIB(pDIB) 'Set resolution if needed If intXRes > 0 AndAlso intTRes > 0 Then NewBitmap.SetResolution(intXRes, intTRes) End If 'Create an instance of the windows TIFF encoder ici = GetEncoderInfo("image/tiff") 'Define encoder parameters Dim eps As New EncoderParameters(1) 'Only one parameter in this case (compression) 'Create an Encoder Value for TIFF compression Group 4 lngEV = CLng(EncoderValue.CompressionCCITT4) eps.Param(0) = New EncoderParameter(System.Drawing.Imaging.Encoder.Compression, lngEV) 'Save file NewBitmap.Save(strFileName, ici, eps) End Sub Private Function GetPixelInfo(ByVal pBMP As IntPtr) As IntPtr Dim p As Integer Dim bmi As BitmapInfoHeader Dim bmprect As Rectangle bmi = New BitmapInfoHeader() Marshal.PtrToStructure(pBMP, bmi) bmprect.X = bmprect.Y = 0 bmprect.Width = bmi.biWidth bmprect.Height = bmi.biHeight If (bmi.biSizeImage = 0) Then On Error Resume Next bmi.biSizeImage = Int((((bmi.biWidth * bmi.biBitCount) + 31) & Hex(Not (31))) / 2 ^ 3) * bmi.biHeight End If p = bmi.biClrUsed If ((p = 0) And (bmi.biBitCount <= 8)) Then p = Int(1 * 2 ^ bmi.biBitCount) End If p = (p * 4) + bmi.biSize + CType(pBMP.ToInt32, Integer) Return New IntPtr(p) End Function Private Function GetEncoderInfo(ByVal strMimeType As String) As ImageCodecInfo Dim r As Integer Dim encoders As ImageCodecInfo() encoders = ImageCodecInfo.GetImageEncoders() For r = 0 To encoders.Length - 1 If encoders(r).MimeType = strMimeType Then Return encoders(r) End If Next Return Nothing End Function End Module![]()
There are currently 1 users browsing this thread. (0 members and 1 guests)
Bookmarks