Image splicing

dizzy01
dizzy01 used Ask the Experts™
on
Hi,

I have written an application that takes two .tif images and splices the first on top of the second.  It also reduces the spliced image's bit depth to 1.  This application works but is REALLY slow :) and i was hoping for some help to improve it's performance.  Any tips and/or code examples would be appreciated.

thanks.

Dom
Imports System
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Drawing.Imaging
Imports System.collections
Imports System.ComponentModel
Imports System.Windows.Forms
Imports System.data
Imports System.Runtime.InteropServices
 
Public Class Form1
 
    Private Sub btnGo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGo.Click
 
        Dim tif1 As String = "c:\imgtest\004.tif"
        Dim tif2 As String = "c:\imgtest\005.tif"
        Dim tif3 As String = "c:\imgtest\006.tif"
 
        Dim img1 As Image = Image.FromFile(tif1)
        Dim img2 As Image = (Image.FromFile(tif2))
 
        Dim Width As Integer = (img1.Width)
        Dim Height As Integer = (img1.Height + img2.Height)
        Dim img3 As Bitmap = (New Bitmap(Width, Height))
        img3.SetResolution(200, 200)
 
        Dim g As Graphics = (Graphics.FromImage(img3))
 
 
 
        g.Clear(Color.Black)
        g.DrawImage(img1, New Point(0, 0))
        g.DrawImage(img2, New Point(0, img2.Height))
 
        g.Dispose()
        img1.Dispose()
        img2.Dispose()
 
 
        'new code from James
        'lock the bits of the original bitmap
        Dim bmdo As BitmapData = img3.LockBits(New Rectangle(0, 0, img3.Width, img3.Height), ImageLockMode.ReadOnly, img3.PixelFormat)
        'add new 1bpp bitmap and lock its bits
        Dim img4 As Bitmap = New Bitmap(img3.Width, img3.Height, PixelFormat.Format1bppIndexed)
        img4.SetResolution(200, 200)
 
        Dim bmdn As BitmapData = img4.LockBits(New Rectangle(0, 0, img4.Width, img4.Height), ImageLockMode.ReadWrite, PixelFormat.Format1bppIndexed)
        'scan through the pixels y by x
        Dim y As Integer
        For y = 0 To img3.Height - 1
            Dim x As Integer
            For x = 0 To img3.Width - 1
                'generate address of colour pixel
                Dim index As Integer = y * bmdo.Stride + x * 4
                'check it's brightness
                If Color.FromArgb(Marshal.ReadByte(bmdo.Scan0, index + 2), Marshal.ReadByte(bmdo.Scan0, index + 1), Marshal.ReadByte(bmdo.Scan0, index)).GetBrightness() > 0.5F Then
                    Me.SetIndexedPixel(x, y, bmdn, True)
                End If
            Next
        Next
        'tidy up
        img3.UnlockBits(bmdo)
        img4.UnlockBits(bmdn)
        img3.Dispose()
 
        Dim info As ImageCodecInfo = Nothing
        Dim ice As ImageCodecInfo
        For Each ice In ImageCodecInfo.GetImageEncoders()
            If ice.MimeType = "image/tiff" Then
                info = ice
                Exit For
            End If
        Next
 
 
        Dim enc As Encoder = Encoder.SaveFlag
        Dim ep As New EncoderParameters(1)
 
        ep.Param(0) = New EncoderParameter(Encoder.Compression, CLng(EncoderValue.CompressionCCITT4))
 
 
        img4.Save(tif3, info, ep)
        img4.Dispose()
 
        'end of new code
        MsgBox("Done")
    End Sub
 
    Protected Sub SetIndexedPixel(ByVal x As Integer, ByVal y As Integer, ByVal bmd As BitmapData, ByVal pixel As Boolean)
        Dim index As Integer = y * bmd.Stride + (x >> 3)
        Dim p As Byte = Marshal.ReadByte(bmd.Scan0, index)
        Dim mask As Byte = &H80 >> (x And &H7)
        If pixel Then
            p = p Or mask
        Else
            p = p And CByte(mask ^ &HFF)
        End If
        Marshal.WriteByte(bmd.Scan0, index, p)
    End Sub

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Most Valuable Expert 2012
Top Expert 2014

Commented:
Its this loop code
        For y = 0 To img3.Height - 1
            Dim x As Integer
            For x = 0 To img3.Width - 1
                'generate address of colour pixel
                Dim index As Integer = y * bmdo.Stride + x * 4
                'check it's brightness
                If Color.FromArgb(Marshal.ReadByte(bmdo.Scan0, index + 2), Marshal.ReadByte(bmdo.Scan0, index + 1), Marshal.ReadByte(bmdo.Scan0, index)).GetBrightness() > 0.5F Then
                    Me.SetIndexedPixel(x, y, bmdn, True)
                End If
            Next
        Next

which would be taking a lot of time and i dont think there is any way of improving it.

Author

Commented:
Yes, that is the area  that is taking the time.  I couldn't think of a way to improve it but it's nice to know that i've not missed something.  Thank you.
Most Valuable Expert 2012
Top Expert 2014

Commented:
You may want to try the GetPixel method of a bitmap instead of using the Marshal.ReadByte.
Hi,

I think you can do image manipulation quicker in C# as you can make use of a native pointer to directly access the bytes instead of having to use multiple method calls. probably not the answer you were looking for.

if I were you I'd comment out the contents of your SetIndexedPixel method to see how much of an overhead this is adding initially. in essence there are lots of nested method calls which impact performance
Commented:
C# would speed it up but unfortunately I do not have the time to re-write the rest of the application.  Thanks for the suggestions though.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial