Что нового

Как сравнить две картинки, идентичны ли они?

Anton

Твори! Пусть завистники твои захлебываются пылью!
Сообщения
69
Репутация
3
Есть 2 картинки одинакового размера в формате *.bmp. Нужно узнать идентичны ли они.
Не на форуме не в гугле нечего не нашел.
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
Anton
что значит идентичность? на глаз? или полная и абсолютная?
если первое, то никак.
если второе, то можно к примеру сравнить их md5-хеши
 
Автор
A

Anton

Твори! Пусть завистники твои захлебываются пылью!
Сообщения
69
Репутация
3
Нее, не на глаз, а точная копия. Пиксель в пиксель. И размер я кстати имел ввиду не вес картинки, а высоту и ширину. ;)

С хешами я не знаком :( безпонятия что это такое и с чем едят
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
Anton
каждому файлу можно сопоставить 16-значную последовательность символов (0-9, A-F) которая с очень высокой долей вероятности (идеальный вариант для сравнения двух файлов) будет уникальна для каждой из сравниваемых файлов. зовется эта последовательность - md5-хеш или дайджест. получить его можно, к примеру используя вот эту функцию
Код:
Func _MD5ForFile($sFile)

    Local $a_hCall = DllCall("kernel32.dll", "hwnd", "CreateFileW", _
            "wstr", $sFile, _
            "dword", 0x80000000, _ ; GENERIC_READ
            "dword", 1, _ ; FILE_SHARE_READ
            "ptr", 0, _
            "dword", 3, _ ; OPEN_EXISTING
            "dword", 0, _ ; SECURITY_ANONYMOUS
            "ptr", 0)

    If @error Or $a_hCall[0] = -1 Then
        Return SetError(1, 0, "")
    EndIf

    Local $hFile = $a_hCall[0]

    $a_hCall = DllCall("kernel32.dll", "ptr", "CreateFileMappingW", _
            "hwnd", $hFile, _
            "dword", 0, _ ; default security descriptor
            "dword", 2, _ ; PAGE_READONLY
            "dword", 0, _
            "dword", 0, _
            "ptr", 0)

    If @error Or Not $a_hCall[0] Then
        DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hFile)
        Return SetError(2, 0, "")
    EndIf

    DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hFile)

    Local $hFileMappingObject = $a_hCall[0]

    $a_hCall = DllCall("kernel32.dll", "ptr", "MapViewOfFile", _
            "hwnd", $hFileMappingObject, _
            "dword", 4, _ ; FILE_MAP_READ
            "dword", 0, _
            "dword", 0, _
            "dword", 0)

    If @error Or Not $a_hCall[0] Then
        DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hFileMappingObject)
        Return SetError(3, 0, "")
    EndIf

    Local $pFile = $a_hCall[0]
    Local $iBufferSize = FileGetSize($sFile)

    Local $tMD5_CTX = DllStructCreate("dword i[2];" & _
            "dword buf[4];" & _
            "ubyte in[64];" & _
            "ubyte digest[16]")

    DllCall("advapi32.dll", "none", "MD5Init", "ptr", DllStructGetPtr($tMD5_CTX))

    If @error Then
        DllCall("kernel32.dll", "int", "UnmapViewOfFile", "ptr", $pFile)
        DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hFileMappingObject)
        Return SetError(4, 0, "")
    EndIf

    DllCall("advapi32.dll", "none", "MD5Update", _
            "ptr", DllStructGetPtr($tMD5_CTX), _
            "ptr", $pFile, _
            "dword", $iBufferSize)

    If @error Then
        DllCall("kernel32.dll", "int", "UnmapViewOfFile", "ptr", $pFile)
        DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hFileMappingObject)
        Return SetError(5, 0, "")
    EndIf

    DllCall("advapi32.dll", "none", "MD5Final", "ptr", DllStructGetPtr($tMD5_CTX))

    If @error Then
        DllCall("kernel32.dll", "int", "UnmapViewOfFile", "ptr", $pFile)
        DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hFileMappingObject)
        Return SetError(6, 0, "")
    EndIf

    DllCall("kernel32.dll", "int", "UnmapViewOfFile", "ptr", $pFile)
    DllCall("kernel32.dll", "int", "CloseHandle", "hwnd", $hFileMappingObject)

    Local $sMD5 = Hex(DllStructGetData($tMD5_CTX, "digest"))

    Return SetError(0, 0, $sMD5)

