JFee Posted May 4, 2008 Share Posted May 4, 2008 I created a nice little program that creates a fractal image using the standard GUI Graphics control. What I want to do now, is create saving functionality to save that graphics control to an image file. After looking through all sorts of functions, the best way I've thought of is the following: _GDIPlus_Startup () $hGraphic = GUICtrlGetHandle($graphic) $GraphicBMP = _GDIPlus_BitmapCreateFromGraphics($width, $height, $hGraphic) $GraphicHBMP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($GraphicBMP) $savePath = FileSaveDialog("Save fractal...", @userprofiledir, "Images (*.jpg;*.gif;*.bmp;*.png)", 18, "Fractal.bmp") _ScreenCapture_SaveImage($savePath, $GraphicHBMP) _GDIPlus_Shutdown () Where $graphic is the control ID for the graphic control. When I run it, I get the save dialog and everything seems to be fine. No errors or crashes, but the _ScreenCapture_SaveImage isn't actually working. It kinda seems like there should be an easier way to do this, but I couldn't find one. Any help with this code or alternative methods are GREATLY appreciated. Regards,Josh Link to comment Share on other sites More sharing options...
Zedna Posted May 4, 2008 Share Posted May 4, 2008 (edited) Post WHOLE reproducing script. I think I can help you. Edited May 4, 2008 by Zedna Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
JFee Posted May 4, 2008 Author Share Posted May 4, 2008 (edited) expandcollapse popup#cs ***************************************************************** Title: JuliaGen Version: 0.4 Creator: Josh Fee Date: 5/1/08 INTRODUCTION This application is used to create fractal images that belong to the Julia Set. The Julia Set consists of all points Z, when iterated through the function f(C) = Z^2 + C, where C is a complex binomial, an infinite number of times, never leaves a given region. The given region that is most common, and used in this program is the circle whose equation is x^2 + y^2 = 4. Each point is assigned a color based on the number of times it needs to be iterated through the function in order for it to leave the region. Points determined to never leave the region is said to be a part of the set. PARAMETERS The fractal image is created based on a set of parameters entered in the parameter list below. The parameters allow you to determing the size of the image, the scale of the image, the center of the image, the C value for f(C), and the number of iterations before the point is determined to be part of the set. RUNNING THE GENERATOR When you run the generator, an empty window will be shown. The fractal is being genearated, but the window does not automatically refresh until the fractal is complete. You can refresh the window by pressing F5, or by minimizing the window and restoring it. COLORING Currently, there are 16 colors being used and are entered manually. A current goal of this project is to automatically create a gradient of X colors, and eventually add the colors in the gradient to the parameter list. TODO LIST - Create a control panel to modify parameters - Have a % complete indicator and time remaining feature - Save images as a .bmp file - Fix GUI locking problem (stop repaints when complete) - Create autmoatic color generation (smooth gradients) NOTES This program was created entirely from scratch. No other similar code was looked at while writing this. ***************************************************************** #ce ; Parameter list: $width = 100; Determines width of image in pixels, height is derived from it (4:3) $zoom = 1; Determines the zoom of the fractal - 1x shows whole fractal, 2x doubles the zoom $centerx = 0; Determines the center of the image... use this to translate the fractal up/down and left/right $centery = 0; ... $Ca = -.8; The real coefficient in C ... the a in (a+bi) examples: .285, -.8 $Cb = .156; The imaginary coefficient in C ... the b in (a+bi) examples .01, .156 $iterations = 256; How many times to iterate the point before it is determined to be part of the set ;Coloring: $gradientStep1 = "ffffff" $gradientStep2 = "ffff66" $gradientStep3 = "0000ff" $gradientStep4 = "000000" ; Parameters you SHOULD NOT TOUCH unless you know what you're doing ; These keep the fractal proportionate... modifying will skew fractal $height = $width;/ 4 * 3 $xscale = 2/$zoom $yscale = $xscale;($xscale / 2) * 1.5 #include <GUIConstants.au3>; GUI library... won't function without it #Include <ScreenCapture.au3>; For saving image #Include <GDIPlus.au3>; For creating BMP of graphic #include <GuiConstantsEx.au3> #include <WinAPI.au3> $gui=GUICreate("Josh Fee's Fractal Project!", $width, $height) $fractal = GUICtrlCreateGraphic(-1,-1,$width,$height); This will contain bitmap data for fractal ;$progress = GUICtrlCreateInput("", 3, 3 ,-1,-1,$ES_READONLY) $progress = GUICtrlCreateProgress(3, 3, 50, 10) GUICtrlSetBkColor($fractal, 0xffffff) GUISetState(@SW_SHOW) HotKeySet("{f5}", "autoRefresh"); Set a hotkey to refresh the image Func autoRefresh(); This function refreshes the graphic HotKeySet("{f5}"); Clear hotkey GUICtrlSetGraphic($fractal, $GUI_GR_REFRESH) HotKeySet("{f5}", "autoRefresh"); Reset the hotkey EndFunc Func genFractal($width, $height, $xscale, $yscale, $centerx, $centery, $Ca, $Cb, $iterations) $totalPix = $width * $height ; Iterate through each pixel for $x = 1 to $width ; if Mod($x, 10) = 0 then GUICtrlSetGraphic($fractal, $GUI_GR_REFRESH); This automatically refreshes every 10 columns for $y = 1 to $height $complete = ($x - 1) * $height + $y $percent = ($complete/$totalPix) * 100 GUICtrlSetData($progress, $percent) If GUICtrlRead($progress) = 100 Then GUICtrlDelete($progress) GUICtrlSetGraphic($fractal,$GUI_GR_MOVE, $x, $y) $count = 0 ; Modify the value of each pixel so that the middle pixel corresponds to the origin $startx = (($x/$width) * (2 * $xscale) - $xscale) + $centerx $starty = ($y/$height * (2 * $yscale) - $yscale) - $centery ; Iterate point through formula (z^2 + c where c is defined in parameters) ; $count represents the number of times it takes for the point to leave the circle x^2 + y^2 = 4 while $count < $iterations and ($startx ^ 2 + $starty ^ 2) <= 4 $count = $count + 1 $newx = ($startx^2 - $starty ^ 2) + $Ca; Determine the new X value after iterating $newy = (2 * $startx * $starty) - $Cb; Determine the new Y value after iterating ; Check if the new point is outside the circle ; If it is, stop looping if ($newx ^ 2 + $newy ^2) > 4 Then ExitLoop EndIf ; If the point is still in the circle, make the iterated point the starting point for6 ; the next iteration $startx = $newx $starty = $newy WEnd ; This next block of code determines the color of the pixel ; Since 16 colors are being used, the remainder of the count/16 will have a color assiged ; This makes all points whose $count = 1 the same color, etc. ; !!! TO DO: Automatically generate the gradient with more than 16 colors for smoother and better image if $count < $iterations Then; If the point is determined to NOT be part of the set, give it a unique color $color = mod($count,256) Select Case $color < 64 $Color1 = $gradientStep1 $Color2 = $gradientStep2 Case $color < 128 $Color1 = $gradientStep2 $Color2 = $gradientStep3 Case $color < 192 $Color1 = $gradientStep3 $Color2 = $gradientStep4 Case Else $Color1 = $gradientStep4 $Color2 = $gradientStep1 EndSelect Dim $startcolor[4] Dim $endcolor[4] Dim $colorDif[4] Dim $colorStep[4] Dim $colorVal[4] $startcolor[1] = StringLeft($Color1,2) $startcolor[2] = StringMid($Color1,3,2) $startcolor[3] = StringRight($Color1,2) $endcolor[1] = StringLeft($Color2,2) $endcolor[2] = StringMid($Color2,3,2) $endcolor[3] = StringRight($Color2,2) $startcolor[1] = Dec($startcolor[1]) $startcolor[2] = Dec($startcolor[2]) $startcolor[3] = Dec($startcolor[3]) $endcolor[1] = Dec($endcolor[1]) $endcolor[2] = Dec($endcolor[2]) $endcolor[3] = Dec($endcolor[3]) for $i = 1 To 3 $colorDif[$i] = $endcolor[$i] - $startcolor[$i] $colorStep[$i] = $colorDif[$i] / (255/4) $colorVal[$i] = $startcolor[$i] + $color * $colorStep[$i] $colorVal[$i] = Hex($colorVal[$i],2) ;MsgBox(1, "", $colorVal[$i]) Next $color = $colorVal[1] & $colorVal[2] & $colorVal[3] ;MsgBox(1, "", $color) ;$colorDif = $endcolor - $startcolor ;$colorStep = $colorDif / 15 ;$color = $startcolor + $color * $colorStep ;$color = hex($color) $color = "0x" & $color ;$rColor = "00" ;$gColor = "00" ;$bColor = "ff" ;If $color < 16 Then ; $t_Color = StringRight(String(hex($color)),1) ; $rColor = $t_Color & $t_Color ; $gColor = $t_Color & $t_Color ;ElseIf $color < 32 Then ; $color = $color - (2 * ($color - 15.5)) ; $t_Color = StringRight(string(hex($color)),1) ; $rColor = $t_Color & $t_Color ; $gColor = $t_Color & $t_Color ;EndIf ;$color = "0x" & $rColor & $gColor & $bColor GUICtrlSetGraphic($fractal, $gui_gr_color, $color) ;MsgBox(1,"Color code", $color) ; Color the pixel GUICtrlSetGraphic($fractal,$GUI_GR_PIXEL, $x, $y) Else ; Make all points part of the set a certain color GUICtrlSetGraphic($fractal, $GUI_GR_COLOR, 0x000000) ;Color the pixels GUICtrlSetGraphic($fractal,$GUI_GR_PIXEL, $x, $y) EndIf Next Next GUICtrlSetGraphic($fractal, $GUI_GR_REFRESH) EndFunc genFractal($width, $height, $xscale, $yscale, $centerx, $centery, $Ca, $Cb, $iterations) _GDIPlus_Startup () ;GUICtrlSetGraphic($fractal, $GUI_GR_REFRESH); Refresh / repaint the window ;GUISetState(@SW_LOCK, $gui); Lock the GUI so it doesn't repaint... not working ;$savePath = FileSaveDialog("Save fractal...", @userprofiledir, "Images (*.jpg;*.gif;*.bmp;*.png)", 18, "Fractal_" & $width & "x" & $height & "_" & $Ca & "+" & $Cb & "_x" & $zoom & ".bmp") ;_GDIPlus_ImageSaveToFile ($fractalBMP, @MyDocumentsDir & "\GDIPlus_Image.jpg") ;$fractalSave - _GDIPlus_BitmapCreateFromHBITMAP($fractalBMP) ;_GDIPlus_ImageSaveToFile($fractalSave, FileSaveDialog("Save fractal...", @userprofiledir, "Images (*.jpg;*.gif;*.bmp;*.png)", 18, "Fractal_" & $width & "x" & $height & "_" & $Ca & "+" & $Cb & "_x" & $zoom & ".bmp")) ;$fractalHBMP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($fractalBMP) ;MsgBox(1, "", "1") $hFractal = GUICtrlGetHandle($fractal) $fractalBMP = _GDIPlus_BitmapCreateFromGraphics($width, $height, $hFractal) $fractalHBMP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($fractalBMP) $savePath = FileSaveDialog("Save fractal...", @userprofiledir, "Images (*.jpg;*.gif;*.bmp;*.png)", 18, "Fractal.bmp") ;MsgBox(1, "blah", String($savePath)) _GDIPlus_ImageSaveToFile($fractalBMP, @userprofiledir & "\fractal.bmp") ;_ScreenCapture_SaveImage(@UserProfileDir & "\fractal.bmp", $fractalHBMP) ;_ScreenCapture_SaveImage(@MyDocumentsDir & "\Fractal-savetest.bmp", $fractalBMP) ;_GDIPlus_GraphicsDispose ($fractal) ;_GDIPlus_GraphicsClear($hFractal, 0xff000000) _GDIPlus_Shutdown() ;GDIPlus_GraphicsClear($fractal, 0xffffff) GUISetState(@SW_SHOW) While 1; Keep the GUI alive ; $msg represents the GUI action, i.e. closing the window $msg = GUIGetMsg() If $msg = $GUI_EVENT_CLOSE Then ExitLoop; If user exits window, end the loop and kill the GUI Wend Ignore the messy script Line 244 is where the stuff that doesn't work starts Thanks for checking this out (hope you like the fractal generation too Parameters up top if you wanna mess around ) Edited May 4, 2008 by JFee Regards,Josh Link to comment Share on other sites More sharing options...
covaks Posted May 5, 2008 Share Posted May 5, 2008 cool. :-) I put in a few lines to take a simple screenshot of the control. I'm sure I messed something up on it though, lol. but for the current size of the control and gui, it works. expandcollapse popup#cs ***************************************************************** Title: JuliaGen Version: 0.4 Creator: Josh Fee Date: 5/1/08 INTRODUCTION This application is used to create fractal images that belong to the Julia Set. The Julia Set consists of all points Z, when iterated through the function f(C) = Z^2 + C, where C is a complex binomial, an infinite number of times, never leaves a given region. The given region that is most common, and used in this program is the circle whose equation is x^2 + y^2 = 4. Each point is assigned a color based on the number of times it needs to be iterated through the function in order for it to leave the region. Points determined to never leave the region is said to be a part of the set. PARAMETERS The fractal image is created based on a set of parameters entered in the parameter list below. The parameters allow you to determing the size of the image, the scale of the image, the center of the image, the C value for f(C), and the number of iterations before the point is determined to be part of the set. RUNNING THE GENERATOR When you run the generator, an empty window will be shown. The fractal is being genearated, but the window does not automatically refresh until the fractal is complete. You can refresh the window by pressing F5, or by minimizing the window and restoring it. COLORING Currently, there are 16 colors being used and are entered manually. A current goal of this project is to automatically create a gradient of X colors, and eventually add the colors in the gradient to the parameter list. TODO LIST - Create a control panel to modify parameters - Have a % complete indicator and time remaining feature - Save images as a .bmp file - Fix GUI locking problem (stop repaints when complete) - Create autmoatic color generation (smooth gradients) NOTES This program was created entirely from scratch. No other similar code was looked at while writing this. ***************************************************************** #ce ; Parameter list: $width = 100; Determines width of image in pixels, height is derived from it (4:3) $zoom = 1; Determines the zoom of the fractal - 1x shows whole fractal, 2x doubles the zoom $centerx = 0; Determines the center of the image... use this to translate the fractal up/down and left/right $centery = 0; ... $Ca = -.8; The real coefficient in C ... the a in (a+bi) examples: .285, -.8 $Cb = .156; The imaginary coefficient in C ... the b in (a+bi) examples .01, .156 $iterations = 256; How many times to iterate the point before it is determined to be part of the set ;Coloring: $gradientStep1 = "ffffff" $gradientStep2 = "ffff66" $gradientStep3 = "0000ff" $gradientStep4 = "000000" ; Parameters you SHOULD NOT TOUCH unless you know what you're doing ; These keep the fractal proportionate... modifying will skew fractal $height = $width;/ 4 * 3 $xscale = 2 / $zoom $yscale = $xscale;($xscale / 2) * 1.5 #include <GUIConstants.au3>; GUI library... won't function without it #Include <ScreenCapture.au3>; For saving image #Include <GDIPlus.au3>; For creating BMP of graphic #include <GuiConstantsEx.au3> #include <WinAPI.au3> #Include <ScreenCapture.au3> ; To capture screenshot of our window -covaks $gui = GUICreate("Josh Fee's Fractal Project!", $width, $height) $fractal = GUICtrlCreateGraphic(-1, -1, $width, $height); This will contain bitmap data for fractal ;$progress = GUICtrlCreateInput("", 3, 3 ,-1,-1,$ES_READONLY) $progress = GUICtrlCreateProgress(3, 3, 50, 10) GUICtrlSetBkColor($fractal, 0xffffff) GUISetState(@SW_SHOW) HotKeySet("{f5}", "autoRefresh"); Set a hotkey to refresh the image Func autoRefresh(); This function refreshes the graphic HotKeySet("{f5}"); Clear hotkey GUICtrlSetGraphic($fractal, $GUI_GR_REFRESH) HotKeySet("{f5}", "autoRefresh"); Reset the hotkey EndFunc ;==>autoRefresh Func genFractal($width, $height, $xscale, $yscale, $centerx, $centery, $Ca, $Cb, $iterations) $totalPix = $width * $height ; Iterate through each pixel For $x = 1 To $width ; if Mod($x, 10) = 0 then GUICtrlSetGraphic($fractal, $GUI_GR_REFRESH); This automatically refreshes every 10 columns For $y = 1 To $height $complete = ($x - 1) * $height + $y $percent = ($complete / $totalPix) * 100 GUICtrlSetData($progress, $percent) If GUICtrlRead($progress) = 100 Then GUICtrlDelete($progress) GUICtrlSetGraphic($fractal, $GUI_GR_MOVE, $x, $y) $count = 0 ; Modify the value of each pixel so that the middle pixel corresponds to the origin $startx = (($x / $width) * (2 * $xscale) - $xscale) + $centerx $starty = ($y / $height * (2 * $yscale) - $yscale) - $centery ; Iterate point through formula (z^2 + c where c is defined in parameters) ; $count represents the number of times it takes for the point to leave the circle x^2 + y^2 = 4 While $count < $iterations And ($startx ^ 2 + $starty ^ 2) <= 4 $count = $count + 1 $newx = ($startx ^ 2 - $starty ^ 2) + $Ca; Determine the new X value after iterating $newy = (2 * $startx * $starty) - $Cb; Determine the new Y value after iterating ; Check if the new point is outside the circle ; If it is, stop looping If ($newx ^ 2 + $newy ^ 2) > 4 Then ExitLoop EndIf ; If the point is still in the circle, make the iterated point the starting point for6 ; the next iteration $startx = $newx $starty = $newy WEnd ; This next block of code determines the color of the pixel ; Since 16 colors are being used, the remainder of the count/16 will have a color assiged ; This makes all points whose $count = 1 the same color, etc. ; !!! TO DO: Automatically generate the gradient with more than 16 colors for smoother and better image If $count < $iterations Then; If the point is determined to NOT be part of the set, give it a unique color $color = Mod($count, 256) Select Case $color < 64 $Color1 = $gradientStep1 $Color2 = $gradientStep2 Case $color < 128 $Color1 = $gradientStep2 $Color2 = $gradientStep3 Case $color < 192 $Color1 = $gradientStep3 $Color2 = $gradientStep4 Case Else $Color1 = $gradientStep4 $Color2 = $gradientStep1 EndSelect Dim $startcolor[4] Dim $endcolor[4] Dim $colorDif[4] Dim $colorStep[4] Dim $colorVal[4] $startcolor[1] = StringLeft($Color1, 2) $startcolor[2] = StringMid($Color1, 3, 2) $startcolor[3] = StringRight($Color1, 2) $endcolor[1] = StringLeft($Color2, 2) $endcolor[2] = StringMid($Color2, 3, 2) $endcolor[3] = StringRight($Color2, 2) $startcolor[1] = Dec($startcolor[1]) $startcolor[2] = Dec($startcolor[2]) $startcolor[3] = Dec($startcolor[3]) $endcolor[1] = Dec($endcolor[1]) $endcolor[2] = Dec($endcolor[2]) $endcolor[3] = Dec($endcolor[3]) For $i = 1 To 3 $colorDif[$i] = $endcolor[$i] - $startcolor[$i] $colorStep[$i] = $colorDif[$i] / (255 / 4) $colorVal[$i] = $startcolor[$i] + $color * $colorStep[$i] $colorVal[$i] = Hex($colorVal[$i], 2) ;MsgBox(1, "", $colorVal[$i]) Next $color = $colorVal[1] & $colorVal[2] & $colorVal[3] ;MsgBox(1, "", $color) ;$colorDif = $endcolor - $startcolor ;$colorStep = $colorDif / 15 ;$color = $startcolor + $color * $colorStep ;$color = hex($color) $color = "0x" & $color ;$rColor = "00" ;$gColor = "00" ;$bColor = "ff" ;If $color < 16 Then ; $t_Color = StringRight(String(hex($color)),1) ; $rColor = $t_Color & $t_Color ; $gColor = $t_Color & $t_Color ;ElseIf $color < 32 Then ; $color = $color - (2 * ($color - 15.5)) ; $t_Color = StringRight(string(hex($color)),1) ; $rColor = $t_Color & $t_Color ; $gColor = $t_Color & $t_Color ;EndIf ;$color = "0x" & $rColor & $gColor & $bColor GUICtrlSetGraphic($fractal, $gui_gr_color, $color) ;MsgBox(1,"Color code", $color) ; Color the pixel GUICtrlSetGraphic($fractal, $GUI_GR_PIXEL, $x, $y) Else ; Make all points part of the set a certain color GUICtrlSetGraphic($fractal, $gui_gr_color, 0x000000) ;Color the pixels GUICtrlSetGraphic($fractal, $GUI_GR_PIXEL, $x, $y) EndIf Next Next GUICtrlSetGraphic($fractal, $GUI_GR_REFRESH) EndFunc ;==>genFractal genFractal($width, $height, $xscale, $yscale, $centerx, $centery, $Ca, $Cb, $iterations) $sSaveFile = FileSaveDialog("Save File", @MyDocumentsDir, "(*.bmp)") $p = ControlGetPos($gui, "", $fractal) ; I think there's an easier way to do this.. $p[0] += _WinAPI_GetSystemMetrics($SM_CYFRAME) $p[1] += _WinAPI_GetSystemMetrics($SM_CYCAPTION)+_WinAPI_GetSystemMetrics($SM_CYFRAME) $p[2] += _WinAPI_GetSystemMetrics($SM_CYFRAME) -1 $p[3] += _WinAPI_GetSystemMetrics($SM_CYCAPTION)+_WinAPI_GetSystemMetrics($SM_CYFRAME) -1 _ScreenCapture_CaptureWnd($sSaveFile, $gui, $p[0], $p[1], $p[2], $p[3], False) While 1; Keep the GUI alive ; $msg represents the GUI action, i.e. closing the window $msg = GUIGetMsg() If $msg = $GUI_EVENT_CLOSE Then ExitLoop; If user exits window, end the loop and kill the GUI WEnd Link to comment Share on other sites More sharing options...
Zedna Posted May 5, 2008 Share Posted May 5, 2008 cool. :-) I put in a few lines to take a simple screenshot of the control. I'm sure I messed something up on it though, lol. but for the current size of the control and gui, it works. Little simpler method: $sSaveFile = FileSaveDialog("Save File", @MyDocumentsDir, "(*.bmp)") $hfractal = GUICtrlGetHandle($fractal) _ScreenCapture_CaptureWnd($sSaveFile, $hfractal, 0, 0, -1, -1, False) Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
JFee Posted May 5, 2008 Author Share Posted May 5, 2008 Little simpler method: $sSaveFile = FileSaveDialog("Save File", @MyDocumentsDir, "(*.bmp)") $hfractal = GUICtrlGetHandle($fractal) _ScreenCapture_CaptureWnd($sSaveFile, $hfractal, 0, 0, -1, -1, False) That works fine and all, but I don't want it to screencapture the window. I really just want to take the graphic control and turn it into an image. If the window is too big, or partially off the screen then it doesn't save it. Does that make sense what I'm trying to do? Regards,Josh Link to comment Share on other sites More sharing options...
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