Jump to content

Optimizing GDIPlus function generating large grid with dots


Recommended Posts

I have the below code which generates a grid an puts a circle into each with random sizes (just for demonstrational purposes).
It does the job right (more or less), but performance is not optimal. Added some monitoring to print out the elapsed time and the peak memory. Here is the output from my laptop:

Quote

Runtime: 0 seconds.Memory peaks 20 -> 22 MB
Grid 10 - image created C:\Users\Attila\Downloads\grid10.png
Runtime: 2 seconds.Memory peaks 22 -> 69 MB
Grid 100 - Image created C:\Users\Attila\Downloads\grid100.png
Runtime: 10 seconds.Memory peaks 69 -> 362 MB
Grid 250 - Image created C:\Users\Attila\Downloads\grid250.png
Runtime: 23 seconds.Memory peaks 362 -> 1310 MB
Grid 450 - Image created C:\Users\Attila\Downloads\grid450.png
Runtime: 45 seconds.Memory peaks 1310 -> 2480 MB
Grid 500 - Image created C:\Users\Attila\Downloads\grid500.png
Runtime: 97 seconds.Memory peaks 2480 -> 2480 MB
Grid 500 - Image created C:\Users\Attila\Downloads\grid1000.png

As you can see, memory climbs up quite quickly, generating a 500x500 grid consumes 2.4GB RAM which is not optimal, not to mention it took 45 seconds.
Grid with size 1000 x 1000 was not even created, I think it is the memory limitation per application.

Question is simple: how could I make this more efficient? Already checked variable scopes, disposing not used object, but that's all what I could do.

Thank you in advance! 

#include <GDIPlus.au3>

Global Const $CELL_SIZE = 30
Global Const $GRID_PADDING = 5
Global Const $MIN_CIRCLE_RADIUS = 5
Global Const $MAX_CIRCLE_RADIUS = 10
Global $START = TimerInit()

Func DrawCircles($hGraphics,$GRID_SIZE)
    Local $hBrush = _GDIPlus_BrushCreateSolid(0xFFFF5050)
    For $i = 0 To $GRID_SIZE - 1
        For $j = 0 To $GRID_SIZE - 1
            Local $iRadius = Random($MIN_CIRCLE_RADIUS, $MAX_CIRCLE_RADIUS, 1)
            Local $iCenterX = $GRID_PADDING * 1.5 + $j * ($CELL_SIZE + $GRID_PADDING) + $CELL_SIZE / 2
            Local $iCenterY = $GRID_PADDING * 1.5 + $i * ($CELL_SIZE + $GRID_PADDING) + $CELL_SIZE / 2
            _GDIPlus_GraphicsFillEllipse($hGraphics, $iCenterX - $iRadius, $iCenterY - $iRadius, $iRadius * 2, $iRadius * 2, $hBrush)
        Next
    Next
    _GDIPlus_BrushDispose($hBrush)
EndFunc   ;==>DrawCircles

Func DrawGrid($hGraphics,$GRID_SIZE)
    Local $hPen = _GDIPlus_PenCreate(0xFF000000, 1)
    For $i = 0 To $GRID_SIZE
        Local $iX = $i * ($CELL_SIZE + $GRID_PADDING)
        _GDIPlus_GraphicsDrawLine($hGraphics, $GRID_PADDING, $GRID_PADDING + $iX, $GRID_PADDING + $GRID_SIZE * ($CELL_SIZE + $GRID_PADDING), $GRID_PADDING + $iX, $hPen)
        _GDIPlus_GraphicsDrawLine($hGraphics, $GRID_PADDING + $iX, $GRID_PADDING, $GRID_PADDING + $iX, $GRID_PADDING + $GRID_SIZE * ($CELL_SIZE + $GRID_PADDING), $hPen)
    Next
    _GDIPlus_PenDispose($hPen)
EndFunc   ;==>DrawGrid

Func DrawGridToBitmap($GRID_SIZE)
    $aWS = ProcessGetStats()
    Local $pb = Round($aWS[1]/1024/1024)
    _GDIPlus_Startup()
    Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($GRID_SIZE * ($CELL_SIZE + $GRID_PADDING) + 2*$GRID_PADDING + 1, $GRID_SIZE * ($CELL_SIZE + $GRID_PADDING) + 2*$GRID_PADDING + 1)
    Local $hBmpCtxt = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    _GDIPlus_GraphicsSetSmoothingMode($hBmpCtxt, $GDIP_SMOOTHINGMODE_HIGHQUALITY)
    _GDIPlus_GraphicsClear($hBmpCtxt, 0xFFFFFFFF)
    Local $hGraphics = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    DrawGrid($hGraphics,$GRID_SIZE)
    DrawCircles($hGraphics,$GRID_SIZE)
    Local $sFilePath = @ScriptDir & "\grid" & $GRID_SIZE & ".png"
    _GDIPlus_ImageSaveToFile($hBitmap, $sFilePath)
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_Shutdown()
    $aWS = ProcessGetStats()
    Local $pa = Round($aWS[1]/1024/1024)
    ConsoleWrite("Runtime: " & Round(TimerDiff($START)/1000) & " seconds.Memory peaks " & $pb & " -> " & $pa & " MB" & @LF)
    $START = TimerInit()
    Return $sFilePath
EndFunc   ;==>DrawGridToBitmap

ConsoleWrite("Grid 10 - image created " & DrawGridToBitmap(10) & @LF)
ConsoleWrite("Grid 100 - Image created " & DrawGridToBitmap(100) & @LF)
ConsoleWrite("Grid 250 - Image created " & DrawGridToBitmap(250) & @LF)
ConsoleWrite("Grid 450 - Image created " & DrawGridToBitmap(450) & @LF)
ConsoleWrite("Grid 500 - Image created " & DrawGridToBitmap(500) & @LF)
ConsoleWrite("Grid 1000 - Image created " & DrawGridToBitmap(1000) & @LF)

 

Link to comment
Share on other sites

Simple way (untested though) is to create a 100x100 grid and copy/merge it 10x10 times into a 1000x1000 grid.  Out of curiosity, what is this used for ?

Edited by Nine
Link to comment
Share on other sites

I could even generate then one-by-one, draw the rectangle, draw the circle and then append it to the previous one. But the lack of knowledge prevents me to do this - I have no clue how to merge/attach to another image.

This is used as a visualization for a CNC program. It generates a CNC (G) code from an image and also generates this image as a preview to show how the result will look like (circles - holes will be cut on the raw material on the given coordinates).

Link to comment
Share on other sites

Link to comment
Share on other sites

I would create a minimal grid, let say 10x10 as an image, convert it to a texture and fill the entire rectangle with the texture. I assume it would be faster then your method, assuming the pattern repeats according to the minimum grid.

Look for _GDIPlus_TextureCreate() in the helpfile.

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

#include <GDIPlus.au3>

Global Const $iCellSize = 30
Global Const $iMaxRadius = 10
Global Const $iMinRadius = 5

; Run some tests
DrawGrid(10)
DrawGrid(100)
DrawGrid(250)
DrawGrid(500)
DrawGrid(1000)

