Hallo,
ich brauchte mal ein Programm, um einen "langen" Screenshot zu machen. Also einfach gesagt, um zum Beispiel eine ganze Webseite zu "screenshotten". Man kann einen Bereich auswählen, von dem 4 mal pro Sekunde ein Screenshot gemacht wird, sofern sich die Checksum geändert hat. (Eine Nutzung der Checksum ohne Bothintergrund :P) Am Ende werden die Screenshots dann zusammengesetzt.
Ich habe das ganze programmiert, bevor ich nach sowas gegooglet hab und wollte eigentlich nur schnell meinen Nutzen daraus ziehen, daher ist es leider nicht total komfortabel, aber es funktioniert. Ich hab es auch nur mit Autoit programmiert, keine ASM-Unterstützung
Wer "Toleranz" braucht, wegen bewegenden Elemten, der sollte im Code gucken, da steht wo man es machen kann. Allerdings dauert das Verfahren dann wesentlich länger und ist nicht mehr so treffsicher ..
Also, hier der Code:
Spoiler anzeigen
#NoTrayIcon
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Icon=TheShadowAE.ico
#AutoIt3Wrapper_Res_requestedExecutionLevel=asInvoker
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <GDIPlus.au3>
#include <WindowsConstants.au3>
#include <Math.au3>
#include <Misc.au3>
#include <GUIT.au3>
#include <ScreenCapture.au3>
#include "inlineASM.au3"
_ASMinit()
$asm_func=_ASMcreateFunc("_ASMcode")
ConsoleWrite("$asm_func="&$asm_func&@CRLF)
MsgBox(0,"Information","How you make a screenshot:"&@CRLF&"1. go to the right window and close this message"&@CRLF&"2. mark the area"&@CRLF&"3. scroll (down)"&@CRLF&"4. press enter")
[/autoit] [autoit][/autoit] [autoit]$gui=_CreateGUIT("BlockMark",@DesktopWidth,@DesktopHeight,0,BitOR($WS_EX_TOOLWINDOW,$WS_EX_TOPMOST))
WinMove($gui[0],"",0,0)
GUISetState(@SW_SHOW,$gui[0])
$contloop=True
Local $del=0 ;for no error
_GDIPlus_Startup()
_GDIPlus_GraphicsClear($gui[5],0x01000000)
_DrawonGUIT($gui)
While $contloop
Local $coords[4]=[-1,-1,-1,-1]
Switch GUIGetMsg()
Case $GUI_EVENT_CLOSE
$contloop=False
EndSwitch
If _IsPressed("1") Then
$pos=MouseGetPos()
$coords[0]=$pos[0]
$coords[1]=$pos[1]
While _IsPressed("1")
_GDIPlus_GraphicsClear($gui[5],0x01000000)
$pos=MouseGetPos()
Local $rect[4]=[$coords[0],$coords[1],$pos[0],$pos[1]]
_adjust($rect)
_GDIPlus_GraphicsDrawRect($gui[5],$rect[0],$rect[1],$rect[2]-$rect[0],$rect[3]-$rect[1])
_DrawonGUIT($gui)
Sleep(10)
WEnd
$pos=MouseGetPos()
$coords[2]=$pos[0]
$coords[3]=$pos[1]
_adjust($coords)
_GDIPlus_GraphicsClear($gui[5],0x00000000)
_GDIPlus_GraphicsDrawRect($gui[5],$coords[0]-1,$coords[1]-1,$coords[2]-$coords[0]+2,$coords[3]-$coords[1]+2)
_DrawonGUIT($gui)
$timer=TimerInit()
$diff=TimerDiff($timer)-250
$i=0
$pixelsum=0
While Not _IsPressed("0D")
If TimerDiff($timer)>$diff+250 Then
$diff=TimerDiff($timer)
$pxsum=PixelChecksum($coords[0],$coords[1],$coords[2],$coords[3],2)
If $pixelsum=0 Or $pixelsum<>$pxsum Then
$pixelsum=$pxsum
$file=@TempDir&"\scrollscreen_"&$i&".png"
FileDelete($file)
_ScreenCapture_Capture($file,$coords[0],$coords[1],$coords[2],$coords[3],False)
$i+=1
EndIf
EndIf
Sleep(10)
WEnd
GUISetState(@SW_HIDE,$gui[0])
;Bilder zusammenfügen
ProgressOn("In Progress..","cutting screenshots togehter","1/"&($i),Default,Default,16) ;+2 = not on top
ConsoleWrite("Start!"&@CRLF&@CRLF)
$completeImage=_GDIPlus_BitmapCreateFromFile(@TempDir&"\scrollscreen_0.png")
ConsoleWrite("$completeImage="&$completeImage&@CRLF)
$w=$coords[2]-$coords[0]+1
$h=$coords[3]-$coords[1]+1
ConsoleWrite("$w="&$w&@CRLF)
ConsoleWrite("$h="&$h&@CRLF)
$comph=$h
For $x=1 To $i-1
ProgressSet(($x+1)/$i*100,($x+1)&"/"&$i)
ConsoleWrite("Progress: "&($x+1)&"/"&$i&@CRLF)
Local $nextIMG=_GDIPlus_BitmapCreateFromFile(@TempDir&"\scrollscreen_"&$x&".png")
ConsoleWrite("$nextIMG="&$nextIMG&@CRLF)
Local $lock1=_GDIPlus_BitmapLockBits($completeImage,0,$comph-$h,$w,$h,$GDIP_ILMREAD,$GDIP_PXF32ARGB)
ConsoleWrite("$lock1="&IsDllStruct($lock1)&", @error is "&@error&@CRLF)
ConsoleWrite("Scan0: "&DllStructGetData($lock1,"Scan0")&@CRLF)
Local $lock2=_GDIPlus_BitmapLockBits($nextIMG,0,0,$w,$h,$GDIP_ILMREAD,$GDIP_PXF32ARGB)
ConsoleWrite("$lock2="&IsDllStruct($lock2)&", @error is "&@error&@CRLF)
ConsoleWrite("Scan0: "&DllStructGetData($lock2,"Scan0")&@CRLF)
Local $s1=DllStructCreate("dword["&($w*$h)&"]",DllStructGetData($lock1,"Scan0"))
Local $s2=DllStructCreate("dword["&($w*$h)&"]",DllStructGetData($lock2,"Scan0"))
Local $concaty=_GetImageInImageY_ASM($w,$h,$s1,$s2)
_GDIPlus_BitmapUnlockBits($completeImage,$lock1)
_GDIPlus_BitmapUnlockBits($nextIMG,$lock2)
If $concaty>=1 Then
$newIMG=_GDIPlus_BitmapCreateFromGraphics($w,$comph+$concaty,$gui[5])
ConsoleWrite("$newIMG="&$newIMG&@CRLF)
ConsoleWrite("Height: "&_GDIPlus_ImageGetHeight($newIMG)&@CRLF)
$gra=_GDIPlus_ImageGetGraphicsContext($newIMG)
ConsoleWrite("$gra="&$gra&@CRLF)
_GDIPlus_GraphicsClear($gra) ;for safety
_GDIPlus_GraphicsDrawImageRect($gra,$completeImage,0,0,$w,$comph)
_GDIPlus_GraphicsDrawImageRect($gra,$nextIMG,0,$comph-$h+$concaty,$w,$h)
_GDIPlus_GraphicsDispose($gra)
$comph+=$concaty
_GDIPlus_BitmapDispose($completeImage)
$completeImage=$newIMG
ConsoleWrite("$completeImage="&$completeImage&@CRLF)
EndIf
_GDIPlus_BitmapDispose($nextIMG)
$del=FileDelete(@TempDir&"\scrollscreen_"&$x&".png")
If $del Then ConsoleWrite("Deleted: "&"scrollscreen_"&$x&".png"&@CRLF)
ConsoleWrite(@CRLF)
Next
ProgressOff()
$del=FileDelete(@TempDir&"\scrollscreen_0.png")
If $del Then ConsoleWrite("Deleted: "&"scrollscreen_0.png"&@CRLF)
ConsoleWrite("Finished!"&@CRLF)
;Speichern
$path=FileSaveDialog("Save the Screenshot","","PNG (*.png)|Images (*.png;*.jpg;*.jpeg;*.bmp)|All (*.*)",18,"screenshot.png")
ConsoleWrite("Path: "&$path&"; @error="&@error&@CRLF)
If Not @error Then _GDIPlus_ImageSaveToFile($completeImage,$path)
_GDIPlus_BitmapDispose($completeImage)
$contloop=False
;~ GUISetState(@SW_SHOW,$gui[0])
EndIf
Sleep(10)
WEnd
_DeleteGUIT($gui)
_GDIPlus_Shutdown()
Exit
Func _GetImageInImageY($w,$h,$s1,$s2)
ConsoleWrite("---_GetImageInImageY---"&@CRLF)
Local $line=-1
For $i=0 To $h-1
Local $trifft=0, $min=Ceiling(($h-$i)*$w*1) ;*0.8=tolerance factor (1=no tolerance) (for smiley movement etc.)
For $y=$i To $h-1
For $x=0 To $w-1
Local $p1,$p2
$p1=DllStructGetData($s1,1,$y*$w+$x+1)
$p2=DllStructGetData($s2,1,($y-$i)*$w+$x+1)
If $p1=$p2 Then
$trifft+=1
If $trifft=$min Then ExitLoop 2
Else
Local $pixleft=($h-$y)*$w-$x-1
If $pixleft<($min-$trifft) Then ExitLoop 2
EndIf
Next
Next
;~ ConsoleWrite("$i="&$i&"; "&$trifft&"/"&$min&@CRLF)
If $trifft=$min Then
$line=$i
ExitLoop
EndIf
Next
ConsoleWrite("Return: "&$line&@CRLF)
ConsoleWrite("-----------------------"&@CRLF)
Return $line
EndFunc
Func _GetImageInImageY_ASM($w,$h,$s1,$s2)
ConsoleWrite("---_GetImageInImageY_ASM---"&@CRLF)
Local $p1=DllStructGetPtr($s1),$p2=DllStructGetPtr($s2)
Local $ret=DllCallAddress("int",$asm_func,"int",$w,"int",$h,"ptr",$p1,"ptr",$p2)
ConsoleWrite("Return: "&$ret[0]&@CRLF)
ConsoleWrite("---------------------------"&@CRLF)
Return $ret[0]
EndFunc
Func _ASMcode()
_("finit")
_("mov ebx,[esp+4]") ;w
_("mov edx,[esp+8]") ;h
_("mov esi,[esp+12]") ;p1
_("mov edi,[esp+16]") ;p2
_("xor eax,eax") ;
_("loop_i:") ;
_(" movd xmm0,eax ;i") ;
_(" mov ecx,edx") ;
_(" sub ecx,eax") ;
_(" imul ecx,ebx") ;
;hier toleranz (ecx*0.8)
_(" movd xmm1,ecx") ;min
_(" xor eax,eax") ;
_(" movd xmm2,eax") ;trifft
_(" movdqa xmm3,xmm0") ;y=i
_(" loop_y:") ;
_(" xor ecx,ecx") ;
_(" loop_x:") ;
_(" movd xmm4,ecx") ;x
_(" lodsd") ;
_(" cmp eax,[edi]") ;
_(" jne @f") ;
;pixel=pixel
_(" movd eax,xmm2") ;
_(" inc eax") ;
_(" movd xmm2,eax") ;
_(" movd ecx,xmm1") ;
_(" cmp eax,ecx") ;
_(" je _return") ;
_(" jmp .weiter") ;
_(" @@:") ;pixel!=pixel
_(" mov eax,edx") ;
_(" movd ecx,xmm3") ;
_(" sub eax,ecx") ;
_(" imul eax,ebx") ;
_(" movd ecx,xmm4") ;
_(" sub eax,ecx") ;
_(" dec eax") ;
_(" movd xmm7,eax") ;temp
_(" movd ecx,xmm1") ;
_(" movd eax,xmm2") ;
_(" sub ecx,eax") ;
_(" movd eax,xmm7") ;
_(" cmp eax,ecx") ;
_(" jb _next") ;
_(" .weiter:") ;
_(" add edi,4") ;
_(" movd ecx,xmm4") ;
_(" inc ecx") ;
_(" cmp ecx,ebx") ;
_(" jb loop_x") ;
_(" movd ecx,xmm3") ;
_(" inc ecx") ;
_(" movd xmm3,ecx") ;
_(" cmp ecx,edx") ;
_(" jb loop_y") ;
_(" _next:") ;
_(" movd eax,xmm0") ;
_(" inc eax") ;
_(" mov esi,[esp+12]") ;
_(" mov edi,[esp+16]") ;
_(" mov ecx,eax") ;
_(" imul ecx,ebx") ;
_(" shl ecx,2") ;
_(" add esi,ecx") ;
_(" cmp eax,edx") ;
_("jb loop_i") ;
_("_return:") ;
_("movd eax,xmm0") ;
_("movd ecx,xmm1") ;
_("movd ebx,xmm2") ;
_("cmp ebx,ecx") ;
_("jne @f") ;
_("ret 16") ;
_("@@:") ;
_("mov eax,-1") ;
_("ret 16") ;
EndFunc
Func _adjust(ByRef $rect)
Local $new[4]=[_Min($rect[0],$rect[2]),_Min($rect[1],$rect[3]),_Max($rect[0],$rect[2]),_Max($rect[1],$rect[3])]
$rect=$new
Return $rect
EndFunc
So, im Anhang ein Beispiel für ein Erzeugnis und die Zip, die Code, Exe und Icon beinhaltet.
Hoffentlich nützt es jemandem
mfg
EDIT:
Neue Version jetzt doch ASM-powered. Ist alles angenehm schnell jetzt