Announcement

Collapse
No announcement yet.

Png and Tiff files

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Png and Tiff files

    I have been exploring adding Tiff and Png files to an image processing program that I have developed. I am particularly interested in 16 bpp grayscale and 48 bpp color versions. I decided to try GDI+ despite Jose Roca's caution that GDI+ did not handle these versions properly. I hoped that I might be able to just use GDI+ to load the file, and then grab the bytes in memory without doing any further processing in GDI+. What I found is that this approach worked fine for 8 bpp images, but not at all for 16 bpp grayscale or 48 bpp color. In the latter cases the image bytes seem to get rescaled to use only about 6 of the available 256 levels. The code follows, and what I would like to know is whether someone could suggest an alternative approach or work-around that might preserve the high dynamic range images?

    Ken German
    Code:
    '#####################
    Public Function Open_Tif_Png(imageData As String, Index As Integer) As Boolean
    
    Dim I As Long, J As Long, K As Long    'index variables
    Dim statusNow As GpStatus
    Dim gdipBeginInfo As GdiplusStartupInput
    Dim gdipToken As Long           'created at GDI+ start, used to close GDI+
    Dim bmpData As BitmapData       'data structure from GDI+ lock
    Dim ptrBmp As Long              'pointer from GDI+ file read
    Dim nuRect As RECTL             'rectangular picture structure of locked data
    Dim xWidth As Single            'image width in pixels
    Dim yHeight As Single           'image height in pixels
    
    Dim ptrBitmapData As Long       'pointer RECTL data
    Dim xStride As Long             'width*bytesperpixel padded/4 
    Dim pixFormat As Long           'return from GetPixelImageFormat
    Dim bytePerPixel As Long        'name says it all
    Dim byteArray() As Byte         'memory block for image data
    Dim datalength As Long          'ubound of byteArray
    '######################
    
    gdipBeginInfo.DebugEventCallback = 0
    gdipBeginInfo.GdiplusVersion = 1
    gdipBeginInfo.SuppressBackgroundThread = 0
    gdipBeginInfo.SuppressExternalCodecs = 0
    
        'Start GDI+
        statusNow = GdiplusStartup(gdipToken, gdipBeginInfo)
    
        'Load file
        statusNow = GdipCreateBitmapFromFile(StrPtr(imageData), ptrBmp)
    
        'Get width and height of image
        statusNow = GdipGetImageDimension(ptrBmp, xWidth, yHeight)
    
        'Set size of image data to be opened for read
        nuRect.Height = yHeight
        nuRect.left = 0
        nuRect.top = 0
        nuRect.Width = xWidth
    
       'get pixel format of opened image
        statusNow = GdipGetImagePixelFormat(ptrBmp, pixFormat)
        'lock bitmap data for reading
        statusNow = GdipBitmapLockBits(ptrBmp, nuRect, ImageLockModeRead, pixFormat, bmpData)
    
        xStride = Abs(bmpData.Stride)   'negative means inverted 
        ptrBitmapData = bmpData.Scan0Ptr
    
        Select Case pixFormat
            Case 137224             
                '%PixelFormat24bppRGB                   
                bytePerPixel = 3
            Case 198659             
                '%PixelFormat8bppIndexed    
                bytePerPixel = 1
            Case 2498570            
                '%PixelFormat32bppARGB      
                bytePerPixel = 4
            Case 1060876            
                '%PixelFormat48bppRGB       
                bytePerPixel = 6
            Case Else
                'Quit
                Screen.MousePointer = vbDefault
                MsgBox "Unrecognized pixel format!", vbOKOnly, "FILE READ ERROR"
                statusNow = GdipBitmapUnlockBits(ptrBmp, bmpData)
                statusNow = GdipDisposeImage(ptrBmp)
                statusNow = GdipDisposeImage(ptrBmp)
                Exit Function
            End Select
    
        datalength = xStride * yHeight - 1
        ReDim byteArray(datalength)
        CopyMemory byteArray(0), ptrBitmapData, datalength
    
    'following code creates an image from byteArray() and closes GDI+ functions neatly but has no impact on the stated problem
     
    '##########################################
    'The above code is actually the VB6 prototype and would be modified appropriatly before proceeding to the PB DLL
    Last edited by Gary Beene; 26 Jul 2014, 12:28 AM. Reason: Code: tags

  • #2
    Since nobody had a suggestion I'll close this thread with my own solution. The solution is to forget about GDI+ and switch to FreeImage. With the exception of FITS, FreeImage can handle almost every useful image format and pixel depth. The only disadvantages are that the DLL is larger than GDI+ and the documentation makes the Windows API look verbose by comparison. For the problem of reading 16 and 48 bpp formats into memory the following code is even simpler than the GDI+ version.
    Code:
    '-------------------------------------------------
    Public Function Open_Tif_Png(imageName As String, Index As Integer) As Boolean
    
    Dim xWidth As Single                    'image width in pixels
    Dim yHeight As Single                   'image height in pixels
    Dim ptrBitmapData As Long           'pointer to dib from FI Load
    Dim ptrDIB As Long                       'pointer to dib data
    Dim xStride As Long                      'width*bytesperpixel padded to mod 4
    Dim pixFormat As Long                  'return from GetPixelImageFormat
    Dim bytePerPixel As Long              'name says it all
    Dim byteArray() As Byte                 'memory block for receiving pixel stream
    Dim datalength As Long                 'ubound of byteArray
    Dim ext As String                            'file extension of imageName
    '######################
    
    ext = Right$(imageName, 3)
    
        'Start FreeImage.DLL
        Call FreeImage_Initialise(0)
    
        Select Case ext
            Case "tif", "TIF"
                ptrDIB = FreeImage_Load(FIF_TIFF, imageName)
            Case "png", "PNG"
                ptrDIB = FreeImage_Load(FIF_PNG, imageName)
    
            Case Else
                Screen.MousePointer = vbDefault
                MsgBox "Unrecognized file extension.", vbOKOnly, "READ ERROR"
                GoTo close1
        End Select
    
        If ptrDIB = 0 Then
            Screen.MousePointer = vbDefault
            MsgBox imageName & " failed to open.", vbOKOnly, "READ ERROR"
            Call FreeImage_DeInitialise
            Exit Function
        End If
    
        bytePerPixel = FreeImage_GetBPP(ptrDIB) \ 8
    
        'Get image size and dimension VB byteArray for memory copy
        xWidth = FreeImage_GetWidth(ptrDIB)
        yHeight = FreeImage_GetHeight(ptrDIB)
        xStride = FreeImage_GetPitch(ptrDIB)
    
        datalength = xStride * yHeight - 1
        ReDim byteArray(datalength)
    
        'Get data pointer and copy memory
        ptrBitmapData = FreeImage_GetBits(ptrDIB)
        CopyMemory byteArray(0), ptrBitmapData, datalength
    
    'at this point the image data is in byteArray and can be manipulated directly
    'or converted to a matrix for convolutions etc.
     
    'To avoid a memory leak FreeImage has to be deinitialised and the bitmap killed before the function concludes just as for GDI+
    Ken German
    Last edited by Gary Beene; 26 Jul 2014, 12:29 AM. Reason: Code: tags

    Comment

    Working...
    X