Func DrawGrid($iSize, $iCellBackgroundColor = 0xFFFFFFFF, $iCellBorderColor = 0xFF000000, $iCellBorderSize = 1, $iCircleColor = 0xFF800000)
    Local $iStartPeak = Round((ProcessGetStats())[1] / 1024 / 1024)
    Local $iTimer = TimerInit()
    Local $iRow, $iCol, $iDiameter, $iRadius, $iCalc
    Local $iCenter = Int($iCellSize / 2)
    Local $iImgSize = $iSize * $iCellSize
    _GDIPlus_Startup()
    Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($iImgSize, $iImgSize)
    If @error Then
        ConsoleWrite('Grid size: ' & $iSize & ' - Error: _GDIPlus_BitmapCreateFromScan0' & @CRLF)
        _GDIPlus_Shutdown()
        Return
    EndIf
    Local $hCell = _GDIPlus_BitmapCreateFromScan0($iCellSize, $iCellSize)
    Local $hGraphics = _GDIPlus_ImageGetGraphicsContext($hCell)
    Local $hPen = _GDIPlus_PenCreate($iCellBorderColor, $iCellBorderSize)
    _GDIPlus_GraphicsClear($hGraphics, $iCellBackgroundColor)
    _GDIPlus_GraphicsDrawRect($hGraphics, 0, 0, $iCellSize - 1, $iCellSize - 1, $hPen)
    _GDIPlus_PenDispose($hPen)
    _GDIPlus_GraphicsDispose($hGraphics)
    Local $hTexture = _GDIPlus_TextureCreate($hCell)
    $hGraphics = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    _GDIPlus_GraphicsSetSmoothingMode($hGraphics, $GDIP_SMOOTHINGMODE_HIGHQUALITY)
    _GDIPlus_GraphicsFillRect($hGraphics, 0, 0, $iImgSize, $iImgSize, $hTexture)
    _GDIPlus_BrushDispose($hTexture)
    $hTexture = _GDIPlus_BrushCreateSolid($iCircleColor)
    ; Draw circles
    For $Index = 0 To $iSize * $iSize - 1
        $iRow = Int($Index / $iSize)
        $iCol = Mod($Index, $iSize)
        $iRadius = Random($iMinRadius, $iMaxRadius, 1)
        $iDiameter = $iRadius * 2
        $iCalc = $iCenter - $iRadius
        _GDIPlus_GraphicsFillEllipse($hGraphics, $iCol *  $iCellSize + $iCalc, $iRow * $iCellSize + $iCalc, $iDiameter, $iDiameter, $hTexture)
    Next
    _GDIPlus_BrushDispose($hTexture)
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_BitmapDispose($hCell)
    _GDIPlus_ImageSaveToFile($hBitmap, 'grid_' & $iSize & '.png')
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_Shutdown()
    Local $iDiff = TimerDiff($iTimer)
    Local $iEndPeak = Round((ProcessGetStats())[1] / 1024 / 1024)
    ConsoleWrite('Grid size: ' & $iSize & ' generated in ' & ($iDiff > 1000 ? Int($iDiff / 1000) & ' s' : Int($iDiff) & ' ms') & '. Memory peaks ' & $iStartPeak & " -> " & $iEndPeak & ' MB.' & @CRLF)
EndFunc

Results:

Grid 10: 19.5998 ms
Grid 100: 487.9959 ms
Grid 250: 3 s
Grid 500: 14 s
Grid 1000: 43 s

Last image it's not created probably due some limitations (a grid of 1000x1000 with 30 as cell size it's an image of 30000x30000 pixels) but I manage to produce an image with a cell size of 20 px. For grid I basically fill the entire image with a texture of a single cell (see @UEZ post) and for circles I use a single loop and some math (nested loops in AutoIt are really slow).

Edited by Andreik
Better statistics display.
Link to comment
Share on other sites

  • Moderators
15 minutes ago, Andreik said:

Results:

Grid 10: 19.5998 ms
Grid 100: 487.9959 ms
Grid 250: 3 s
Grid 500: 14 s
Grid 1000: 43 s

 I'm a little jealous, your computer speed is like 10% - 25% - 40% faster than mine depending on the loop stack!  These numbers don't look like much but to me it's a huge deal 😟

Grid 10: 20.7552 ms
Grid 100: 833.3427 ms
Grid 250: 4 s
Grid 500: 18 s
Grid 1000: 46 s

I need an upgrade 😔

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

Why am I getting this error...

Quote

Grid size: 10 generated in 14 ms. Memory peaks 17 -> 19 MB.
Grid size: 100 generated in 331 ms. Memory peaks 19 -> 53 MB.
Grid size: 250 generated in 2 s. Memory peaks 53 -> 234 MB.
Grid size: 500 generated in 8 s. Memory peaks 234 -> 877 MB.
Grid size: 1000 - Error: _GDIPlus_BitmapCreateFromScan0

I use bitmapcreatefromscan0 in other scripts just fine.

Some guy's script + some other guy's script = my script!

Link to comment
Share on other sites

lol, ok, removed it and got a score also 😛

Grid size: 10 generated in 14 ms. 
Grid size: 100 generated in 336 ms. 
Grid size: 250 generated in 2 s. 
Grid size: 500 generated in 8 s. 
Grid size: 1000 generated in 19 s.

Some guy's script + some other guy's script = my script!

Link to comment
Share on other sites

Merge/copy on my PC gets 2.78 sec for 500x500 on 30 px...including save

On creation only < 1 sec.

#include <GDIPlus.au3>

Local $hTimer = TimerInit()

