SilkTest 技術情報(FAQ)


.NETスクリプトで除外領域を指定してビットマップオブジェクトの比較を行う

.NET スクリプトでは、.NET Frameworkの高度な機能が簡単に使用できます。

このサンプルコードは、ビットマップオブジェクト同士を高速に比較し、差異を強調した画像ファイルとして保存することができます。

また、画像比較の際に除外領域を指定することも出来ます。

  • ※Silk Test 14.0からイメージ検証機能が追加されました。

共有モジュールとしてコーディングを行う

  • 共有モジュールとしてBmpDiffVBクラスを作成
  1. ファイルメニューから「新規作成 → .NETスクリプト」、資産名「BmpDiff」として空の資産を作成します。
  2. 次のプログラムをそのまま共有モジュールの内容に貼り付けて保存します。
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.Runtime.InteropServices
Public Class BmpDiffVB
    Private bmpBody1 As BitmapData
    Private bmpBody2 As BitmapData
    Private bmpBodyR As BitmapData
 
    Private bmpData1 As Bitmap
    Private bmpData2 As Bitmap
    Private bmpDataR As Bitmap
    Private fmtData1 As PixelFormat
    Private fmtData2 As PixelFormat
    Private isSizeDiffer As Boolean
    Private lstExcluded As List(Of Rectangle)
 
 
    Public ReadOnly Property LastResult() As Bitmap
        Get
            Dim bitmap As Bitmap = Me.bmpDataR
            Return bitmap
        End Get
    End Property
 
    Public Sub New(ByVal strFilename1 As String, ByVal strFilename2 As String)
        MyBase.New()
        Me.fmtData1 = PixelFormat.Format24bppRgb
        Me.fmtData2 = PixelFormat.Format24bppRgb
        Me.lstExcluded = New List(Of Rectangle)()
        Me.isSizeDiffer = False
        Me.bmpData1 = New Bitmap(strFilename1)
        Me.bmpData2 = New Bitmap(strFilename2)
        Me.bmpDataR = Me.bmpData1.Clone(New Rectangle(0, 0, Me.bmpData1.Width, Me.bmpData1.Height), Me.bmpData1.PixelFormat)
        Me.bmpBody1 = Nothing
        Me.bmpBody2 = Nothing
        Me.isSizeDiffer = Me.chkSize()
    End Sub
 
    Public Sub New(ByVal a_Bmp1 As Bitmap, ByVal a_Bmp2 As Bitmap)
        MyBase.New()
        Me.fmtData1 = PixelFormat.Format24bppRgb
        Me.fmtData2 = PixelFormat.Format24bppRgb
        Me.lstExcluded = New List(Of Rectangle)()
        Me.isSizeDiffer = False
        Me.bmpData1 = a_Bmp1
        Me.bmpData2 = a_Bmp2
        Me.bmpDataR = Me.bmpData1.Clone(New Rectangle(0, 0, Me.bmpData1.Width, Me.bmpData1.Height), Me.bmpData1.PixelFormat)
        Me.bmpBody1 = Nothing
        Me.bmpBody2 = Nothing
        Me.isSizeDiffer = Me.chkSize()
    End Sub
 
    Public Sub AddExcluded(ByVal r As Rectangle)
        Me.lstExcluded.Add(r)
    End Sub
 
    Public Function chkSize() As Boolean
        Dim flag As Boolean
        Dim height As Boolean
        If (Me.bmpData1.Width <> Me.bmpData2.Width) Then
            height = False
        Else
            height = Me.bmpData1.Height = Me.bmpData2.Height
        End If
        If (height) Then
            flag = False
        Else
            flag = True
        End If
        Return flag
    End Function
 
    Public Function GetDepth(ByVal pic As PixelFormat) As Integer
        Select Case pic
            Case PixelFormat.Format32bppPArgb
                Return 4
            Case PixelFormat.Format32bppArgb
                Return 4
            Case PixelFormat.Format24bppRgb
                Return 3
            Case PixelFormat.Format32bppRgb
                Return 4
        End Select
        Throw New InvalidOperationException("Unsupported pixel format")
    End Function
 
 
    Public Function Compare() As Boolean
        Me.setTurbo()
        If Me.isSizeDiffer Then
            Return False
        End If
        If (Me.fmtData1 <> Me.fmtData2) Then
            Return False
        End If
        Dim bResult As Boolean = True
        If (Not Me.bmpBody1 Is Nothing) Then
            Dim depth As Integer = Me.GetDepth(Me.fmtData1)
            Dim adr1 As IntPtr = Me.bmpBody1.Scan0
            Dim adr2 As IntPtr = Me.bmpBody2.Scan0
            Dim adrR As IntPtr = Me.bmpBodyR.Scan0
            Dim y As Integer
            For y = 0 To Me.bmpData1.Height - 1
                Dim x As Integer
                For x = 0 To Me.bmpBody1.Width - 1
                    Dim pos As Integer = ((x * depth) + (Me.bmpBody1.Stride * y))
                    Dim isDifferent As Boolean = False
                    For i As Integer = 0 To depth - 1
                        Dim b1 As Byte = Marshal.ReadByte(adr1, (pos + i))
                        Dim b2 As Byte = Marshal.ReadByte(adr2, (pos + i))
                        If (b1 <> b2) Then
                            isDifferent = True
                        End If
                        i += 1
                    Next
                    If isDifferent Then
                        For i As Integer = 0 To depth - 1
                            Marshal.WriteByte(adrR, (pos + i), &HFF)
                            i += 1
                        Next i
                        bResult = False
                    Else
                        For i As Integer = 0 To depth - 1
                            Dim bR As Byte = CByte((Marshal.ReadByte(adrR, (pos + i)) >> 2))
                            Marshal.WriteByte(adrR, (pos + i), bR)
                        Next i
                    End If
                Next x
            Next y
        End If
        Me.bmpData1.UnlockBits(Me.bmpBody1)
        Me.bmpData2.UnlockBits(Me.bmpBody2)
        Me.bmpDataR.UnlockBits(Me.bmpBodyR)
        Return bResult
    End Function
 
 
    Public Function Compare(ByVal strResultFile As String) As Boolean
        Dim bRet As Boolean = Me.Compare()
        If (strResultFile <> Nothing) Then
            Me.bmpDataR.Save(strResultFile)
        End If
        Dim flag As Boolean = bRet
        Return flag
    End Function
 
    Public Function Compare(ByRef resultBMP As Bitmap) As Boolean
        Dim bRet As Boolean = Me.Compare()
        resultBMP = DirectCast(Me.bmpDataR.Clone(), Bitmap)
        Dim flag As Boolean = bRet
        Return flag
    End Function
 
 
 
    Private Sub setTurbo()
        Dim right As Boolean = False
        If (Me.isSizeDiffer) Then
            Return
        End If
 
        Me.bmpBody1 = Me.bmpData1.LockBits(New Rectangle(0, 0, Me.bmpData1.Width, Me.bmpData1.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb)
        Me.bmpBody2 = Me.bmpData2.LockBits(New Rectangle(0, 0, Me.bmpData2.Width, Me.bmpData2.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb)
        Me.bmpBodyR = Me.bmpDataR.LockBits(New Rectangle(0, 0, Me.bmpDataR.Width, Me.bmpDataR.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb)
        Dim adr1 As IntPtr = Me.bmpBody1.Scan0
        Dim adr2 As IntPtr = Me.bmpBody2.Scan0
        Dim depth As Integer = Me.GetDepth(Me.fmtData1)
 
        For Each r As Rectangle In lstExcluded
            For y As Integer = r.Top To r.Bottom
                For x As Integer = r.Left To r.Right
                    Dim pos As Integer = x * depth + bmpBody1.Stride * y
                    For i As Integer = 0 To depth - 1
                        System.Runtime.InteropServices.Marshal.WriteByte(adr1, pos + i, 0)
                        System.Runtime.InteropServices.Marshal.WriteByte(adr2, pos + i, 0)
                    Next
                Next
            Next
        Next
    End Sub
End Class

他の.NETスクリプトからの呼び出し例

上記で作成した.NETスクリプトは、共有モジュールとして利用できます。プロパティの[参照]→[.NETスクリプト]で「.NETスクリプト参照の追加」を選択して、common.BmpDiffを追加してください。

たとえば、次のプログラムは、Windows7の「砂漠.jpg」と、「クラゲ.jpg」を比較し、比較結果を「result.bmp」という名前で保存しています。 また、除外領域として左上から100x100ドットの矩形部分を定義します。

今回紹介したクラスは、ビットマップファイルを比較することはできません。そのため、Bitmapオブジェクトを作成してから保存している点に注意してください。

Public Module Main
	Dim _desktop As Desktop = Agent.Desktop
	Public Sub Main()
		Dim bmp1 As New Bitmap("C:\Users\Public\Pictures\Sample Pictures\Desert.jpg")
		Dim bmp2 As New Bitmap("C:\Users\Public\Pictures\Sample Pictures\Chrysanthemum.jpg")
		Dim diff As BmpDiffVB = New  BmpDiffVB(bmp1,bmp2)
		Dim bret As Boolean 
		
		diff.AddExcluded(New Rectangle(0,0,100,100) )
		bret = diff.Compare("C:\Users\Public\Pictures\Sample Pictures\result.bmp")
		Workbench.Verify(bret)
	End Sub
End Module

免責事項

ここで紹介したスクリプトは説明のためのサンプルであり、製品の一部ではございません。スクリプトが実際に動作するか、御社業務に適合するかなどに関しまして、一切の保証はございません。 スクリプト、説明、その他すべてについて、無謬性は保障されません。

ここで紹介するスクリプトの一部、もしくは全部について、弊社に断りなく、御社スクリプトの内部に組み込み、そのままご利用頂いても構いません。

本スクリプトの一部もしくは全部を二次的著作物に対して引用する場合、著作権法の精神に基づき、適切な扱いを行ってください。