CodeMaster Rapture Posted February 27, 2007 Posted February 27, 2007 Nice little library... if I could get it to work... Opt("ColorMode", 1) Local $sz_BMP = @ScriptDir & "\Checksum_" & $cs_Current & ".bmp" If (Not FileExists($sz_BMP)) Then Local $BMP = _BMPCreate(13,13) For $iterX = $X To $X+13 For $iterY = $Y To $Y+13 _PixelWrite($BMP,$X,$Y,PixelGetColor($iterX,$iterY)) Next Next _BMPWrite($BMP,$sz_BMP) EndIf Opt("ColorMode", 0) Basically, I have a PixelChecksum from earlier in my script and then if it is an unknown one, I want it to create a BMP of that area (13x13 icon) so I can look at it later. Only problem is, all the BMPs I create are all white. Help? Thanx, -CMR
vitor Posted March 27, 2007 Posted March 27, 2007 it takes a LOT of time to open a file from the size of the screen (like a bitmap 1024x768). Is there a new version of your library ? Is there any way to improve that performace ? Thx and congratulations for the nice library !
PaulIA Posted March 27, 2007 Posted March 27, 2007 it takes a LOT of time to open a file from the size of the screen (like a bitmap 1024x768). Is there a new version of your library ?Is there any way to improve that performace ?Thx and congratulations for the nice library !You might try the ScreenCap module from Auto3Lib. It can capture any portion of the screen, does not require a DLL and can do a full screen capture in milliseconds. Auto3Lib: A library of over 1200 functions for AutoIt
vitor Posted March 28, 2007 Posted March 28, 2007 You might try the ScreenCap module from Auto3Lib. It can capture any portion of the screen, does not require a DLL and can do a full screen capture in milliseconds.The problem is not capturing. Capturing I can do fine with a DLLcall, its fast. The problem is opening and reading the bmp file saved from that screenshot.
Kilhian Posted February 24, 2008 Posted February 24, 2008 Does this library still supported ?because it seems that _BMPWrite($BMPHandle,$Fpath[,$Progress]) is bugged...@error =0
evilertoaster Posted February 26, 2008 Author Posted February 26, 2008 Humm, I havn't worked on this much at all recently. In all honesty I thought it would have become obsolete by now, but I'm glad too se it's getting some use still with the alternitves available. I'll look at it today and see if i need to change anything since its last release.
Kilhian Posted February 26, 2008 Posted February 26, 2008 I'll look at it today and see if i need to change anything since its last release.thanks
evilertoaster Posted February 26, 2008 Author Posted February 26, 2008 I've updated the _BMPWrite function to work correctly with the differnt way autoit handles binary files since it was created. At some point now I can probably go back and make a few speed tweaks to it since I don't think I'll have to manually parse out my strings into binary data now which could help with loading and writing times.
evilertoaster Posted March 4, 2008 Author Posted March 4, 2008 At some point now I can probably go back and make a few speed tweaks to it since I don't think I'll have to manually parse out my strings into binary data now which could help with loading and writing times.Done now. See first post.
Uriziel01 Posted March 5, 2008 Posted March 5, 2008 (edited) Why in this 2.0 BMPOpen create me an array contains only the high and wight of picture ?? 1.9 was returning array with all pixels in it. this is my code: #include "BMP2.au3" #include <array.au3> global $string,$string1,$string2a,$sr1,$sr2,$sr3,$string3 $plik="" do $plik=FileOpenDialog("Wybierz plik",@MyDocumentsDir,"Images (*.bmp)", 1 + 2) until $plik<>"" $BMP=_BMPOpen($plik,1) _ArrayDisplay($BMP,"BMP") FileDelete(@ScriptDir&"\MyBMP.bmp") _BMPWrite($BMP,@ScriptDir & "\MyBMP.bmp");Closes the BMP to a file GUICreate("BMP Example",_BMPGetWidth($BMP)+100, _BMPGetHeight($BMP)+100) GUICtrlCreatePic(@ScriptDir & "\MyBMP.bmp", 58, 10, _BMPGetWidth($BMP), _BMPGetHeight($BMP)) GUISetState() Do $msg = GUIGetMsg() Until $msg = -3;$GUI_EVENT_CLOSE How can I obtain array with all pixels ? Edited March 5, 2008 by Uriziel01
evilertoaster Posted March 5, 2008 Author Posted March 5, 2008 How can I obtain array with all pixels ?The bitmap is stored differently. But you should not have to access the array directly... The binary data is stored in $BMPHandle[3] if that helps... but like it said the whole point of the library is you wouldn't have to work with this data yourself. As far as your code goes--- you have FileOpen($plik,1), but you can't do this in 2.0 becuase the progress bar 'feature' was removed. The BMP opening happens almost instantly so there's no need for a progress bar.
Andreik Posted November 1, 2009 Posted November 1, 2009 (edited) Somewhere is a bug. Check this BMPs overlay example: the result picture contain some colors that isn't in nor pictures.Download example Edited November 1, 2009 by Andreik
Zedna Posted November 1, 2009 Posted November 1, 2009 I have an idea for speed improvement without any BIG rewites especially in _PixelWrite() Princip would be in storing binary data in structure of bytes instead of one big string of binary data. _PixelWrite(): ... $struct = DllStructCreate('byte['&BinaryLen($BMPHandle[3])&']', $BMPHandle[3]) DllStructSetData($struct, $index, $data) ... Original is very inefficient Func _PixelWrite(ByRef $BMPHandle,$x,$y,$color) If $x>$BMPHandle[1]-1 Or $x<0 Or $y>$BMPHandle[2]-1 Or $y<0 or StringLen($color)<>6 or Dec($Color)=0 Then Return 0 $color = _Reverse6($Color) $BMPHandle[3]=BinaryMid($BMPHandle[3],1,_ChordToOffset($x,$y,$BMPHandle))&Binary("0x"&$color)&BinaryMid($BMPHandle[3],_ChordToOffset($x,$y,$BMPHandle)+4) Return 1 EndFunc Maybe such structure can also stored in $BMPHandle[3] instead of Binary string ... Resources UDF ResourcesEx UDF AutoIt Forum Search
evilertoaster Posted November 2, 2009 Author Posted November 2, 2009 Somewhere is a bug. Check this BMPs overlay example: the result picture contain some colors that isn't in nor pictures. Download example Try the new one (see first page). Also your GBR2RGB() function probably won't be needed as it seemed to be a workaround to a larger problem. All the colors should be in RBG() format already. And lastly I thought I'd note: For $I = 0 To $X For $J = 0 To $Y The heights and widths start at 0. For example: (0,0) is the first pixel, not (1,1) as was in your code (not that it matters in this case)
evilertoaster Posted November 2, 2009 Author Posted November 2, 2009 I have an idea for speed improvement without any BIG rewites especially in _PixelWrite() _PixelWrite(): ... $struct = DllStructCreate('byte['&BinaryLen($BMPHandle[3])&']', $BMPHandle[3]) DllStructSetData($struct, $index, $data) Original is very inefficient Maybe such structure can also stored in $BMPHandle[3] instead of Binary string ... Indeed the largest problem with _PixelWrite() is it doesn't scale well with large bitmaps since it has to copy the whole thing every time a pixel is written. No question it's faster, but now that I'm back here looking... I wounder what would be faster...using DllStructSetData or creating an native array of binarystrings. Well, something I'll probably check out sometime when I can. (or hopefully someone else does it before then )
AndyG Posted November 2, 2009 Posted November 2, 2009 (edited) I wounder what would be faster...using DllStructSetData or creating an native array of binarystrings.The question is, what do you mean with "faster"? Arrayfunctions are slow by nature and there is no reason to use them in this case. If you have the Bitmapdata in a struct, you could use not only the DllStructSetData but also something like external dll´s (prospeed i.e.) to work with the bitmap . An other idea is to work with stringreplace instead of $string=stringleft()+$partofstring+stringright. Simple Example 5 times faster:expandcollapse popup#include <Array.au3> #include <bmp.au3> $MAIN = GUICreate("BMP Overlay",320,135) $PIC1 = GUICtrlCreatePic("",5,5,100,100,0x1000) $PIC2 = GUICtrlCreatePic("",110,5,100,100,0x1000) $PIC3 = GUICtrlCreatePic("",215,5,100,100,0x1000) $LOAD1 = GUICtrlCreateButton("Load",5,110,100,20) $LOAD2 = GUICtrlCreateButton("Load",110,110,100,20) $OVERLAY = GUICtrlCreateButton("Overlay",215,110,100,20) GUISetState() While True $MSG = GUIGetMsg() Switch $MSG Case $LOAD1 $PATH1 = FileOpenDialog("Load",@ScriptDir,"Bitmap (*.bmp)",1) If Not @error Then GUICtrlSetImage($PIC1,$PATH1) Case $LOAD2 $PATH2 = FileOpenDialog("Load",@ScriptDir,"Bitmap (*.bmp)",1) If Not @error Then GUICtrlSetImage($PIC2,$PATH2) Case $OVERLAY $t=timerinit() $BITMAP1 = _BMPOpen($PATH1,True) $BITMAP2 = _BMPOpen($PATH2,True) $X = _BMPGetWidth($BITMAP1) $Y = _BMPGetHeight($BITMAP1) $PROGRESS = ProgressOn("Overlay BMPs","Overlay...") For $I = 1 To $X For $J = 1 To $Y $PIXEL = _PixelRead($BITMAP2,$I,$J) If $PIXEL <> "FFFFFF" Then _PixelWrite($BITMAP1,$I,$J,GBR2RGB($PIXEL)) ;ProgressSet($I*100/$X,"Offset: " & $I & "x" & $J) ; not a good position Next ;ProgressSet($I*100/$X,"Offset: " & $I & "x" & $J) ;saves half the time and looks the same :o) Next ProgressOff() _BMPWrite($BITMAP1,@ScriptDir & "\mybitmap.bmp",True) GUICtrlSetImage($PIC3,@ScriptDir & "\mybitmap.bmp") $m=timerdiff($t) msgbox(0,"Time old version",$m) $t=timerinit() _overlay($path1,$path2) GUICtrlSetImage($PIC3,@ScriptDir & "\overlay.bmp") $m=timerdiff($t) msgbox(0,"Time function version",$m) Case -3 Exit EndSwitch Sleep(10) WEnd Func GBR2RGB($COLOR) Return StringRight($COLOR,2) & StringLeft($COLOR,2) & StringMid($COLOR,3,2) EndFunc func _overlay($bitmapfile1,$bitmapfile2,$ovlcolor="0xFFFFFF") ;Color in BGR !!! local $data1=fileread($bitmapfile1) ;open bitmapfiles local $data2=fileread($bitmapfile2) local $bmp2=StringTrimLeft($data2,54) ;"raw" bitmapdata of file #2 local $bmp2data=_bmpopen($bitmapfile2) ;get width and height of bitmap local $width = _BMPGetWidth($bmp2data) local $height = _BMPGetHeight($bmp2data) local $fillbytes=$bmp2data[0] ;number of fillbytes at end of each line local $ovlcol=binarytostring($ovlcolor) ;Overlaycolor for $i= 0 to $height-1 ;rows for $c=1 to $width*3 step 3 ;each pixel in the row $pixel=stringmid($bmp2,$i*(($width*3)+$fillbytes)+$c,3) if $pixel<>$ovlcol Then ;if pixelcolor<>overlaycolor then ;consolewrite($i&" "&($c-1)/3&@crlf) $data1=stringreplace($data1,54+$i*(($width*3)+$fillbytes)+$c,$pixel) ;replace pixel in the data of file #1 endif next next $filehandle=fileopen("overlay.bmp",18) filewrite($filehandle,$data1) fileclose($filehandle) endfunc And have a look at the comments of the position of the ProgressSet(). Andy Edited November 2, 2009 by AndyG
Andreik Posted November 2, 2009 Posted November 2, 2009 I know about ProgressSet but I put this line inside of second loop to get real value of $J. But you are right is not important because is fast.
evilertoaster Posted November 2, 2009 Author Posted November 2, 2009 The question is, what do you mean with "faster"?To me, faster means taking less time to execute... That is, would it be faster (per function call) to use the structs like Zenda mentioned or would it be faster to break the binary stream into an array of 3byte chunks so that when you write a pixel you could simply say- $bitmap[$someOffset]=0xDDFFBB. Arrayfunctions are slow by nature and there is no reason to use them in this caseWell, slow relative to what? stringmid (or binarymid) isn't very fast on large streams of data either. It may be the 'lesser of 2 evils' but one of them will probably be faster than the other. but also something like external dll´s (prospeed i.e.) to work with the bitmapThe whole point of this library is to have native (no external dll) support for bitmaps. It's debatably silly to do in a scripting language that CAN use external dlls, but that's what it is. An other idea is to work with stringreplace instead of $string=stringleft()+$partofstring+stringrightDo stringleft and stringright work on binary data? there is no BinaryLeft() or BinaryRight() so my option was only BinaryMid(). Either way, the method you describe there is really what's already being done (to my knowledge). @Andreik: No news = good news then? (is it working?)
Malkey Posted November 3, 2009 Posted November 3, 2009 evilertoaster While playing around with your "draw lines on bitmap" example, and seeing what was possible, I discovered it is possible to draw lines on a bitmap with StringRegExpReplace. If both BmpCreates are bumped up to 640,640 , the difference in creation times is more apparent. I am posting this here to share as a proof of concept (or, amazed that it worked). expandcollapse popup; ;#include <Array.au3> ;#include "BMP.au3" ; http://www.autoitscript.com/forum/index.php?showtopic=27362&view=findpost&p=742082 _SetCursor(@WindowsDir & "\cursors\hourglas.ani", 32512) ; Set cursor to hour-glass. $BMP = _BMPCreate(64, 64) ;Create BMP Handle with dimensions 64X64 $BMP = _BMPCreateMod(64, 64) ;Create BMP Handle with dimensions 64X64 Local $Header = StringLeft($BMP[3], 110); 110 = "0x" + 54bytes Local $sImageData = StringTrimLeft($BMP[3], 110) $sImageDataMod1 = StringRegExpReplace($sImageData, "(.{6})", "\1 ") ;All image to pale blue Local $sImageDataMod2 = StringRegExpReplace($sImageDataMod1, "(.{2})(.{2})(.{2}) ", "${1}${2}D0 ") ; Red diagonal top-right to bottom-left Local $sImageDataMod3 = StringRegExpReplace($sImageDataMod2, "((.{6} ){" & $BMP[2] & "})", "${1} 0000FF ") ;Black vertical center line. Local $sImageDataMod4 = StringRegExpReplace($sImageDataMod3, "(.{" & (($BMP[1] / 2 - 1) * 7) & "})(.{6} )(.{" & ($BMP[1] * 7 / 2) & "})", "${1} 000000 ${3} ") ; ;Create replacement (yellow horizontal coloured) line. Local $SlINE = StringRegExpReplace(StringFormat("%" & $BMP[1] & "s", " "), ".", "00FFFF") ;Separate each line of bitmap with space Local $sImageDataModLines = StringRegExpReplace(StringStripWS($sImageDataMod4, 8), "(.{" & (($BMP[1]) * 6) & "})", "\1 ") Local $aLines = StringSplit($sImageDataModLines, " "), $sImageDataMod, $sL; Split on space ;_ArrayDisplay($aLines) $aLines[Int($aLines[0] / 2)] = $SlINE ; yellow horizontal center line. For $i = 1 To UBound($aLines) - 1 ;Green diagonal top-left to bottom-right $sL = StringRegExpReplace($aLines[$i], "(.{6})", "\1 ") $sImageDataMod &= StringStripWS(StringRegExpReplace($sL, "((?:.{6} ){" & (UBound($aLines) - 3 - $i) & "})(.{6} )((?:.{6} ){" & ($i - 1) & "})", "${1} 00FF00 \3"), 8) Next $BMP[3] = $Header & StringStripWS($sImageDataMod, 8) _BMPWrite($BMP, @ScriptDir & "\MyBMP.bmp");Closes the BMP to a file GUICreate("BMP Example", $BMP[1] + 20, $BMP[2] + 20) GUICtrlCreatePic(@ScriptDir & "\MyBMP.bmp", 10, 10, $BMP[1], $BMP[2]) GUISetState() ;http://www.autoitscript.com/forum/index.php?showtopic=25898&view=findpost&p=676920 DllCall("user32.dll", "int", "SystemParametersInfo", "int", 0x57, "int", 0, "int", 0, "int", 0); Reset Cursor Do $msg = GUIGetMsg() Until $msg = -3;$GUI_EVENT_CLOSE Func _BMPCreateMod($Width, $Height) $begin = TimerInit() Local $rowData, $imageData ;***BMP header (54bytes total)*** Local $Header = "0x424D00000000000000003600000028000000" & _ _Reverse8(Hex($Width, 8)) & _ ;4bytes, bitmap width _Reverse8(Hex($Height, 8)) & _ ;4bytes, bitmap hieght "0100180000000000" & _ _Reverse8(Hex(($Height) * ($Width) * 3 + ($Height * Mod($Width, 4)), 8)) & _ ;4bytes, bitmap data size "00000000000000000000000000000000" $rowData = StringRegExpReplace(StringFormat("%" & $Width & "s", " "), ".", "FFFFFF") $imageData = StringRegExpReplace(StringFormat("%" & $Height & "s", " "), ".", $rowData) ;ConsoleWrite($imageData & @CRLF) Local $BMPHandle[4] = [Mod($Width, 4), $Width, $Height, $Header & $imageData] ConsoleWrite("_BMPCreateMod " & TimerDiff($begin) & @CRLF) Return $BMPHandle EndFunc ;==>_BMPCreateMod ;Copied from BMP.au3 file - ADDED TIMER Func _BMPCreate($Width, $Height) $begin = TimerInit() Local $c = Mod($Width, 4) Local $d = Binary("") If $c = 3 Then $d = Binary("0x000000") If $c = 2 Then $d = Binary("0x0000") If $c = 1 Then $d = Binary("0x00") ;***BMP header (54bytes total)*** Local $Header = Binary("0x424D" & _ ;2bytes, BM signature "00000000" & _ ;4bytes, filesize (optional, omitted) "0000" & _ ;2bytes, reserved "0000" & _ ;2bytes, reserved "36000000" & _ ;4bytes, offset to image data "28000000" & _ ;4bytes, BITMAPINFOHEADER _Reverse8(Hex($Width, 8)) & _ ;4bytes, bitmap width _Reverse8(Hex($Height, 8)) & _ ;4bytes, bitmap hieght "0100" & _ ;2bytes, bitmap planes "1800" & _ ;2bytes, bitmap bitdepth "00000000" & _ ;4bytes, bitmap compression type (none) _Reverse8(Hex(($Height) * _ ($Width) * 3 + ($Height * $c), 8)) & _ ;4bytes, bitmap data size "00000000" & _ ;4bytes, bitmap horizontal resolution (optional,omitted) "00000000" & _ ;4bytes, bitmap vertical resolution (optional,omitted) "00000000" & _ ;4bytes, bitmap colors (optional?, omitted) "00000000") ;4bytes, important colors (optional?, omitted) ;***End Header*** Local $rowData = Binary("") Local $imageData = Binary("") For $n = 1 To $Width $rowData &= Binary("0xFFFFFF") Next $rowData &= $d For $m = 1 To $Height $imageData &= $rowData Next Local $BMPHandle[4] $BMPHandle[0] = $c $BMPHandle[1] = $Width $BMPHandle[2] = $Height $BMPHandle[3] = $Header & $imageData ConsoleWrite("_BMPCreate " & TimerDiff($begin) & @CRLF) Return $BMPHandle EndFunc ;==>_BMPCreate ;Copied from BMP.au3 file Func _Reverse8($inHex) Return StringMid($inHex, 7, 2) & StringMid($inHex, 5, 2) & StringMid($inHex, 3, 2) & StringMid($inHex, 1, 2) EndFunc ;==>_Reverse8 ;Copied from BMP.au3 file Func _BMPWrite(ByRef $BMPHandle, $Fpath, $Progress = 1) If IsArray($BMPHandle) = False Then Return 0 $out = FileOpen($Fpath, 18) If $out = -1 Then Return -1 FileWrite($out, $BMPHandle[3]) FileClose($out) Return 1 EndFunc ;==>_BMPWrite ;================================================================== ; http://www.autoitscript.com/forum/index.php?showtopic=25898&view=findpost&p=182505 ; $s_file - file to load cursor from ; $i_cursor - system cursor to change ;================================================================== Func _SetCursor($s_file, $i_cursor) Local $newhcurs, $lResult $newhcurs = DllCall("user32.dll", "int", "LoadCursorFromFile", "str", $s_file) If Not @error Then $lResult = DllCall("user32.dll", "int", "SetSystemCursor", "int", $newhcurs[0], "int", $i_cursor) If Not @error Then $lResult = DllCall("user32.dll", "int", "DestroyCursor", "int", $newhcurs[0]) Else MsgBox(0, "Error", "Failed SetSystemCursor") EndIf Else MsgBox(0, "Error", "Failed LoadCursorFromFile") EndIf EndFunc ;==>_SetCursor
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now