Global Const $CELL_SIZE = 30
Global Const $MIN_CIRCLE_RADIUS = 5
Global Const $MAX_CIRCLE_RADIUS = 10

_GDIPlus_Startup()
Local $iMerge = 5
Local $hBitmap = DrawGridToBitmap(100)
Local $iDim = _GDIPlus_ImageGetWidth($hBitmap)
Local $hImage = _GDIPlus_BitmapCreateFromScan0(($iDim - 1) * $iMerge + 1, ($iDim - 1) * $iMerge + 1)
If @error Then Exit ConsoleWrite(@error & @CRLF)
Local $hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage)
For $i = 0 To $iMerge - 1
  For $j = 0 To $iMerge - 1
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, $i * ($iDim - ($i ? 1 : 0)), $j * ($iDim - ($j ? 1 : 0)), $iDim, $iDim)
  Next
Next
ConsoleWrite("Creation = " & TimerDiff($hTimer) & @CRLF)
_GDIPlus_ImageSaveToFile($hImage, "Test.jpg")
_GDIPlus_ImageDispose($hBitmap)
_GDIPlus_ImageDispose($hImage)
_GDIPlus_GraphicsDispose($hGraphic)
_GDIPlus_Shutdown()
ConsoleWrite("Final = " & TimerDiff($hTimer) & @CRLF)

Func DrawCircles($hGraphics, $GRID_SIZE)
  Local $hBrush = _GDIPlus_BrushCreateSolid(0xFFFF5050)
  For $i = 0 To $GRID_SIZE - 1
    For $j = 0 To $GRID_SIZE - 1
      Local $iRadius = Random($MIN_CIRCLE_RADIUS, $MAX_CIRCLE_RADIUS, 1)
      Local $iCenterX = $j * $CELL_SIZE + $CELL_SIZE / 2
      Local $iCenterY = $i * $CELL_SIZE + $CELL_SIZE / 2
      _GDIPlus_GraphicsFillEllipse($hGraphics, $iCenterX - $iRadius, $iCenterY - $iRadius, $iRadius * 2, $iRadius * 2, $hBrush)
    Next
  Next
  _GDIPlus_BrushDispose($hBrush)
EndFunc   ;==>DrawCircles

Func DrawGrid($hGraphics, $GRID_SIZE)
  Local $hPen = _GDIPlus_PenCreate(0xFF000000, 1)
  For $i = 0 To $GRID_SIZE
    _GDIPlus_GraphicsDrawLine($hGraphics, 0, $i * $CELL_SIZE, $GRID_SIZE * $CELL_SIZE, $i * $CELL_SIZE, $hPen)
    _GDIPlus_GraphicsDrawLine($hGraphics, $i * $CELL_SIZE, 0, $i * $CELL_SIZE, $GRID_SIZE * $CELL_SIZE, $hPen)
  Next
  _GDIPlus_PenDispose($hPen)
EndFunc   ;==>DrawGrid

Func DrawGridToBitmap($GRID_SIZE)
  Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($GRID_SIZE * $CELL_SIZE + 1, $GRID_SIZE * $CELL_SIZE + 1)
  Local $hGraphics = _GDIPlus_ImageGetGraphicsContext($hBitmap)
  _GDIPlus_GraphicsSetSmoothingMode($hGraphics, $GDIP_SMOOTHINGMODE_HIGHQUALITY)
  _GDIPlus_GraphicsClear($hGraphics, 0xFFFFFFFF)
  DrawGrid($hGraphics, $GRID_SIZE)
  DrawCircles($hGraphics, $GRID_SIZE)
  _GDIPlus_GraphicsDispose($hGraphics)
  Return $hBitmap
EndFunc   ;==>DrawGridToBitmap

 

Edited by Nine
solve issue of size
Link to comment
Share on other sites

  • Moderators
2 hours ago, Andreik said:

@SmOke_N My computer it's pretty old now. It's a Intel Core i7-8750H CPU @ 2.20GHz with 16 GB RAM. I got it like 5 years ago but it's still running good so I don't intend to get a new one soon.

Mine i7-7500U CPU @ 2.70GHz but only 8gb ram, so that makes sense to me, and my computer  not optimized because my dell doesn't like my charger so I have to cheat with throttlestop app (to bypass dell bios lock (stingy bastages)) to even get it to run like yours around 2.3ghz.

And no, didn't error check, I read what you wrote before running it and didn't care lol.

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

38 minutes ago, Nine said:

Merge/copy on my PC gets 2.78 sec for 500x500 on 30 px...including save

On creation only < 1 sec.

#include <GDIPlus.au3>

Global Const $CELL_SIZE = 30
Global Const $GRID_PADDING = 0
Global Const $MIN_CIRCLE_RADIUS = 5
Global Const $MAX_CIRCLE_RADIUS = 10

_GDIPlus_Startup()
Local $hTimer = TimerInit()
Local $merge = 5
Local $hBitmap = DrawGridToBitmap(100)
Local $iDim = _GDIPlus_ImageGetWidth($hBitmap)
Local $hImage = _GDIPlus_BitmapCreateFromScan0($iDim * $merge, $iDim * $merge)
If @error Then Exit ConsoleWrite(@error & @CRLF)
Local $hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage)
For $i = 0 To $merge - 1
  For $j = 0 To $merge - 1
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, $i * $iDim - ($i ? 2 : 0), $j * $iDim - ($j ? 2 : 0), $iDim, $iDim)
  Next
Next
ConsoleWrite("Creation = " & TimerDiff($hTimer) & @CRLF)
_GDIPlus_ImageSaveToFile($hImage, "Test.jpg")
_GDIPlus_ImageDispose($hBitmap)
_GDIPlus_ImageDispose($hImage)
_GDIPlus_GraphicsDispose($hGraphic)
_GDIPlus_Shutdown()
ConsoleWrite("Final = " & TimerDiff($hTimer) & @CRLF)

Func DrawCircles($hGraphics, $GRID_SIZE)
  Local $hBrush = _GDIPlus_BrushCreateSolid(0xFFFF5050)
  For $i = 0 To $GRID_SIZE - 1
    For $j = 0 To $GRID_SIZE - 1
      Local $iRadius = Random($MIN_CIRCLE_RADIUS, $MAX_CIRCLE_RADIUS, 1)
      Local $iCenterX = $GRID_PADDING * 1.5 + $j * ($CELL_SIZE + $GRID_PADDING) + $CELL_SIZE / 2
      Local $iCenterY = $GRID_PADDING * 1.5 + $i * ($CELL_SIZE + $GRID_PADDING) + $CELL_SIZE / 2
      _GDIPlus_GraphicsFillEllipse($hGraphics, $iCenterX - $iRadius, $iCenterY - $iRadius, $iRadius * 2, $iRadius * 2, $hBrush)
    Next
  Next
  _GDIPlus_BrushDispose($hBrush)
EndFunc   ;==>DrawCircles

Func DrawGrid($hGraphics, $GRID_SIZE)
  Local $hPen = _GDIPlus_PenCreate(0xFF000000, 1)
  For $i = 0 To $GRID_SIZE
    Local $iX = $i * ($CELL_SIZE + $GRID_PADDING)
    _GDIPlus_GraphicsDrawLine($hGraphics, $GRID_PADDING, $GRID_PADDING + $iX, $GRID_PADDING + $GRID_SIZE * ($CELL_SIZE + $GRID_PADDING), $GRID_PADDING + $iX, $hPen)
    _GDIPlus_GraphicsDrawLine($hGraphics, $GRID_PADDING + $iX, $GRID_PADDING, $GRID_PADDING + $iX, $GRID_PADDING + $GRID_SIZE * ($CELL_SIZE + $GRID_PADDING), $hPen)
  Next
  _GDIPlus_PenDispose($hPen)
EndFunc   ;==>DrawGrid

Func DrawGridToBitmap($GRID_SIZE)
  Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($GRID_SIZE * ($CELL_SIZE + $GRID_PADDING) + 2 * $GRID_PADDING + 1, $GRID_SIZE * ($CELL_SIZE + $GRID_PADDING) + 2 * $GRID_PADDING + 1)
  Local $hGraphics = _GDIPlus_ImageGetGraphicsContext($hBitmap)
  _GDIPlus_GraphicsSetSmoothingMode($hGraphics, $GDIP_SMOOTHINGMODE_HIGHQUALITY)
  _GDIPlus_GraphicsClear($hGraphics, 0xFFFFFFFF)
  DrawGrid($hGraphics, $GRID_SIZE)
  DrawCircles($hGraphics, $GRID_SIZE)
  _GDIPlus_GraphicsDispose($hGraphics)
  Return $hBitmap
EndFunc   ;==>DrawGridToBitmap

 

I assume he will use some real data for/instead of these circles and it's not interested to repeat a pattern. Also you have some minor issue with the output file, it's 15005x15005 px.

Link to comment
Share on other sites

I meant something like this here (proof of concept):

#include <GDIPlus.au3>

Global Const $CELL_SIZE = 30
Global Const $GRID_PADDING = 5
Global Const $MIN_CIRCLE_RADIUS = 5
Global Const $MAX_CIRCLE_RADIUS = 10
Global $START = TimerInit()

Func DrawCircles($hGraphics,$GRID_SIZE)
    Local $hBrush = _GDIPlus_BrushCreateSolid(0xFFFF5050)
    For $i = 0 To $GRID_SIZE - 1
        For $j = 0 To $GRID_SIZE - 1
            Local $iRadius = Random($MIN_CIRCLE_RADIUS, $MAX_CIRCLE_RADIUS, 1)
            Local $iCenterX = $GRID_PADDING * 1.5 + $j * ($CELL_SIZE + $GRID_PADDING) + $CELL_SIZE / 2
            Local $iCenterY = $GRID_PADDING * 1.5 + $i * ($CELL_SIZE + $GRID_PADDING) + $CELL_SIZE / 2
            _GDIPlus_GraphicsFillEllipse($hGraphics, $iCenterX - $iRadius, $iCenterY - $iRadius, $iRadius * 2, $iRadius * 2, $hBrush)
        Next
    Next
    _GDIPlus_BrushDispose($hBrush)
EndFunc   ;==>DrawCircles

Func DrawGrid($hGraphics,$GRID_SIZE)
    Local $hPen = _GDIPlus_PenCreate(0xFF000000, 1)
    For $i = 0 To $GRID_SIZE
        Local $iX = $i * ($CELL_SIZE + $GRID_PADDING)
        _GDIPlus_GraphicsDrawLine($hGraphics, $GRID_PADDING, $GRID_PADDING + $iX, $GRID_PADDING + $GRID_SIZE * ($CELL_SIZE + $GRID_PADDING), $GRID_PADDING + $iX, $hPen)
        _GDIPlus_GraphicsDrawLine($hGraphics, $GRID_PADDING + $iX, $GRID_PADDING, $GRID_PADDING + $iX, $GRID_PADDING + $GRID_SIZE * ($CELL_SIZE + $GRID_PADDING), $hPen)
    Next
    _GDIPlus_PenDispose($hPen)
EndFunc   ;==>DrawGrid


Func DrawGridToBitmap($GRID_SIZE)
    $aWS = ProcessGetStats()
    Local $pb = Round($aWS[1]/1024/1024)
    _GDIPlus_Startup()
    Local $iW = $GRID_SIZE * ($CELL_SIZE + $GRID_PADDING) + 2*$GRID_PADDING + 1, $iH = $GRID_SIZE * ($CELL_SIZE + $GRID_PADDING) + 2*$GRID_PADDING + 1
