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
'API' 카테고리의 다른 글
SetWindowsHookEx를 사용한 마우스 전역 훅 (0) | 2011.10.06 |
---|---|
ODBC 레지스트리로 직접 설정 (0) | 2011.10.02 |
OleCreatePictureIndirect을 사용한 비트맵을 이미지 개체 만들기, 이미지 합성 (0) | 2011.09.30 |
CreateCompatibleBitmap을 사용한 메모리를 이용한 이미지 복사 (0) | 2011.09.30 |
CreateCompatibleDC를 사용한 이미지의 DC를 생성하자. (0) | 2011.09.30 |