+ Reply to Thread
Results 1 to 5 of 5

Thread: Getting a bitmap from a DIB handle

  1. #1
    MarMan is offline VB.NET Forum Newbie MarMan is on a distinguished programming path ahead
    .NET Framework
    .NET 2.0
    Join Date
    Jan 2010
    Posts
    17
    Reputation
    9

    Question Getting a bitmap from a DIB handle

    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.

  2. #2
    MattP is offline VB.NET Forum All-Mighty MattP has a reputation beyond repute MattP has a reputation beyond repute MattP has a reputation beyond repute MattP has a reputation beyond repute MattP has a reputation beyond repute MattP has a reputation beyond repute MattP has a reputation beyond repute MattP has a reputation beyond repute MattP has a reputation beyond repute MattP has a reputation beyond repute MattP has a reputation beyond repute
    .NET Framework
    .NET 4.0
    Join Date
    Feb 2008
    Location
    USA
    Posts
    1,016
    Reputation
    533

    Default

    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

  3. #3
    MarMan is offline VB.NET Forum Newbie MarMan is on a distinguished programming path ahead
    .NET Framework
    .NET 2.0
    Join Date
    Jan 2010
    Posts
    17
    Reputation
    9

    Default

    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.

  4. #4
    MattP is offline VB.NET Forum All-Mighty MattP has a reputation beyond repute MattP has a reputation beyond repute MattP has a reputation beyond repute MattP has a reputation beyond repute MattP has a reputation beyond repute MattP has a reputation beyond repute MattP has a reputation beyond repute MattP has a reputation beyond repute MattP has a reputation beyond repute MattP has a reputation beyond repute MattP has a reputation beyond repute
    .NET Framework
    .NET 4.0
    Join Date
    Feb 2008
    Location
    USA
    Posts
    1,016
    Reputation
    533

    Default

    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:

    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
    This seems to compile fine on my system though I don't have anything to test it out on.

    Didn't think so.
    It would be advisable to avoid the snarky comments especially when you're coming to a place for help.

    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

  5. #5
    MarMan is offline VB.NET Forum Newbie MarMan is on a distinguished programming path ahead
    .NET Framework
    .NET 2.0
    Join Date
    Jan 2010
    Posts
    17
    Reputation
    9

    Smile

    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.

    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
    Thanks again Matt.

+ Reply to Thread

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

     

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts