Link to home
Start Free TrialLog in
Avatar of dizzy01
dizzy01Flag for United Kingdom of Great Britain and Northern Ireland

asked on

Image splicing

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

Avatar of Nasir Razzaq
Nasir Razzaq
Flag of United Kingdom of Great Britain and Northern Ireland image

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.
Avatar of dizzy01

ASKER

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.
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
ASKER CERTIFIED SOLUTION
Avatar of dizzy01
dizzy01
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial