먼저 비교할 이미지의 크기는 같다는 조건이며, 하나의 픽셀도 다르다면 다른것으로 간주한다.

GetDIBits는 비트맵에 대한 정보,데이타(각 픽셀 데이타)를 지정된 방식에 따라 구성하여 반환한다.

비트맵을 버퍼에 복사한다
● 선언
Function GetDIBits Lib "gdi32" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long

● 인수

aHDC ━ DC 핸들
hBitmap ━ 비트맵 핸들
nStartScan ━ 시작할 스캔 라인
nNumScans ━ 스캔할 라인수
lpBits ━ 비트맵의 각 비트 데이터가 저장될 버퍼
lpBI ━ 비트맵 형식
wUsage ━ 어떤 칼라를 사용할지를 나타낸다

● 반환
성공 ━ lpBits이 Null이 아니면 스캔 라인수, Null이면 0이 아닌 값
실패 ━ 0

상수
wUsage 사용, 어떤 칼라 사용하는지

상수 설명
DIB_RGB_COLORS 0 RGB 색 사용
DIB_PAL_COLORS 1 팔레트의 인덱스 사용(16-bit인덱스)

소스의 간략한 설명이다.
우선 메모리의 비트맵과 DC를 생성하고, 메모리 비트맵에 비교할 첫번째 이미지를 복사하고, 두번째 이미지를 메모리 비트맵과 XOR를 하여서 복하나다. 같은 픽셀의 같은 칼러의 픽셀은 검은색(&H00000000)이 되 버린다. GetDIBs를 사용해서 비트 데이터를 복하한후에 비트 데이터가 다 0이라면 두 이미가 같다는 것이고 0이 아닌 값이 있다면 다른것으로 간주한다.

소스 초기 이미지이다


이미지 비교 버튼을 누르면 두 이미지를 비교한다.


소스이다.
Option Explicit
Option Base 1

Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function BitBlt Lib "gdi32" (ByVal hDCDest As Long, ByVal XDest As Long, ByVal YDest As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hdcSrc As Long, ByVal XSrc As Long, ByVal YSrc As Long, ByVal dwRop As Long) As Long
Private Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
Private Declare Function OleCreatePictureIndirect Lib "olepro32.dll" (PicDesc As Any, RefIID As GUID, ByVal fPictureOwnsHandle As Long, IPic As IPicture) As Long ' 생성된 비트맵을 VB에서 사용가능하도록, 이미지 개체로 만든다.
Private Declare Function CLSIDFromString Lib "ole32" (ByVal str As Long, id As GUID) As Long
Private Declare Function GetObject Lib "gdi32" Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Long, ByVal Source As Long, ByVal length As Long)
Private Declare Function GetDIBits Lib "gdi32" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFOHEADER, ByVal wUsage As Long) As Long

Private Type GUID ' 이미지 개체 클래스 ID를 저장할 구조체
    Data1 As Long
    Data2 As Integer
    Data3 As Integer
    Data4(7) As Byte
End Type

Private Type PicBmp ' VB에서 이미지 개체를 생성하기 위한 정보 구조체
    Size As Long
    Type As Long
    BitmapHwnd As Long
    hPal As Long
    Reserved As Long
End Type

Private Type BITMAP
    bmType As Long
    bmWidth As Long
    bmHeight As Long
    bmWidthBytes As Long
    bmPlanes As Integer
    bmBitsPixel As Integer
    bmBits As Long
End Type

Private Type BITMAPINFOHEADER
    biSize          As Long
    biWidth         As Long
    biHeight        As Long
    biPlanes        As Integer
    biBitCount      As Integer
    biCompression   As Long
    biSizeImage     As Long
    biXPelsPerMeter As Long
    biYPelsPerMeter As Long
    biClrUsed       As Long
    biClrImportant  As Long
End Type

Private Const SRCCOPY = &HCC0020
Private Const SRCINVERT = &H660046
Private Const BI_RGB = 0
Private Const DIB_RGB_COLORS = 0

Public Function CreateImageDC(sPic As StdPicture) As Long ' 이미지에 대한 DC 생성
    Dim hdcPicture As Long ' 메모리 DC

   hdcPicture = CreateCompatibleDC(ByVal 0&)
   SelectObject hdcPicture, sPic.Handle
   CreateImageDC = hdcPicture
End Function

Private Function CheckBitmapBlack(ByVal ImageHandle As Long, ByVal ImageDC As Long) As Boolean ' 비트맵이 검은색인지를 판별한다. 검은색일경우 True 반환
    Dim BITMAPINFO As BITMAP
    Dim BitmapInfoHeafer As BITMAPINFOHEADER
    Dim CheckData() As Byte
   
    GetObject ImageHandle, LenB(BITMAPINFO), BITMAPINFO
    With BitmapInfoHeafer
        .biSize = LenB(BitmapInfoHeafer)
        .biWidth = BITMAPINFO.bmWidth
        .biHeight = BITMAPINFO.bmHeight
        .biPlanes = 1
        .biBitCount = BITMAPINFO.bmBitsPixel
        .biCompression = BI_RGB
    End With
    GetDIBits ImageDC, ImageHandle, 0, BITMAPINFO.bmHeight, ByVal 0&, BitmapInfoHeafer, DIB_RGB_COLORS ' 이미지의 비트 데이터 크기를얻는다
    ReDim CheckData(BitmapInfoHeafer.biSizeImage)
    GetDIBits ImageDC, ImageHandle, 0, BITMAPINFO.bmHeight, ByVal VarPtr(CheckData(1)), BitmapInfoHeafer, DIB_RGB_COLORS  ' 이미지의 비트 데이터 크기를얻는다
    CheckBitmapBlack = Len(Replace(CheckData, vbNullChar, "")) = 0
End Function

Private Sub cmdImageCompare1_Click() ' 같은 이미지 비교
    Dim Sorhdc As Long ' 소스 DC
    Dim Deshdc As Long ' 대상 DC(메모리)
    Dim DesBitmap As Long ' 대상 비트맵(메모리)
    Dim SizeX As Long ' 첫번째 이미지 박스 비트맵 크기 : X축 픽셀수
    Dim SizeY As Long ' 첫번째 이미지 박스 비트맵 크기 : Y축 픽셀수
    Dim Pic As PicBmp ' 비트맵을 OLE 개체로 생성하기 위한 비트맵 정보
    Dim IID_IDispatch As GUID ' VB에서 사용할 이미지 개체의 GUID
    Dim IPic As IPictureDisp ' VB에서 사용할 이미지 개체

    SizeX = CLng(Me.ScaleX(imgSource11.Picture.Width, vbHimetric, vbPixels)) ' 이미지박스 이지미의 픽셀 크기
    SizeY = CLng(Me.ScaleY(imgSource11.Picture.Height, vbHimetric, vbPixels))

    Sorhdc = CreateImageDC(imgSource11.Picture) ' 이미지에 대한 DC를 생성한다
    Deshdc = CreateCompatibleDC(ByVal 0&) ' 메모리 DC와 메모리 비트맵을 생성한다.
    DesBitmap = CreateCompatibleBitmap(picXor1.hdc, SizeX, SizeY)
    SelectObject Deshdc, DesBitmap ' 메모리 DC와 메모리 비트맵을 연결한다
    BitBlt Deshdc, 0, 0, SizeX, SizeY, Sorhdc, 0, 0, SRCCOPY ' 이미지 박스 이미지를 메모리 비트맵에 복사
    DeleteDC Sorhdc
    Sorhdc = CreateImageDC(imgSource12.Picture) ' 이미지에 대한 DC를 생성한다
    BitBlt Deshdc, 0, 0, SizeX, SizeY, Sorhdc, 0, 0, SRCINVERT ' 이미지 박스 이미지와 메모리 비트맵에 이미지를 XOR로 하여 복사한다
    DeleteDC Sorhdc
   
    labResult1.Caption = IIf(CheckBitmapBlack(DesBitmap, Deshdc), "같음", "다름") ' 두 이미지를 XOR 한 결과가 검은색이면 True를 반환한다
   
    DeleteDC Deshdc

    ' 메모리의 비트맵을 VB에서 사용하는 이미지 개체로 변환
    Call CLSIDFromString(StrPtr("{00020400-0000-0000-C000-000000000046}"), IID_IDispatch) ' vb에서 사용되는 GUID를 구조체에 저장한다.
    With Pic
        .Size = Len(Pic)
        .Type = vbPicTypeBitmap
        .BitmapHwnd = DesBitmap
        .hPal = 0&
    End With
    Call OleCreatePictureIndirect(Pic, IID_IDispatch, 1, IPic)
    Set picXor1.Picture = IPic ' 생성된 이미지 개체 반환