EndFunc   ;==>_MD5ForFile
 

Medic84

Омега
Команда форума
Администратор
Сообщения
1 575
Репутация
335
Если уж пиксель в пиксель, то почему бы не сравнить по размеру? :smile:
 
Автор
A

Anton

Твори! Пусть завистники твои захлебываются пылью!
Сообщения
69
Репутация
3
По размеру можно попробовать. И вправду вес у них врядли будет одинаков.

Kaster, спасибо за функцию. Думаю лучшего варианта не придумать.
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
Anton
в формате bmp? вес файла будет определяться исключительно его размерами. то есть красный квадрат 4х4 будет весить столько же сколько и синий квадрат 4х4. но идентичны ли они? ;)
 

madmasles

Модератор
Глобальный модератор
Сообщения
7 790
Репутация
2 319
Anton
Попробуйте так:
Код:
$hFile1 = FileOpen("1.bmp", 16)
$hFile2 = FileOpen("2.bmp", 16)

$sTest1 = FileRead($hFile1)
$sTest2 = FileRead($hFile2)
FileClose($hFile1)
FileClose($hFile2)
MsgBox(0, "", "1.bmp - " & FileGetSize("1.bmp") & " b" & @CRLF & "2.bmp - " & FileGetSize("2.bmp") & " b")
If $sTest1 = $sTest2 Then
	MsgBox(0, "", "Одинаковые")
Else
	MsgBox(0, "", "Разные")
EndIf

картинки
 

kzru_hunter

Осваивающий
Сообщения
144
Репутация
49
Kaster предложил самый быстрый способ.
Вариант от madmasles в 2-3 раз медленнее.

Вот пример, чтобы было понятно, как быть с md5:
Код:
If _IdenticalImages("Безымянный1.bmp","Безымянный3.bmp") Then
	MsgBox(64,"Инфо","Картинки идентичны")
Else
	MsgBox(64,"Инфо","Картинки НЕ идентичны")
EndIf

Func _IdenticalImages($file1,$file2)
	If _MD5ForFile($file1) = _MD5ForFile($file2) Then
		Return True
	Else
		Return False
	EndIf
EndFunc
 
Автор
A

Anton

Твори! Пусть завистники твои захлебываются пылью!
Сообщения
69
Репутация
3
Способ madmasles действительно медленнее работает в этом случае всё таки весь файл сравнивается а при md5 хеше только 16 символов. Но для маленьких файлов пойдет и способ madmasles'a.

Всем спасибо! :ok:
 

madmasles

Модератор
Глобальный модератор
Сообщения
7 790
Репутация
2 319
Anton [?]
С хешами я не знаком
безпонятия что это такое и с чем едят
С учетом этого я и приводил свой пример. :blum:
Бесспорно, ИМХО, что хэш-сумма быстрее.
 

Medic84

Омега
Команда форума
Администратор
Сообщения
1 575
Репутация
335
Kaster [?]
в формате bmp? вес файла будет определяться исключительно его размерами. то есть красный квадрат 4х4 будет весить столько же сколько и синий квадрат 4х4. но идентичны ли они?
А еще от глубины цвета :smile:
 

FlatX007

Tattoo!
Сообщения
197
Репутация
35
Kaster - а как можно узнать процент выполнения операции при подсчёте md5, другими словами прогресс бар можно замутить ?
 

Belfigor

Модератор
Локальный модератор
Сообщения
3 595
Репутация
938
FlatX007 сказал(а):
Kaster - а как можно узнать процент выполнения операции при подсчёте md5, другими словами прогресс бар можно замутить ?
В автоите нет, ну разве что если что-то с эдлибрегистр замутить, а так, пока у тебя будет читаться файл - скрипт будет стоять на месте без эдлиба. Да и даже с эдлибом, я конечно им не пользуюсь но сомневаюсь что можно узнать статус выполнения другой функции если в ней не включена возможность об отчете о том что она делает до того момента как она отработает. Но для такого варианта и файл должен читаться по кускам.
 

FlatX007

Tattoo!
Сообщения
197
Репутация
35
Ничего не понял :whistle:, особено крутая фраза :
...что можно узнать статус выполнения другой функции если в ней не включена возможность об отчете о том что она делает до того момента как она отработает
 

Belfigor

Модератор
Локальный модератор
Сообщения
3 595
Репутация
938
Ну то есть суть в том, что если функция в переменную возвращает только результат по окончанию отработки и во время работы не возвращает какую-то промежуточную информацию которую можно будет использовать для визуального отображения в прогресс баре, твой прогресс бар никогда не сдвинется с места ибо у него будет только два положения 0% и 100%
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
FlatX007
я не знаю такого способа, чесгря
 

madmasles

Модератор
Глобальный модератор
Сообщения
7 790
Репутация
2 319
FlatX007
прогресс бар можно замутить ?
Попробуйте так, у меня работает:
Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <ListboxConstants.au3>
#include <ButtonConstants.au3>
#include <StaticConstants.au3>
#include <EditConstants.au3>
#include <GUIMenu.au3>

Opt("TrayMenuMode", 1)

Global $message = "Выберите файл для измерения хеш-сумм."

$Form1 = GUICreate("Контрольные суммы файлов.", 420, 110, -1, -1, -1, $WS_EX_ACCEPTFILES)
GUISetBkColor(0xFFFFCC)
$List1 = GUICtrlCreateInput("", 5, 2, 375, 22, BitOR($GUI_SS_DEFAULT_INPUT, $ES_LEFT, $ES_READONLY))
GUICtrlSetState(-1, $GUI_DROPACCEPTED)
GUICtrlSetFont(-1, 8.5, 400, 0, "Tahoma")
GUICtrlSetTip(-1, "Перетащите сюда файл." & @CRLF & "или кликните по кнопке справа.")
$Button1 = GUICtrlCreateButton("...", 385, 1, 30, 24)
GUICtrlSetTip(-1, "Выбрать файл.")
GUICtrlSetFont(-1, 9, 700, 0, "Tahoma")
$Button2 = GUICtrlCreateButton("Очистить", 5, 27, 80, 25)
GUICtrlSetTip(-1, "Очистить строку выбора файла.")
GUICtrlSetFont(-1, 9, 700, 0, "Tahoma")
$Button3 = GUICtrlCreateButton("Вычислить", 180, 27, 80, 25)
GUICtrlSetTip(-1, "Вычислить контрольную сумму файла.")
GUICtrlSetFont(-1, 9, 700, 0, "Tahoma")
$Combo1 = GUICtrlCreateCombo("MD5", 360, 27, 55, 25)
GUICtrlSetFont(-1, 8.5, 700, 0, "Tahoma")
GUICtrlSetData(-1, "MD2|MD4|SHA1", "MD5")
GUICtrlSetTip(-1, "Выберите какую контрольную" & @CRLF & "сумму файла надо вычислить.")
$Progress1 = GUICtrlCreateProgress(5, 57, 410, 22)
GUICtrlSetState(-1, $GUI_HIDE)
$Input1 = GUICtrlCreateInput("", 5, 57, 50, 22, BitOR($GUI_SS_DEFAULT_INPUT, $ES_CENTER, $ES_READONLY))
GUICtrlSetFont(-1, 9, 700, 0, "Tahoma")
GUICtrlSetState(-1, $GUI_HIDE)
$Input2 = GUICtrlCreateInput("", 60, 57, 285, 22, BitOR($GUI_SS_DEFAULT_INPUT, $ES_CENTER, $ES_READONLY))
GUICtrlSetFont(-1, 8.5, 400, 0, "Tahoma")
GUICtrlSetState(-1, $GUI_HIDE)
$Input3 = GUICtrlCreateInput("", 60, 83, 285, 22, BitOR($GUI_SS_DEFAULT_INPUT, $ES_CENTER))
GUICtrlSetFont(-1, 8.5, 400, 0, "Tahoma")
GUICtrlSetState(-1, $GUI_HIDE)
GUICtrlSetTip(-1, "Введите контрольную сумму для сравнения.")
$Button4 = GUICtrlCreateButton("Сравнить", 350, 83, 65, 23)
GUICtrlSetTip(-1, "Сравнить контрольные суммы.")
GUICtrlSetFont(-1, 8.5, 700, 0, "Tahoma")
GUICtrlSetState(-1, $GUI_HIDE)
GUISetState(@SW_SHOW)

