Win7 performance of "new bitmap(filename)"?

JesperSP

Member
Joined
Jun 22, 2011
Messages
6
Location
Maaloev, Denmark
Programming Experience
3-5
Dear all,

I have written a VB.net forms program that analyzes a lot of (~1400) jpg images from automated lab-equipment. I am in the process of migrating from WinXP to Win7 and to my surprise I noticed that analysis was 5 times slower under win7 compared to win XP (!?!?!). I investigated further and found that the loading of the jpg images was the step that was takning longer! The simple code below gives me 70 images per second under XP, but only 12 images per second under win7. Has anyone else noticed this performance drop, and can something be done to improve it ?

Cheers,
Jesper

VB.NET:
Public Class Form1


    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        If FolderBrowserDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
            Dim starttime As DateTime = Now
            Dim counter As Integer = 0
            For Each filename As String In My.Computer.FileSystem.GetFiles(FolderBrowserDialog1.SelectedPath)
                If filename.EndsWith(".jpg") Then
                    Dim bm As New Bitmap(filename, False)
                    ' do something with bitmap
                    '  PictureBox1.Image = bm
                    bm.Dispose()
                    counter += 1
                    Dim seconds As Double = (Now - starttime).TotalSeconds
                    If seconds > 0 Then Label1.Text = counter / seconds & " images per second."
                    Application.DoEvents()
                End If
            Next


        End If
    End Sub
End Class
 
First things first, that code should not be in your Button's Click event handler. That should pretty much all be done on a secondary thread.

As for the question, I'm not aware of any specific reason that that should be the case. What you might be able to do to make it a moot point is use two background threads: one to load the Images and one to process them.
 
First things first, that code should not be in your Button's Click event handler. That should pretty much all be done on a secondary thread.

As for the question, I'm not aware of any specific reason that that should be the case. What you might be able to do to make it a moot point is use two background threads: one to load the Images and one to process them.

Thanks for your reply. In the interest of clarity I have isolated the step that causes the issue in the code example provided. In my real code the loop runs in 4 threads (one for each hyperthread/core), which speeds up loading of the images - while one thread loads an image the other thread copies the interesting regions from the images. This multithreading really speeds up the execution - but for some reason the bottleneck appears to be the loading of the images right now. I would love to be able to just load the 8-bit grayscale jpg images directly into an array of bytes containing the gray-values of the pixels from which I then can copy the values using System.Runtime.InteropServices.Marshal.Copy - this woud make my life a lot simpler.

Cheers,
Jesper
 
5x Performance increase using FreeImage.dll


The following code takes 15502 ms to run (~64.5 images/s) on my Win7 machine (Core2Duo 2GHz). In contrast, using the old "New Bitmap(filename)" method it takes 68023ms (~14.7 images/s)!
There is also a speed increase on the XP machine (I5 M540) which goes from 66 to 88 images/s. The only issue is that the application goes from 500kb to 3MB, because the DLL takes 2.5MB.

Can anyone help me get the Micosoft Visual Basic 2010 Express to include the DLL when I publish the code? (I'm currently using the standard ClickOnce installer that comes as standard with the IDE)

Cheers,
Jesper

VB.NET:
Imports System.Reflection
Imports System.Runtime.InteropServices


Public Class Form1
    Public Enum FIF
        FIF_UNKNOWN = -1
        FIF_BMP = 0
        FIF_ICO = 1
        FIF_JPEG = 2
        FIF_JNG = 3
        FIF_KOALA = 4
        FIF_LBM = 5
        FIF_MNG = 6
        FIF_PBM = 7
        FIF_PBMRAW = 8
        FIF_PCD = 9
        FIF_PCX = 10
        FIF_PGM = 11
        FIF_PGMRAW = 12
        FIF_PNG = 13
        FIF_PPM = 14
        FIF_PPMRAW = 15
        FIF_RAS = 16
        FIF_TARGA = 17
        FIF_TIFF = 18
        FIF_WBMP = 19
        FIF_PSD = 20
        FIF_CUT = 21
        FIF_IFF = FIF_LBM
        FIF_XBM = 22
        FIF_XPM = 23
    End Enum
    <DllImport("FreeImage.dll")> _
    Public Shared Function FreeImage_Load(ByVal format As FIF, ByVal filename As String, ByVal flags As Integer) As Integer
    End Function


    <DllImport("FreeImage.dll")> _
    Public Shared Sub FreeImage_Unload(ByVal handle As Integer)
    End Sub


    <DllImport("FreeImage.dll")> _
    Public Shared Function FreeImage_Save(ByVal format As FIF, ByVal handle As Integer, ByVal filename As String, ByVal flags As Integer) As Boolean
    End Function
    <DllImport("FreeImage.dll")> _
    Public Shared Function FreeImage_GetScanLine(ByVal handle As Integer, ByVal y As Integer) As IntPtr
    End Function
    '.......


    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim stp As New Stopwatch
        stp.Start()
        For i = 1 To 1000
            ' Dim bm As New Bitmap("C:\gray.jpg",0)
            Dim myimage As Integer = FreeImage_Load(FIF.FIF_JPEG, "C:\gray.jpg", 0)
            Dim imgptr As IntPtr = FreeImage_GetScanLine(myimage, 0)
            Dim bytes(1280 * 1024) As Byte
            Marshal.Copy(imgptr, bytes, 0, 1280 * 1024 - 1)


            '            Dim bm As New Bitmap(1280, 1024, System.Drawing.Imaging.PixelFormat.Format8bppIndexed)
            '           Dim bmData As System.Drawing.Imaging.BitmapData = bm.LockBits(New Rectangle(0, 0, 1280, 1024), Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format8bppIndexed)
            '          Dim dptr As System.IntPtr = bmData.Scan0


            ' Marshal.Copy(bytes, 0, dptr, 1280 * 1024 - 1)
            ' bm.UnlockBits(bmData)
            ' PictureBox1.Image = bm


            ' do something with bitmap
            '  PictureBox1.Image = bm


            FreeImage_Unload(myimage)
        Next
        Label1.Text = CStr(stp.ElapsedMilliseconds)
    End Sub
End Class
 
Back
Top