-
Oct 8th, 2017, 05:30 AM
#1
Thread Starter
Addicted Member
Why are the two pictures not the same after Save and Load it agains?
Hello,
need to compare two pictures which are obtained using the function BitBlt:
Code:
hDC = GetWindowDC(GetDesktopWindow)
BitBlt picTemp.hDC, 0, 0, Width, Height, hDC, left, top, vbSrcCopy
picTemp.Picture = picTemp.Image
then, i'm clone this picture to another:
Code:
BitBlt picDest.hDC, 0, 0, picTemp.Width, picTemp.Height, picTemp.hDC, 0, 0, vbSrcCopy
picDest.Picture = picDest.Image
and now, if i'm compare these pictures, they will be identical.
(i'm using compare method from this place http://www.vbforums.com/showthread.p...=1#post2926566,
also, attaching module with method to the post. Ex.: ImagesSame(Picture1, Picture2))
But,
when I'm saving picture from picDest:
Code:
SavePicture picDest.Picture, "C:\pic.bmp"
and load again to PictureBox:
Code:
picDest.Picture = LoadPicture("C:\pic.bmp")
picDest.Picture = picDest.Image
These pictures are no longer identical!
The question is how to make the loadable picture identical to the one that was obtained with the function BitBlt?
------------------------------------------------------------------------------------------------------------
ModImageCompare.bas
Ten Years After - 01 You Give Me Loving
-
Oct 8th, 2017, 10:27 AM
#2
Re: Why are the two pictures not the same after Save and Load it agains?
Are the two pictureboxes identically sized? Why are you calling LoadPicture, then setting the Picture property from the Image property? No point and could potentially change the .Picture property if the picbox inner dimensions are not the same size as the loaded picture.
There are potentially several other problems with your code. I think you need to understand the difference between an object's Width and its ScaleWidth, its Height and ScaleHeight. A form's Width/Height is always measured in Twips. A control's Width/Height is measured in that control container's ScaleMode. ScaleWidth and ScaleHeight can be measured in scalemodes you dictate.
That compare routine assumes that the picbox scalemode is pixels, not Twips or anything else.
Edited: In my opinion trying to compare a screen capture of a desktop to some saved capture from a different date is pointless. Even when trying to compare captures just seconds apart can be different. For example, my desktop background is random and changes on its own while the pc is running. If a web browser was open, there could be animated images being displayed, the time displayed in the taskbar could change, and a wide range of other variables apply. Good luck with that.
Last edited by LaVolpe; Oct 8th, 2017 at 11:18 AM.
-
Oct 8th, 2017, 11:57 AM
#3
Re: Why are the two pictures not the same after Save and Load it agains?
FYI: That comparison routine relies on more assumptions as I look at it deeper.
Assumes: Picbox ScaleMode is pixels and AutoSize=True. Otherwise...
Scenario 1: Picture assigned is 256x256 but the picbox is larger. Or the picbox scalemode is twips (twip sizes are greater than pixels)
The routine will create arrays that are larger than what would be needed to read just the picture's pixels. This may still compare correctly, because the unfilled array entries will be zeroes. But it may also fail and haven't tested it. The GetDibits call requests an image height that exceeds the actual height. The return value of GetDibits is not checked to see if it is zero. If it is zero, then nothing was retrieved and the comparison would simply be comparing arrays filled with zeroes (false positive result)
Scenario 2: Picture assigned is 256x256 but the picbox is smaller and scalemode is pixels
The routine will not compare the entire image, only part of it.
That routine isn't written to deal with non-pixel scalemodes and cases where the picbox is not exactly sized as the image it contains. AutoSize=True and ScaleMode=Pixels will help for loaded pictures. It is also not optimized. It should not even attempt to retrieve the pixel data if the picture sizes are not identical, but it does. If image sizes are different, then they cannot possibly be identical.
-
Oct 8th, 2017, 12:15 PM
#4
Thread Starter
Addicted Member
Re: Why are the two pictures not the same after Save and Load it agains?
Well of course the size is the same. And i know about sizes, scales and units. The problem is different.
If not difficult, make please these steps:
- place on the Form 2 identical PictureBox with AutoRedraw = True
- take a screenshot of the specified area into PictureBox1
- then save image from PictureBox1
- then load the saved image into PictureBox2
- again make a screenshot of the same area
- compare images
As a result, you should leave visually 2 identical images. But only at first glance.
Now, if you compare these two PictureBox'es, they will not be identical.
Code:
Private Type Rect
Left As Long
Top As Long
right As Long
bottom As Long
End Type
Private Declare Function GetSystemMetrics Lib "user32" (ByVal nIndex As Long) As Long
Private Declare Function GetWindowRect Lib "user32" (ByVal hWnd As Long, lpRect As Rect) As Long
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function GetWindowDC Lib "user32" (ByVal hWnd As Long) As Long
Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
Private Declare Function ReleaseDC Lib "user32" (ByVal hWnd As Long, ByVal hDC As Long) As Long
Private Sub GetScreenshot(Optional ByVal hWnd As Long = 0)
Dim hDC As Long
Dim WindowRect As Rect
Dim Left As Long
Dim Top As Long
Dim Width As Long
Dim Height As Long
If hWnd = 0 Then
'Get the DC of the desktop
hDC = GetWindowDC(GetDesktopWindow)
'Get the virtual screen coordinates (this handles multiple monitors too :)
Left = 700
Top = 300
Width = 220
Height = 130
Else
'Get the DC of the window we want to capture
hDC = GetWindowDC(hWnd)
'Get the window coordinates
GetWindowRect hWnd, WindowRect
Left = 0
Top = 0
Width = WindowRect.right - WindowRect.Left
Height = WindowRect.bottom - WindowRect.Top
End If
'BitBlt into our own DC
BitBlt PictureBox1.hDC, 0, 0, Width, Height, hDC, Left, Top, vbSrcCopy
PictureBox1.Picture = PictureBox1.Image
'Delete our reference to the windows's DC
ReleaseDC hWnd, hDC
End Sub
Private Sub ShotSaveLoadAndCompare()
GetScreenshot
SavePicture PictureBox1.Picture, "C:\pic.bmp"
PictureBox2.Picture = LoadPicture("C:\pic.bmp")
PictureBox2.Picture = PictureBox2.Image
Debug.Print ImagesSame(PictureBox1, PictureBox2)
End Sub
'this code return true when compare
Private Sub TestForTrueCompare()
GetScreenshot
BitBlt PictureBox2.hDC, 0, 0, PictureBox1.Width, PictureBox1.Height, PictureBox1.hDC, 0, 0, vbSrcCopy
PictureBox2.Picture = PictureBox2.Image
Debug.Print ImagesSame(PictureBox1, PictureBox2)
End Sub
Last edited by sergeos; Oct 8th, 2017 at 12:25 PM.
Ten Years After - 01 You Give Me Loving
-
Oct 8th, 2017, 12:27 PM
#5
Re: Why are the two pictures not the same after Save and Load it agains?
You don't explain what the properties/dimensions of the pictureboxes should be. Maybe you should upload a test project instead? At least we'd be able to look at your exact code and be able to explain why it failed.
-
Oct 8th, 2017, 12:34 PM
#6
Thread Starter
Addicted Member
Re: Why are the two pictures not the same after Save and Load it agains?
LaVolpe, please, just copy-paste my code into Form module, and also include module with Picture compare from first topic. Thank you for your responsiveness.
Ten Years After - 01 You Give Me Loving
-
Oct 8th, 2017, 01:27 PM
#7
Re: Why are the two pictures not the same after Save and Load it agains?
If you place a stop on the Exit For in that compare routine and test the 2 values that don't compare, you will notice something:
1 of the bitmaps is using the alpha channel, the other is not. Therefore, the pixels are not identical
Example:
? hex(lonPix_1(lonLoop)) is FFAE8F8F
? hex(lonPix_2(lonLoop)) is AE8F8F
Based on the above, it appears BitBlt is setting the alpha byte in the picturebox's DC, but VB does not do 32bpp images, so it converts the image to 24bpp when it saves it. GetDIBits will return 0 as the alpha byte if the source bitmap is not 32bpp (saved bitmap), but will return it if the bitmap is 32bpp (picturebox bitmap).
If you want to ignore the alpha channel, the compare module may need to be written to return pixels in 24bpp vs 32bpp. Of course this does require reworking the loop and sizing the array to deal with DWORD aligned bitmap scan widths. Optionally, you can still use 32bpp, but only compare the 1st 3 bytes of the value, not all four, i.e.,
Code:
If (lonPix_1(lonLoop) And &HFFFFFF) <> (lonPix_2(lonLoop) And &HFFFFFF) Then
-
Oct 8th, 2017, 02:13 PM
#8
Thread Starter
Addicted Member
Re: Why are the two pictures not the same after Save and Load it agains?
Big thanks, LaVolpe!
Rewritten module by me is impossible now. Not have skills. Hmmm, and what if i'm adding prefix to compair result? Like this
? FFAE8F8F = "FF" & AE8F8F
Ten Years After - 01 You Give Me Loving
-
Oct 8th, 2017, 02:40 PM
#9
Re: Why are the two pictures not the same after Save and Load it agains?
Originally Posted by sergeos
Rewritten module by me is impossible now. Not have skills. Hmmm, and what if i'm adding prefix to compair result? Like this
? FFAE8F8F = "FF" & AE8F8F
No. The array are longs not strings. It would be ? &HFFAE8F8F = &HFF000000 OR &HAE8F8F
But if you don't want to rewrite, simply make the change I suggested in my previous reply
Instead of: If lonPix_1(lonLoop) <> lonPix_2(lonLoop) Then
This: If (lonPix_1(lonLoop) And &HFFFFFF) <> (lonPix_2(lonLoop) And &HFFFFFF) Then
-
Oct 8th, 2017, 03:53 PM
#10
Thread Starter
Addicted Member
Re: Why are the two pictures not the same after Save and Load it agains?
Big thanks,
Mustang Mach I is power!
Ten Years After - 01 You Give Me Loving
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|