While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit
		Case $GUI_EVENT_DROPPED
			GUICtrlSetData($List1, "")
			GUICtrlSetData($List1, @GUI_DragFile)
			If FileGetAttrib(@GUI_DragFile) = "D" Then
				ToolTip("Вы выбрали папку, а не файл.", Default, Default, "Контрольные суммы файлов.", 3, 1)
				GUICtrlSetData($List1, "")
				Sleep(2000)
				ToolTip("")
			Else
				GUICtrlSetTip($List1, @GUI_DragFile)
			EndIf
		Case $Button1
			_OpenFile()
		Case $Button2
			GUICtrlSetData($List1, "")
			GUICtrlSetData($Input1, "")
			GUICtrlSetData($Input2, "")
			GUICtrlSetData($Input3, "")
			GUICtrlSetState($Input1, $GUI_HIDE)
			GUICtrlSetState($Input2, $GUI_HIDE)
			GUICtrlSetState($Input3, $GUI_HIDE)
			GUICtrlSetState($Button4, $GUI_HIDE)
			GUICtrlSetTip($List1, "Перетащите сюда файл." & @CRLF & "или кликните по кнопке справа.")
		Case $Button3
			_Hash()
		Case $Button4
			_Compare()
	EndSwitch
WEnd

Func _OpenFile()
	Local $file
	$file = FileOpenDialog($message, @DesktopDir & "\", "Все файлы (*.*)", 1 + 2)
	If @error Then
		ToolTip("Вы не выбрали файл для вычисления.", Default, Default, "Контрольные суммы файлов.", 3, 1)
		Sleep(2000)
		Return ToolTip("")
	Else
		GUICtrlSetData($List1, "")
		GUICtrlSetData($List1, $file)
		GUICtrlSetTip($List1, $file)
	EndIf
EndFunc   ;==>_OpenFile

Func _Hash()
	Local $fileFromList1, $Percent
	GUICtrlSetData($Input1, "")
	GUICtrlSetData($Input2, "")
	GUICtrlSetData($Input3, "")
	GUICtrlSetState($Input1, $GUI_HIDE)
	GUICtrlSetState($Input2, $GUI_HIDE)
	GUICtrlSetState($Input3, $GUI_HIDE)
	GUICtrlSetState($Button1, $GUI_HIDE)
	GUICtrlSetState($Button2, $GUI_HIDE)
	GUICtrlSetState($Button3, $GUI_HIDE)
	GUICtrlSetState($Button4, $GUI_HIDE)
	GUICtrlSetState($Combo1, $GUI_HIDE)
	$hMenu = _GUICtrlMenu_GetSystemMenu($Form1)
	_GUICtrlMenu_EnableMenuItem($hMenu, $SC_CLOSE, 2)
	$algoritm = GUICtrlRead($Combo1, 1)
	$fileFromList1 = GUICtrlRead($List1, 1)
	If $fileFromList1 = "" Then
		ToolTip("Вы не выбрали файл для вычисления.", Default, Default, "Контрольные суммы файлов.", 3, 1)
		Sleep(2000)
		_GUICtrlMenu_EnableMenuItem($hMenu, $SC_CLOSE, 0)
		Return ToolTip("")
	EndIf
	GUICtrlSetState($Progress1, $GUI_SHOW)
	$files_size = Ceiling(FileGetSize($fileFromList1) / (1024 * 1024))
	If $algoritm = "MD5" Then
		$n = 3
	ElseIf $algoritm = "MD2" Then
		$n = 1
	ElseIf $algoritm = "MD4" Then
		$n = 2
	ElseIf $algoritm = "SHA1" Then
		$n = 0
	EndIf
	$HashedData = ObjCreate("CAPICOM.HashedData.1")
	$hFile = FileOpen($fileFromList1, 16)
	$HashedData.Algorithm() = $n
	$w = 0
	While 1
		$Buf = FileRead($hFile, 1024 * 1024)
		If @error = -1 Then ExitLoop
		$HashedData.Hash($Buf)
		$w += 1
		$Percent = $w * 100 / $files_size
		GUICtrlSetData($Progress1, $Percent)
		Sleep(2)
	WEnd
	FileClose($hFile)
	GUICtrlSetData($Progress1, "")
	GUICtrlSetState($Progress1, $GUI_HIDE)
	GUICtrlSetState($Input1, $GUI_SHOW)
	GUICtrlSetData($Input1, $algoritm)
	GUICtrlSetState($Input2, $GUI_SHOW)
	GUICtrlSetData($Input2, $HashedData.Value)
	GUICtrlSetState($Input3, $GUI_SHOW)
	GUICtrlSetState($Button1, $GUI_SHOW)
	GUICtrlSetState($Button2, $GUI_SHOW)
	GUICtrlSetState($Button3, $GUI_SHOW)
	GUICtrlSetState($Button4, $GUI_SHOW)
	GUICtrlSetState($Combo1, $GUI_SHOW)
	_GUICtrlMenu_EnableMenuItem($hMenu, $SC_CLOSE, 0)
EndFunc   ;==>_Hash

Func _Compare()
	$hash1 = GUICtrlRead($Input2, 1)
	$hash2 = GUICtrlRead($Input3, 1)
	If $hash2 = "" Then
		ToolTip("Вы не ввели сумму для сравнения.", Default, Default, "Контрольные суммы файлов.", 3, 1)
		Sleep(2000)
		Return ToolTip("")
	EndIf
	If $hash1 = $hash2 Then
		ToolTip("Контрольные суммы совпадают.", Default, Default, "Контрольные суммы файлов.", 1, 1)
		Sleep(2000)
		Return ToolTip("")
	Else
		ToolTip("Контрольные суммы не совпадают.", Default, Default, "Контрольные суммы файлов.", 3, 1)
		Sleep(2000)
		Return ToolTip("")
	EndIf
EndFunc   ;==>_Compare
Проверял только на Windows XP. Только сначала проверьте, есть ли у Вас в Диск:\WINDOWS\system32 capicom.dll. Если нет, то она здесь лежит. Ее надо положить в Диск:\WINDOWS\system32 и сделать Пуск-Выполнить-regsvr32 capicom.dll.
Этот способ вычисления хеш-сумм я узнал от Garrett`а.
 

AZJIO

Меценат
Меценат
Сообщения
2 752
Репутация
1 149
madmasles
Опять у меня вылетает на $HashedData.Algorithm() = $n, строка 135. Я не пойму, что за запись, переменная и функция в одном флаконе.
 
Верх