Malkey Posted July 29, 2008 Posted July 29, 2008 For some time now I have been trying to save a multi-colored image to a file with one picked color appearing as transparent.This is my first success. It manipulates a screen capture. It 's a start.This scriptPros - This enables maniputation of all individual colors in an image. Like, able to change the alpha channel of a RGB or , change any RGB to any other ARGB (Alpha,Red,Green,Blue). Alpha channel value being the RGB degree of visibility, ranging from 0x00, invisible, to 0xFF, opaque.Cons - It is painfully slow. The only thing left I can think of to speed the process up is to remove the progress bar.If anyone knows or can think of a method that is really fast and can change at least one picked color to be transparent when saved to an image file all with AutoIt script, please tell or show. I would really like to know.expandcollapse popup#include <GuiConstantsEx.au3> #include <GDIPlus.au3> #include <ScreenCapture.au3> #include <WinAPI.au3> #include <WindowsConstants.au3> ; NomadMemory.au3 at ; http://www.autoitscript.com/forum/index.php?s=&showtopic=19329&view=findpost&p=394082 Opt('MustDeclareVars', 1) Opt("PixelCoordMode", 0) ; Array to make white transparent ;local $aColorAlpha[2] = [1, 0x00FFFFFF] ; Change Alpha value on one color ; Array to make white transparent & Red almost transparent Local $aColorAlpha[3] = [2, 0x00FFFFFF, 0x10FF0000] ; Change Alpha value on two colors ; Array to make white to slightly visible yellow ;local $aColorSwap[2][2] = [[1,0],[0xFFFFFF,0x10FFFF00]] ; Swap one color with another ; Array to make white to slightly visible yellow & Black to a fully visible red. Local $aColorSwap[3][2] = [[2, 0],[0xFFFFFF, 0x10FFFF00], _ [0x000000, 0xFFFF0000]] ; Swap two colors ; To get started - Comment and/or uncomment the above arrays and enter into command below. ;ImageColorChange($aColorAlpha, 300, 200) ; <================= START FUNCTION HERE ======= ImageColorChange($aColorSwap, 300, 200) ; <============ or HERE ShellExecute(@DesktopDir & "\TestWrite.png") ; Loop until user exits Do Sleep(10) Until GUIGetMsg() = $GUI_EVENT_CLOSE FileDelete(@DesktopDir & "\TestWrite.png") ; ========================================== ; Description - Either changes Alpha channel of one or more selected colors ; or ; Changes one or more colors to other colors. ; Input - $aColor is an array. Either single or two dimensional array. ; - Single array to change Alpha channel (transparency) ; $aColorAlpha[0] contains number of colors to be changed. ; Colors entered are in 0xAARRGGBB format where ; AA is the new required Alpha value. Range is 00 to FF. 00 is completely invisible. ; RRGGBB is the color which will have its alpha channel changed. FF0000 is Red. ; ; - Two dimensional array to swap colors. ; $aColorSwap[0][0] contains number of colors to be swapped. ; $aColorSwap[1+n][0] is the color to replace in 0xRRGGBB format. ; $aColorSwap[1+n][1] is the replacement color in 0xAARRGGBB format. ; - $iWidth & $iHeight for Width and Height of image ; Func ImageColorChange(ByRef $aColor, $iWidth = -1, $iHeight = -1) Local Const $ULW_ALPHA = 2 Local $hGUI, $hBitmap, $hGraphic, $hImage, $hGUIFake Local $width, $height, $format, $Value, $hBitmap1, $hBitmap3, $hImage2 Local $hWnd, $hDC, $pSize, $tSize, $pSource, $tSource, $pBlend, $tBlend, $Reslt Local $ReadMaterial, $sCLSID, $GuiSizeX, $GuiSizeY, $iOpacity = 255,$dat,$x,$y Local $addr,$v_Value,$v_Buffer, $stride, $Scan0, $memOpen If $iWidth = -1 Then $GuiSizeX = 600 Else $GuiSizeX = $iWidth EndIf If $iHeight = -1 Then $GuiSizeY = 500 Else $GuiSizeY = $iHeight EndIf ;MsgBox(0,"",UBound($aColor, 2)) ; Create GUI's $hGUI = GUICreate("GDI+", $GuiSizeX, $GuiSizeY, -1, -1, 0, ($WS_EX_LAYERED)) GUISetState() $hGUIFake = GUICreate("GDI+ FAKE", 600, 300, @DesktopWidth / 4, @DesktopHeight / 8) GUISetBkColor(0xFFFFB0) GUISetState() _GDIPlus_Startup() $hWnd = _WinAPI_GetDC($hGUI) $hDC = _WinAPI_CreateCompatibleDC($hWnd) $hBitmap = _WinAPI_CreateCompatibleBitmap($hWnd, $GuiSizeX, $GuiSizeY) _WinAPI_SelectObject($hDC, $hBitmap) $hGraphic = _GDIPlus_GraphicsCreateFromHDC($hDC) $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap) _GDIPlus_GraphicsClear($hGraphic, 0x00CC8040) ;$iWidth = _GDIPlus_ImageGetWidth ($hImage) ;$iHeight = _GDIPlus_ImageGetHeight ($hImage) $hBitmap3 = _ScreenCapture_Capture("", 0, 0, $GuiSizeX, $GuiSizeY, False) $hImage2 = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap3) $hBitmap1 = _GDIPlus_BitmapCloneArea($hImage2, 0, 0, $GuiSizeX, $GuiSizeY, $GDIP_PXF32ARGB) $ReadMaterial = "The bitmap image is loading." & @CRLF & @CRLF & _ "A snap shot of the top left quarter of the screen will be manipulated. " & @CRLF & _ "This window will be deleted when the colored pixels have been changed in " & @CRLF & _ "the area of memory where the bitmap is stored.On final exit, the png file " & @CRLF & _ "saved to desktop will be deleted." & @CRLF & @CRLF ProgressOn("Progress Bar", "The bitmap image is loading.", "0 percent") $Reslt = _GDIPlus_BitmapLockBits ($hBitmap1, 0, 0, $GuiSizeX, $GuiSizeY, BitOR($GDIP_ILMREAD, $GDIP_ILMWRITE) , $GDIP_PXF32ARGB) ;Get the returned values of _GDIPlus_BitmapLockBits () $width = DllStructGetData($Reslt, "width") $height = DllStructGetData($Reslt, "height") $stride = DllStructGetData($Reslt, "stride") $format = DllStructGetData($Reslt, "format") $Scan0 = DllStructGetData($Reslt, "Scan0") ; See GDIPlusConstants.au3 (Line 115+) for format Numbers $ReadMaterial &= "Contents of $tagGDIPBITMAPDATA. (The output of the _GDIPlus_BitmapLockBits() function):" & @CRLF & _ "width: " & $width & @CRLF & _ "height: " & $height & @CRLF & _ "stride: " & $stride & @CRLF & _ "format: " & Hex($format, 8) & @CRLF & _ "Scan0 : " & $Scan0 $memOpen = _MemoryOpen(_WinAPI_GetCurrentProcessID()) GUISetCursor(1) GUICtrlCreateLabel($ReadMaterial, 10, 10, 580, 480) GUICtrlSetFont(-1, 11, 500) ;Change Alpha Channel - single dimensional array If UBound($aColor, 2) = 0 Then For $i = 1 To $GuiSizeX For $j = 20 To $GuiSizeY + 20 For $n = 1 To $aColor[0] ;#cs ;_MemoryRead($Scan0 + (($y - 21) * $stride) + (($x - 1) * 4), $memOpen) $v_Buffer = DllStructCreate('dword') $addr = $Scan0 + (($j - 21) * $stride) + (($i - 1) * 4) DllCall($memOpen[0], 'int', 'ReadProcessMemory', _ 'int', $memOpen[1], _ 'int', $addr, _ 'ptr', DllStructGetPtr($v_Buffer), _ 'int', DllStructGetSize($v_Buffer), 'int', '') $v_Value = DllStructGetData($v_Buffer, 1) ;ConsoleWrite("$v_Value " & hex($v_Value) & @CRLF) If Hex($v_Value, 6) = Hex($aColor[$n], 6) Then DllStructSetData($v_Buffer, 1, ($aColor[$n])) DllCall($memOpen[0], 'int', 'WriteProcessMemory', _ 'int', $memOpen[1], _ 'int', $addr, _ 'ptr', DllStructGetPtr($v_Buffer), _ 'int', DllStructGetSize($v_Buffer), 'int', '') EndIf $v_Buffer = "" Next Next ;if GUIGetMsg() = $GUI_EVENT_CLOSE then exit ProgressSet(Int(100 * $i / ($GuiSizeX)), Int(100 * $i / ($GuiSizeX)) & " percent") Next EndIf ;Swap colors - 2 dimensional array If UBound($aColor, 2) = 2 Then For $i = 1 To $GuiSizeX For $j = 20 To $GuiSizeY + 20 For $n = 1 To $aColor[0][0] $v_Buffer = DllStructCreate('dword') $addr = $Scan0 + (($j - 21) * $stride) + (($i - 1) * 4) DllCall($memOpen[0], 'int', 'ReadProcessMemory', _ 'int', $memOpen[1], 'int', $addr, _ 'ptr', DllStructGetPtr($v_Buffer), 'int', DllStructGetSize($v_Buffer), 'int', '') $v_Value = DllStructGetData($v_Buffer, 1) ;ConsoleWrite("$v_Value " & hex($v_Value) & @CRLF) If Hex($v_Value, 6) = Hex($aColor[$n][0], 6) Then DllStructSetData($v_Buffer, 1, ($aColor[$n][1])) DllCall($memOpen[0], 'int', 'WriteProcessMemory', _ 'int', $memOpen[1], _ 'int', $addr, _ 'ptr', DllStructGetPtr($v_Buffer), _ 'int', DllStructGetSize($v_Buffer), 'int', '') EndIf $v_Buffer = "" Next Next ;if GUIGetMsg() = $GUI_EVENT_CLOSE then exit ProgressSet(Int(100 * $i / ($GuiSizeX)), Int(100 * $i / ($GuiSizeX)) & " percent") Next EndIf _MemoryClose($memOpen) _GDIPlus_BitmapUnlockBits($hBitmap1, $Reslt) GUISetCursor(2) ;MsgBox(0, "Ready to Continue", "Bitmap has loaded. Press OK to continue.") GUIDelete($hGUIFake) ProgressOff() _GDIPlus_GraphicsDrawImage($hGraphic, $hBitmap1, 0, 0) $tSize = DllStructCreate($tagSIZE) $pSize = DllStructGetPtr($tSize) DllStructSetData($tSize, "X", $GuiSizeX) DllStructSetData($tSize, "Y", $GuiSizeY) $tSource = DllStructCreate($tagPOINT) $pSource = DllStructGetPtr($tSource) $tBlend = DllStructCreate($tagBLENDFUNCTION) $pBlend = DllStructGetPtr($tBlend) DllStructSetData($tBlend, "Alpha", $iOpacity) ;0xFFCC8040)Alpha DllStructSetData($tBlend, "Format", 1) _WinAPI_UpdateLayeredWindow($hGUI, $hWnd, 0, $pSize, $hDC, $pSource, 0, $pBlend, $ULW_ALPHA) ;$ULW_COLORKEY ) ; Save to file $sCLSID = _GDIPlus_EncodersGetCLSID("PNG") _GDIPlus_ImageSaveToFileEx($hBitmap1, @DesktopDir & "\TestWrite.png", $sCLSID) ; Clean up resources _GDIPlus_GraphicsDispose($hGraphic) _WinAPI_DeleteObject($hImage) _WinAPI_DeleteObject($hImage2) _WinAPI_DeleteObject($hBitmap) _WinAPI_DeleteObject($hBitmap1) _WinAPI_DeleteObject($hBitmap3) _WinAPI_DeleteDC($hDC) _WinAPI_ReleaseDC($hGUI, $hWnd) _GDIPlus_Shutdown() Return EndFunc ;==>ImageColorChange ;================================================================================== ; Author(s): Nomad Func _MemoryOpen($iv_Pid, $iv_DesiredAccess = 0x1F0FFF, $iv_InheritHandle = 1) If Not ProcessExists($iv_Pid) Then SetError(1) Return 0 EndIf Local $ah_Handle[2] = [DllOpen('kernel32.dll')] If @error Then SetError(2) Return 0 EndIf Local $av_OpenProcess = DllCall($ah_Handle[0], 'int', 'OpenProcess', 'int', $iv_DesiredAccess, _ 'int', $iv_InheritHandle, 'int', $iv_Pid) If @error Then DllClose($ah_Handle[0]) SetError(3) Return 0 EndIf $ah_Handle[1] = $av_OpenProcess[0] Return $ah_Handle EndFunc ;==>_MemoryOpen ;================================================================================== ; Author(s): Nomad Func _MemoryClose($ah_Handle) If Not IsArray($ah_Handle) Then SetError(1) Return 0 EndIf DllCall($ah_Handle[0], 'int', 'CloseHandle', 'int', $ah_Handle[1]) If Not @error Then DllClose($ah_Handle[0]) Return 1 Else DllClose($ah_Handle[0]) SetError(2) Return 0 EndIf EndFunc ;==>_MemoryClose
Andreik Posted July 29, 2008 Posted July 29, 2008 Awsome! I like very much your scripts. One question: shortcut sign from my icons is black and in your script is red. Why?
Malkey Posted July 29, 2008 Author Posted July 29, 2008 (edited) Andreik said: Awsome! I like very much your scripts. One question: shortcut sign from my icons is black and in your script is red. Why?Good Question In the script posted there is this near the start ; Array to make white to slightly visible yellow & Black to a fully visible red. Local $aColorSwap[3][2] = [[2, 0],[0xFFFFFF, 0x10FFFF00], _ [0x000000, 0xFFFF0000]] ; Swap two colors ; To get started - Comment and/or uncomment the above arrays and enter into command below. ;ImageColorChange($aColorAlpha, 300, 200) ; <================= START FUNCTION HERE ======= ImageColorChange($aColorSwap, 300, 200) ; <============ or HERE ImageColorChange() is using the $aColorSwap array. Looking at the contents of that array we have [[2, 0],[0xFFFFFF, 0x10FFFF00], [0x000000, 0xFFFF0000]] The script see $aColorSwap[0][0] = 2 meaning there are two colors to change First colors are [0xFFFFFF, 0x10FFFF00], meaning white, 0xFFFFFF to slightly visible yellow,0x10FFFF00. Second color [0x000000, 0xFFFF0000], meaning Black, 0x000000 to a fully visible red, 0xFFFF0000. So the format is [0xRRGGBB, 0xAARRGGBB], meaning change color, 0xRRGGBB to this color, 0xAARRGGBB. Hope this makes it clearer. Edited July 29, 2008 by Malkey
Malkey Posted August 1, 2008 Author Posted August 1, 2008 Thanks to weaponx for his example @http://www.autoitscript.com/forum/index.ph...st&p=555694This made me realize NomadMemory is not needed. This does speed the process up a little. But it is still not fast. Here is the first post script again without the NomadMemory calls.expandcollapse popup#include <GuiConstantsEx.au3> #include <GDIPlus.au3> #include <ScreenCapture.au3> #include <WinAPI.au3> #include <WindowsConstants.au3> ; NomadMemory.au3 at ; http://www.autoitscript.com/forum/index.ph...st&p=394082 Opt('MustDeclareVars', 1) Opt("PixelCoordMode", 0) ; Array to make white transparent ;local $aColorAlpha[2] = [1, 0x00FFFFFF] ; Change Alpha value on one color ; Array to make white transparent & Red almost transparent Local $aColorAlpha[3] = [2, 0x00FFFFFF, 0x10000000] ; Change Alpha value on two colors ; Array to make white to slightly visible yellow ;local $aColorSwap[2][2] = [[1,0],[0xFFFFFF,0x10FFFF00]] ; Swap one color with another ; Array to make white to slightly visible yellow & Black to a fully visible red. Local $aColorSwap[3][2] = [[2, 0],[0xFFFFFF, 0x10FFFF00], _ [0x000000, 0xFFFF0000]] ; Swap two colors ; To get started - Comment and/or uncomment the above arrays and enter into command below. ;ImageColorChange($aColorAlpha) ; <================= START FUNCTION HERE ======= ImageColorChange($aColorSwap) ; <============ or HERE ShellExecute(@DesktopDir & "\TestWrite.png") ; Loop until user exits Do Sleep(10) Until GUIGetMsg() = $GUI_EVENT_CLOSE FileDelete(@DesktopDir & "\TestWrite.png") ; ========================================== ; Description - Either changes Alpha channel of one or more selected colors ; or ; Changes one or more colors to other colors. ; Input - $aColor is an array. Either single or two dimensional array. ; - Single array to change Alpha channel (transparency) ; $aColorAlpha[0] contains number of colors to be changed. ; Colors entered are in 0xAARRGGBB format where ; AA is the new required Alpha value. Range is 00 to FF. 00 is completely invisible. ; RRGGBB is the color which will have its alpha channel changed. FF0000 is Red. ; ; - Two dimensional array to swap colors. ; $aColorSwap[0][0] contains number of colors to be swapped. ; $aColorSwap[1+n][0] is the color to replace in 0xRRGGBB format. ; $aColorSwap[1+n][1] is the replacement color in 0xAARRGGBB format. ; - $iWidth & $iHeight for Width and Height of image ; Func ImageColorChange(ByRef $aColor, $iWidth = -1, $iHeight = -1) Local Const $ULW_ALPHA = 2 Local $hGUI, $hBitmap, $hGraphic, $hImage, $hGUIFake Local $width, $height, $format, $Value, $hBitmap1, $hBitmap3, $hImage2 Local $hWnd, $hDC, $pSize, $tSize, $pSource, $tSource, $pBlend, $tBlend, $Reslt Local $ReadMaterial, $sCLSID, $GuiSizeX, $GuiSizeY, $iOpacity = 255,$dat,$x,$y Local $addr,$v_Value,$v_Buffer, $stride, $Scan0, $memOpen If $iWidth = -1 Then $GuiSizeX = 600 Else $GuiSizeX = $iWidth EndIf If $iHeight = -1 Then $GuiSizeY = 500 Else $GuiSizeY = $iHeight EndIf ;MsgBox(0,"",UBound($aColor, 2)) ; Create GUI's $hGUI = GUICreate("GDI+", $GuiSizeX, $GuiSizeY, -1, -1, 0, ($WS_EX_LAYERED)) GUISetState() $hGUIFake = GUICreate("GDI+ FAKE", 600, 300, @DesktopWidth / 4, @DesktopHeight / 8) GUISetBkColor(0xFFFFB0) GUISetState() _GDIPlus_Startup() $hWnd = _WinAPI_GetDC($hGUI) $hDC = _WinAPI_CreateCompatibleDC($hWnd) $hBitmap = _WinAPI_CreateCompatibleBitmap($hWnd, $GuiSizeX, $GuiSizeY) _WinAPI_SelectObject($hDC, $hBitmap) $hGraphic = _GDIPlus_GraphicsCreateFromHDC($hDC) $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap) _GDIPlus_GraphicsClear($hGraphic, 0x00CC8040) ;$iWidth = _GDIPlus_ImageGetWidth ($hImage) ;$iHeight = _GDIPlus_ImageGetHeight ($hImage) $hBitmap3 = _ScreenCapture_Capture("", 0, 0, $GuiSizeX, $GuiSizeY, False) $hImage2 = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap3) $hBitmap1 = _GDIPlus_BitmapCloneArea($hImage2, 0, 0, $GuiSizeX, $GuiSizeY, $GDIP_PXF32ARGB) $ReadMaterial = "The bitmap image is loading." & @CRLF & @CRLF & _ "A snap shot of the top left quarter of the screen will be manipulated. " & @CRLF & _ "This window will be deleted when the colored pixels have been changed in " & @CRLF & _ "the area of memory where the bitmap is stored.On final exit, the png file " & @CRLF & _ "saved to desktop will be deleted." & @CRLF & @CRLF ProgressOn("Progress Bar", "The bitmap image is loading.", "0 percent") $Reslt = _GDIPlus_BitmapLockBits ($hBitmap1, 0, 0, $GuiSizeX, $GuiSizeY, BitOR($GDIP_ILMREAD, $GDIP_ILMWRITE) , $GDIP_PXF32ARGB) ;Get the returned values of _GDIPlus_BitmapLockBits () $width = DllStructGetData($Reslt, "width") $height = DllStructGetData($Reslt, "height") $stride = DllStructGetData($Reslt, "stride") $format = DllStructGetData($Reslt, "format") $Scan0 = DllStructGetData($Reslt, "Scan0") ; See GDIPlusConstants.au3 (Line 115+) for format Numbers $ReadMaterial &= "Contents of $tagGDIPBITMAPDATA. (The output of the _GDIPlus_BitmapLockBits() function):" & @CRLF & _ "width: " & $width & @CRLF & _ "height: " & $height & @CRLF & _ "stride: " & $stride & @CRLF & _ "format: " & Hex($format, 8) & @CRLF & _ "Scan0 : " & $Scan0 GUISetCursor(1) GUICtrlCreateLabel($ReadMaterial, 10, 10, 580, 480) GUICtrlSetFont(-1, 11, 500) ;Change Alpha Channel - single dimensional array If UBound($aColor, 2) = 0 Then For $i = 0 To $GuiSizeX - 1 For $j = 0 To $GuiSizeY -1 For $n = 1 To $aColor[0] $v_Buffer = DllStructCreate("dword", $Scan0 + ($j * $stride) + ($i * 4)) $v_Value =DllStructGetData($v_Buffer, 1) If Hex($v_Value, 6) = Hex($aColor[$n], 6) Then DllStructSetData($v_Buffer, 1, hex($aColor[$n],8)) EndIf Next Next ;if GUIGetMsg() = $GUI_EVENT_CLOSE then exit ProgressSet(Int(100 * $i / ($GuiSizeX)), Int(100 * $i / ($GuiSizeX)) & " percent") Next EndIf ;Swap colors - 2 dimensional array If UBound($aColor, 2) = 2 Then For $i = 0 To $GuiSizeX - 1 For $j = 0 To $GuiSizeY -1 For $n = 0 To $aColor[0][0] $v_Buffer = DllStructCreate("dword", $Scan0 + ($j * $stride) + ($i * 4)) $v_Value = DllStructGetData($v_Buffer, 1) If Hex($v_Value, 6) = Hex($aColor[$n][0], 6) Then DllStructSetData($v_Buffer, 1, hex($aColor[$n][1],8)) EndIf Next Next ;if GUIGetMsg() = $GUI_EVENT_CLOSE then exit ProgressSet(Int(100 * $i / ($GuiSizeX)), Int(100 * $i / ($GuiSizeX)) & " percent") Next EndIf _GDIPlus_BitmapUnlockBits($hBitmap1, $Reslt) GUISetCursor(2) ;MsgBox(0, "Ready to Continue", "Bitmap has loaded. Press OK to continue.") GUIDelete($hGUIFake) ProgressOff() _GDIPlus_GraphicsDrawImage($hGraphic, $hBitmap1, 0, 0) $tSize = DllStructCreate($tagSIZE) $pSize = DllStructGetPtr($tSize) DllStructSetData($tSize, "X", $GuiSizeX) DllStructSetData($tSize, "Y", $GuiSizeY ) $tSource = DllStructCreate($tagPOINT) $pSource = DllStructGetPtr($tSource) $tBlend = DllStructCreate($tagBLENDFUNCTION) $pBlend = DllStructGetPtr($tBlend) DllStructSetData($tBlend, "Alpha", $iOpacity) ;0xFFCC8040)Alpha DllStructSetData($tBlend, "Format", 1) _WinAPI_UpdateLayeredWindow($hGUI, $hWnd, 0, $pSize, $hDC, $pSource, 0, $pBlend, $ULW_ALPHA) ;$ULW_COLORKEY ) ; Save to file $sCLSID = _GDIPlus_EncodersGetCLSID("PNG") _GDIPlus_ImageSaveToFileEx($hBitmap1, @DesktopDir & "\TestWrite.png", $sCLSID) ; Clean up resources _GDIPlus_GraphicsDispose($hGraphic) _WinAPI_DeleteObject($hImage) _WinAPI_DeleteObject($hImage2) _WinAPI_DeleteObject($hBitmap) _WinAPI_DeleteObject($hBitmap1) _WinAPI_DeleteObject($hBitmap3) _WinAPI_DeleteDC($hDC) _WinAPI_ReleaseDC($hGUI, $hWnd) _GDIPlus_Shutdown() Return EndFunc ;==>ImageColorChange
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