;~  ConsoleWrite($iW & " x " & $iH & @CRLF)
    Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH)
    Local $hBmpCtxt = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    _GDIPlus_GraphicsSetSmoothingMode($hBmpCtxt, $GDIP_SMOOTHINGMODE_HIGHQUALITY)
    _GDIPlus_GraphicsClear($hBmpCtxt, 0xFFFFFFFF)
    If $GRID_SIZE > 10 Then
        Local $iW2 = 10 * ($CELL_SIZE + $GRID_PADDING) + 2*$GRID_PADDING - 1, $iH2 = 10 * ($CELL_SIZE + $GRID_PADDING) + 2*$GRID_PADDING - 1
        Local $hBitmap2 = _GDIPlus_BitmapCreateFromScan0($iW2, $iH2), $hBmpCtxt2 = _GDIPlus_ImageGetGraphicsContext($hBitmap2)
        _GDIPlus_GraphicsClear($hBmpCtxt2, 0xFFFFFFFF)
        _GDIPlus_GraphicsSetSmoothingMode($hBmpCtxt2, $GDIP_SMOOTHINGMODE_HIGHQUALITY)
        DrawGrid($hBmpCtxt2,10)
        DrawCircles($hBmpCtxt2,10)
        Local $hTexture = _GDIPlus_TextureCreate2($hBitmap2, 5, 5, $iW2 - 9, $iH2 - 9)
        DllCall($__g_hGDIPDll, "int", "GdipTranslateTextureTransform", "handle", $hTexture, "float", 5, "float", 5, "int", 0)
        _GDIPlus_GraphicsFillRect($hBmpCtxt, 5, 5, $iW - 11, $iH - 11, $hTexture)
        _GDIPlus_GraphicsDispose($hBmpCtxt2)
        _GDIPlus_BitmapDispose($hBitmap2)
        _GDIPlus_BrushDispose($hTexture)
    Else
        DrawGrid($hBmpCtxt,$GRID_SIZE)
        DrawCircles($hBmpCtxt,$GRID_SIZE)
    EndIf
    Local $sFilePath = @ScriptDir & "\grid" & $GRID_SIZE & ".png"
    _GDIPlus_ImageSaveToFile($hBitmap, $sFilePath)
    _GDIPlus_GraphicsDispose($hBmpCtxt)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_Shutdown()
    $aWS = ProcessGetStats()
    Local $pa = Round($aWS[1]/1024/1024)
    ConsoleWrite("Runtime: " & Round(TimerDiff($START)/1000) & " seconds.Memory peaks " & $pb & " -> " & $pa & " MB" & @LF)
    $START = TimerInit()
    Return $sFilePath
EndFunc   ;==>DrawGridToBitmap

ConsoleWrite("Grid 10 - image created " & DrawGridToBitmap(10) & @LF)
ConsoleWrite("Grid 100 - Image created " & DrawGridToBitmap(100) & @LF)
ConsoleWrite("Grid 250 - Image created " & DrawGridToBitmap(250) & @LF)
ConsoleWrite("Grid 450 - Image created " & DrawGridToBitmap(450) & @LF)
ConsoleWrite("Grid 500 - Image created " & DrawGridToBitmap(500) & @LF)
ConsoleWrite("Grid 1000 - Image created " & DrawGridToBitmap(1000) & @LF)

 

Edited by UEZ
small update

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Thanks everyone for the feedback. Using texture might not be a proper solution, as it does not have a specific pattern, it is always different. I gave a try for each version posted, here are the results from my laptop:

Quote

@Andreik
Grid size: 10 generated in 36 ms. Memory peaks 20 -> 22 MB.
Grid size: 100 generated in 909 ms. Memory peaks 22 -> 56 MB.
Grid size: 250 generated in 4 s. Memory peaks 56 -> 236 MB.
Grid size: 500 generated in 17 s. Memory peaks 236 -> 880 MB.
Grid size: 1000 - Error: _GDIPlus_BitmapCreateFromScan0

@Nine
Creation = 2855.1627
Final = 7668.4703
Memory peak: 948

@UEZ
Runtime: 0 seconds.Memory peaks 20 -> 22 MB
Grid 10 - image created C:\Users\Attila\Downloads\grid10.png
Runtime: 0 seconds.Memory peaks 22 -> 69 MB
Grid 100 - Image created C:\Users\Attila\Downloads\grid100.png
Runtime: 2 seconds.Memory peaks 69 -> 315 MB
Grid 250 - Image created C:\Users\Attila\Downloads\grid250.png
Runtime: 5 seconds.Memory peaks 315 -> 970 MB
Grid 450 - Image created C:\Users\Attila\Downloads\grid450.png
Runtime: 6 seconds.Memory peaks 970 -> 1192 MB
Grid 500 - Image created C:\Users\Attila\Downloads\grid500.png
Runtime: 0 seconds.Memory peaks 1192 -> 1192 MB
Grid 1000 - Image created C:\Users\Attila\Downloads\grid1000.png

My main concern is still the memory usage, each version consumes more than 800Mb memory which is not optimal :( 
Is that possible to somehow use the texture, e.g. generate 1 grid for each diameter in the given range, and when generating the complete image just by appending each grid cell next to each other? But without keeping them in memory, dumping that into a file instead. Maybe I should also using a different image type as suggested by @junkew? I have no clue where to start :( 

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...