Ayuda con Raw Data Pixel
Publicado: 25 May 2011, 00:14
Hola foro como van a ver el tema de la imagen binaria quedo colgado por ahi, pero me segui interezando acerca de como obtener datos de un BMP.. empece investigando la funcion LockBits y vi en MSDN que era un metodo..
primera pregunta ¿en que se diferencia un metodo a una funcion?
Bueno estube dando vueltas y pude hacer andar la funcion y me devolvia una estructura... de ahi a saber como usar esos datos para sacar los datos de los colores en cada pixel no pude... vi que habia ejemplos en MSDN pero escritos en C++ y VB.NET pero no pude interpretar ninguno para pasarlos a autoit.
Luego se me dio por buscar en el foro de AutoIt y encontre la la manera de hacerlo gracias a un usuario de ahi que posteo un script que hacie exactamente eso.. en esta funcion tengo un par de dudas que luego les aclarare aver si me ayudan a entender algo(luego lo pongo con mis agregados)
Bueno a esa funcion le agregue otra para seleccionar un area y que tome una screen de la seleccion, tambien me ayudaron en el foro de AutoIt oficial... (siempre bien encaminado pero nunca pude definirlo solo ..)
Y use la funcion que habiamos echo con el proyecto de la imagen binaria para imprimir el arreglo de colores en un control grafico(no uso este metodo por lo practico sino que es para imprimir a partir de un arreglo)
tengo este script que ademas tienen unos marcadores de tiempo para chekear cuanto tarda cada etapa en realizarse...
Mi primer duda seria en esta parte
Si alguien me aclara un poco como es que esta separando toda la data para acomodarla en un arreglo se lo agradeceria..
Lo otro que era por lo que principalmente venia esta relacionado con esto anterior...
La parte que mas tarda en realizar el programa es acomodar los datos en un arreglo... ¿que metodo me proponen para evitar esto y buscar directamente un pixel de tal coordenada a partir del dato principal sin ponerlo en un arreglo?
Desde ya gracias y no tienen la obligacion de contestar, solo si les interezo el tema
EDIT: Le agregue un _arraydisplay() para que vean los resultados en una tabla
Y tambien les agrego los resultados de mi "banco de prueba" para que vean lo que tarda cada etapa del programa algunos datos no me sorprenden tanto... yo sabia que Getpixel x pixel no era la manera de hacerlo si los datos estan en memoria debe ser rapido recuperarlos..
PD: Otra cosa que voy a empezar a ver es como armar un BMP, a partir del arreglo este... aunque windows tiene funciones para hacer esto...
PD2: El Script esta en ingles porque estube trabajando con gente del foro de AutoIt en ingles...
PD3: Ojo si prueban mostrar la imagen a travez de la raw data si la imagen que tomaron es muy grande... se les puede colgar la PC.... yo todabia y hace 3 min estoy esperando los resultados de la full screen ... pero esto solo si lo que quieren es mostrarla para tomar los datos y ver el arreglo esta todo mas que bien.
primera pregunta ¿en que se diferencia un metodo a una funcion?
Bueno estube dando vueltas y pude hacer andar la funcion y me devolvia una estructura... de ahi a saber como usar esos datos para sacar los datos de los colores en cada pixel no pude... vi que habia ejemplos en MSDN pero escritos en C++ y VB.NET pero no pude interpretar ninguno para pasarlos a autoit.
Luego se me dio por buscar en el foro de AutoIt y encontre la la manera de hacerlo gracias a un usuario de ahi que posteo un script que hacie exactamente eso.. en esta funcion tengo un par de dudas que luego les aclarare aver si me ayudan a entender algo(luego lo pongo con mis agregados)
Bueno a esa funcion le agregue otra para seleccionar un area y que tome una screen de la seleccion, tambien me ayudaron en el foro de AutoIt oficial... (siempre bien encaminado pero nunca pude definirlo solo ..)
Y use la funcion que habiamos echo con el proyecto de la imagen binaria para imprimir el arreglo de colores en un control grafico(no uso este metodo por lo practico sino que es para imprimir a partir de un arreglo)
tengo este script que ademas tienen unos marcadores de tiempo para chekear cuanto tarda cada etapa en realizarse...
Código: Seleccionar todo
#include <misc.au3>
#include <WindowsConstants.au3>
#include <winapi.au3>
#include <Array.au3>
#include <GUIConstantsEx.au3>
#include <ScreenCapture.au3>
HotKeySet("{esc}", "_exit")
Global $pos
$Gui = GUICreate("selection tool", 300, 50, -1, -1)
$bnSelect = GUICtrlCreateButton("start select", 0, 0, 100, 50)
$bnShowRaw = GUICtrlCreateButton("ShowRawData", 100, 0, 100, 50)
GUICtrlSetState($bnShowRaw, $GUI_DISABLE)
$bnShowFromRD = GUICtrlCreateButton("ShowScrenfromRD", 200, 0, 100, 50)
GUICtrlSetState($bnShowFromRD, $GUI_DISABLE)
GUISetState()
While 1
$nmsg = GUIGetMsg()
Switch $nmsg
Case -3
_exit()
Case $bnSelect
$sel = _drawbox()
If IsArray($sel) Then
GUICtrlSetState($bnShowRaw, $GUI_ENABLE)
EndIf
Case $bnShowRaw
$begin1 = TimerInit()
$rawdata = _Getrawdata($sel[4])
If Not @error Then
ConsoleWrite("Time in ms to do all the work = " & TimerDiff($begin1) & @CRLF)
GUICtrlSetState($bnShowFromRD, $GUI_ENABLE)
_arraydisplay($rawdata)
EndIf
Case $bnShowFromRD
$ShowGUI = GUICreate("screen show", $sel[2], $sel[3], $sel[0], $sel[1], $WS_POPUP)
$graph = GUICtrlCreateGraphic(0, 0, $sel[2], $sel[3])
_printrawdata($rawdata, $graph)
GUISetState(@SW_SHOW, $ShowGUI)
GUICtrlSetState($graph, $GUI_SHOW)
MsgBox(0, "tip", "Press ´BackSpace´key to close Show window")
Do
Sleep(50)
Until _IsPressed("08") ; BackSpace
GUIDelete($ShowGUI)
EndSwitch
WEnd
Func _Exit()
Exit
EndFunc ;==>_Exit
Func _drawbox()
$hGui = GUICreate("selectionbox", @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, $WS_EX_TOPMOST)
GUISetBkColor(0x000000, $hGui)
WinSetTrans($hGui, "", 20)
GUISetState()
GUISetCursor(3)
$DLL = DllOpen("user32.dll")
While Not _IsPressed("01", $DLL)
$pos = MouseGetPos()
Sleep(10)
WEnd
$iX = $pos[0]
$iW = 0
$iY = $pos[1]
$iH = 0
While _IsPressed(01, $DLL)
$pos2 = MouseGetPos()
Select
Case $pos2[0] < $pos[0]
$iX = $pos2[0]
$iW = $pos[0] - $pos2[0]
Case $pos[0] < $pos2[0]
$iX = $pos[0]
$iW = $pos2[0] - $pos[0]
EndSelect
Select
Case $pos2[1] < $pos[1]
$iY = $pos2[1]
$iH = $pos[1] - $pos2[1]
Case $pos[1] < $pos2[1]
$iY = $pos[1]
$iH = $pos2[1] - $pos[1]
EndSelect
_GUICreateInvRect($hGui, $iX, $iY, $iW, $iH)
WEnd
GUIDelete($hGui)
DllClose($DLL)
$begin = TimerInit()
$hBMP = _ScreenCapture_Capture("", $iX, $iY, $iW + $iX, $iH + $iY)
ConsoleWrite("Time in ms. to take a screen from a " & $iW & "X" & $iH & " Area = " & TimerDiff($begin) & @CRLF)
Local $selectedpos[5] = [$iX, $iY, $iW, $iH, $hBMP]
Return $selectedpos
EndFunc ;==>_drawbox
Func _GUICreateInvRect($hWnd, $iX, $iY, $iW, $iH)
$hMask_1 = _WinAPI_CreateRectRgn(0, 0, @DesktopWidth, $iY)
$hMask_2 = _WinAPI_CreateRectRgn(0, 0, $iX, @DesktopHeight)
$hMask_3 = _WinAPI_CreateRectRgn($iX + $iW, 0, @DesktopWidth, @DesktopHeight)
$hMask_4 = _WinAPI_CreateRectRgn(0, $iY + $iH, @DesktopWidth, @DesktopHeight)
_WinAPI_CombineRgn($hMask_1, $hMask_1, $hMask_2, 2)
_WinAPI_CombineRgn($hMask_1, $hMask_1, $hMask_3, 2)
_WinAPI_CombineRgn($hMask_1, $hMask_1, $hMask_4, 2)
_WinAPI_DeleteObject($hMask_2)
_WinAPI_DeleteObject($hMask_3)
_WinAPI_DeleteObject($hMask_4)
_WinAPI_SetWindowRgn($hWnd, $hMask_1, 1)
EndFunc ;==>_GUICreateInvRect
Func _Getrawdata($hBMP) ; Credits to Malkey http://www.autoitscript.com/forum/index.php?app=forums&module=forums§ion=findpost&pid=718522
_GDIPlus_Startup()
$hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hBMP)
$width = _GDIPlus_ImageGetWidth($hBitmap)
$height = _GDIPlus_ImageGetHeight($hBitmap)
Local $aSize = DllCall('gdi32.dll', 'int', 'GetBitmapBits', 'ptr', $hBMP, 'int', 0, 'ptr', 0)
If Not @error Then
$tBits = DllStructCreate('byte[' & $aSize[0] & ']')
$begin = TimerInit()
DllCall('gdi32.dll', 'int', 'GetBitmapBits', 'ptr', $hBMP, 'int', $aSize[0], 'ptr', DllStructGetPtr($tBits))
$sHex = Hex(DllStructGetData($tBits, 1))
ConsoleWrite("Time in ms. to get the rawdata and save it in a variable = " & TimerDiff($begin) & @CRLF)
$begin = TimerInit()
$sHex = StringRegExpReplace($sHex, "([[:xdigit:]]{6})(FF)", "\1 ")
Local $pix[$height][$width], $aTemp
$aArr = StringRegExp($sHex, "(.{" & ($width * 7) & "})", 3)
ConsoleWrite("Time in ms to preparate the rawdata to be indexed in an array = " & TimerDiff($begin) & @CRLF)
$begin = TimerInit()
For $width = 0 To UBound($aArr) - 1
$aTemp = StringRegExp($aArr[$width] & " ", "(.{6}) ", 3)
For $height = 0 To UBound($aTemp) - 1
$pix[$width][$height] = StringRegExpReplace($aTemp[$height], "(.{2})(.{2})(.{2})", "\3\2\1") ; To RGB format
Next
Next
ConsoleWrite("Time in ms to put the entire raw in an array = " & TimerDiff($begin) & @CRLF)
Else
SetError(@error)
Return ""
EndIf
_GDIPlus_BitmapDispose($hBitmap)
_WinAPI_DeleteObject($hBMP)
_GDIPlus_Shutdown()
Return $pix
EndFunc ;==>_Getrawdata
Func _printrawdata($ArBMPRawdata, $hgraphic)
$begin = TimerInit()
For $x = 0 To UBound($ArBMPRawdata) - 1
For $y = 0 To UBound($ArBMPRawdata, 2) - 1
$color = "0x" & $ArBMPRawdata[$x][$y]
GUICtrlSetGraphic($hgraphic, $GUI_GR_COLOR, $color)
GUICtrlSetGraphic($hgraphic, $GUI_GR_PIXEL, $y, $x) ; :S
GUICtrlSetState($graph, $GUI_SHOW)
Next
Next
ConsoleWrite("Time in ms to print from the rawdata using GuictrlsetGraphics = " & TimerDiff($begin) & @CRLF)
EndFunc ;==>_printrawdata
Código: Seleccionar todo
$sHex = Hex(DllStructGetData($tBits, 1))
$sHex = StringRegExpReplace($sHex, "([[:xdigit:]]{6})(FF)", "\1 ")
Local $pix[$height][$width], $aTemp
$aArr = StringRegExp($sHex, "(.{" & ($width * 7) & "})", 3)
For $width = 0 To UBound($aArr) - 1
$aTemp = StringRegExp($aArr[$width] & " ", "(.{6}) ", 3)
For $height = 0 To UBound($aTemp) - 1
$pix[$width][$height] = StringRegExpReplace($aTemp[$height], "(.{2})(.{2})(.{2})", "\3\2\1") ; To RGB format
Next
Next
Lo otro que era por lo que principalmente venia esta relacionado con esto anterior...
La parte que mas tarda en realizar el programa es acomodar los datos en un arreglo... ¿que metodo me proponen para evitar esto y buscar directamente un pixel de tal coordenada a partir del dato principal sin ponerlo en un arreglo?
Desde ya gracias y no tienen la obligacion de contestar, solo si les interezo el tema
EDIT: Le agregue un _arraydisplay() para que vean los resultados en una tabla
Y tambien les agrego los resultados de mi "banco de prueba" para que vean lo que tarda cada etapa del programa algunos datos no me sorprenden tanto... yo sabia que Getpixel x pixel no era la manera de hacerlo si los datos estan en memoria debe ser rapido recuperarlos..
Código: Seleccionar todo
>"C:\Program Files (x86)\AutoIt3\SciTE\AutoIt3Wrapper\AutoIt3Wrapper.exe" /run /prod /ErrorStdOut /in "F:\Agustin\autoit\Foro Autoit\selection Box.au3" /autoit3dir "C:\Program Files (x86)\AutoIt3" /UserParams
+>19:15:50 Starting AutoIt3Wrapper v.2.0.1.24 Environment(Language:0C0A Keyboard:0000040A OS:WIN_7/ CPU:X64 OS:X64)
>Running AU3Check (1.54.19.0) from:C:\Program Files (x86)\AutoIt3
+>19:15:50 AU3Check ended.rc:0
>Running:(3.3.6.1):C:\Program Files (x86)\AutoIt3\autoit3_x64.exe "F:\Agustin\autoit\Foro Autoit\selection Box.au3"
Time in ms. to take a screen from a 1679X1049 Area = 169.281363649551
Time in ms. to get the rawdata and save it in a variable = 350.138662051994
Time in ms to preparate the rawdata to be indexed in an array = 6982.95608722142
Time in ms to put the entire raw in an array = 52866.9062746925
Time in ms to do all the work = 60251.2221886589
PD2: El Script esta en ingles porque estube trabajando con gente del foro de AutoIt en ingles...
PD3: Ojo si prueban mostrar la imagen a travez de la raw data si la imagen que tomaron es muy grande... se les puede colgar la PC.... yo todabia y hace 3 min estoy esperando los resultados de la full screen ... pero esto solo si lo que quieren es mostrarla para tomar los datos y ver el arreglo esta todo mas que bien.