End Sub

Private Sub cmdImageCompare2_Click() ' 다른 이미지 비교
    Dim Sorhdc As Long ' 소스 DC
    Dim Deshdc As Long ' 대상 DC(메모리)
    Dim DesBitmap As Long ' 대상 비트맵(메모리)
    Dim SizeX As Long ' 첫번째 이미지 박스 비트맵 크기 : X축 픽셀수
    Dim SizeY As Long ' 첫번째 이미지 박스 비트맵 크기 : Y축 픽셀수
    Dim Pic As PicBmp ' 비트맵을 OLE 개체로 생성하기 위한 비트맵 정보
    Dim IID_IDispatch As GUID ' VB에서 사용할 이미지 개체의 GUID
    Dim IPic As IPictureDisp ' VB에서 사용할 이미지 개체

    SizeX = CLng(Me.ScaleX(imgSource21.Picture.Width, vbHimetric, vbPixels)) ' 이미지박스 이지미의 픽셀 크기
    SizeY = CLng(Me.ScaleY(imgSource21.Picture.Height, vbHimetric, vbPixels))

    Sorhdc = CreateImageDC(imgSource21.Picture) ' 이미지에 대한 DC를 생성한다
    Deshdc = CreateCompatibleDC(ByVal 0&) ' 메모리 DC와 메모리 비트맵을 생성한다.
    DesBitmap = CreateCompatibleBitmap(picXor2.hdc, SizeX, SizeY)
    SelectObject Deshdc, DesBitmap ' 메모리 DC와 메모리 비트맵을 연결한다
    BitBlt Deshdc, 0, 0, SizeX, SizeY, Sorhdc, 0, 0, SRCCOPY ' 이미지 박스 이미지를 메모리 비트맵에 복사
    DeleteDC Sorhdc
    Sorhdc = CreateImageDC(imgSource22.Picture) ' 이미지에 대한 DC를 생성한다
    BitBlt Deshdc, 0, 0, SizeX, SizeY, Sorhdc, 0, 0, SRCINVERT ' 이미지 박스 이미지와 메모리 비트맵에 이미지를 XOR로 하여 복사한다
    DeleteDC Sorhdc
   
    labResult2.Caption = IIf(CheckBitmapBlack(DesBitmap, Deshdc), "같음", "다름")
   
    DeleteDC Deshdc

    ' 메모리의 비트맵을 VB에서 사용하는 이미지 개체로 변환
    Call CLSIDFromString(StrPtr("{00020400-0000-0000-C000-000000000046}"), IID_IDispatch) ' vb에서 사용되는 GUID를 구조체에 저장한다.
    With Pic
        .Size = Len(Pic)
        .Type = vbPicTypeBitmap
        .BitmapHwnd = DesBitmap
        .hPal = 0&
    End With
    Call OleCreatePictureIndirect(Pic, IID_IDispatch, 1, IPic)
    Set picXor2.Picture = IPic ' 생성된 이미지 개체 반환
End Sub

+ Recent posts