Jump to content

Recommended Posts

Posted

Let's say I have the following:

dim $matrix[10][10]

for $y = 0 to 9
    for $x = 0 to 9
        $matrix[$x][$y] = 0xFFFFFFFF
    Next
Next

$matrix[5][5] = 0xFF000000

Imagine $matrix as an image. A white background with a black dot in the center.

I want to save this image as jpg, png or whatever.

Is there a good way to do it?

I wrote a program which uses _GDIPlus_GraphicsFillRect to create a lot of 1x1 px squares, but it's really slow and unpractical.

Would be glad for any help.

Posted

Why not just create an image outside of autoit? What is this program going to be used for? It seems a little pointless to me.

Posted (edited)

Here is one method.

#include <WinAPI.au3>
#include <GDIPlus.au3>
;#include <Array.au3>

Local $sFilename, $begin, $aArr, $time, $iColor, $iW, $iH

$sFilename = @ScriptDir & "\TestWhiteBlackDot.png" ;bmp"
$iW = 10
$iH = 10

Dim $matrix[10][10]

For $y = 0 To 9
    For $x = 0 To 9
        $matrix[$x][$y] = 0xFFFFFFFF ; Colour format is 0xBBGGRRAA
    Next
Next
$matrix[5][5] = 0x000000FF ; Colour format is 0xBBGGRRAA

$begin = TimerInit()

_FileArrayToImage($sFilename, $matrix)

ConsoleWrite("Time taken = " & Round(TimerDiff($begin) / 1000, 3) & " secs" & @CRLF)
ShellExecute($sFilename)


Func _FileArrayToImage($filename, $aArr)
    Local $iW = UBound($aArr, 1), $iH = UBound($aArr, 2), $sResult = ""
    Local $hBMP, $hImage1, $Reslt, $width, $height, $stride, $format, $Scan0
    Local $sResult, $v_BufferA
    $hBMP = _WinAPI_CreateBitmap($iW, $iH, 1, 32)
    _GDIPlus_Startup()
    $hImage1 = _GDIPlus_BitmapCreateFromHBITMAP($hBMP)

    $Reslt = _GDIPlus_BitmapLockBits($hImage1, 0, 0, $iW, $iH, $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")

    $v_BufferA = DllStructCreate("byte[" & $height * $width * 4 & "]", $Scan0)
    ;$AllPixels = DllStructGetData($v_BufferA, 1)

    For $y = 0 To $height - 1
        For $x = 0 To $width - 1
            $sResult &= Hex($aArr[$x][$y], 8)
        Next
    Next

    DllStructSetData($v_BufferA, 1, "0x" & StringStripWS($sResult, 8))

    _GDIPlus_BitmapUnlockBits($hImage1, $Reslt)
    _GDIPlus_ImageSaveToFile($hImage1, $filename)

    _GDIPlus_ImageDispose($hImage1)
    _WinAPI_DeleteObject($hBMP)
    _GDIPlus_Shutdown()
    Return
EndFunc ;==>_FileArrayToImage

Edit: Removed unnecessary DllStructGetData()'s used for debugging.

Added all variable declarations.

Edited by Malkey
Posted (edited)

I managed to hack/build a similar example but with SDL.

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseX64=n
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#Include "SDL.au3"

_SDL_Init($_SDL_INIT_VIDEO)

Global $sFilename = @DesktopDir & "\TestWhiteBlackDot.bmp"
Local $iTimer

Global $aMatrix[1000][1000]

For $iY = 0 To 999
    For $iX = 0 To 999
        $aMatrix[$iX][$iY] = 0xFFFFFFFF ; Colour format is 0xRRGGBB(AA?)
    Next
Next
$aMatrix[5][5] = 0 ; Colour format is 0xRRGGBB(AA?)

$iTimer = TimerInit()

_FileArrayToImage($sFilename, $aMatrix)

ConsoleWrite("Time taken = " & Round(TimerDiff($iTimer) / 1000, 3) & " secs" & @CRLF)
;~ ShellExecute($sFilename)

Func _FileArrayToImage($sFilename, $aMatrix)
    Local $iW = UBound($aMatrix, 1), $iH = UBound($aMatrix, 2), $sResult = ""

    For $iY = 0 To $iH -1
        For $iX = 0 To $iW -1
            $sResult &= Hex($aMatrix[$iX][$iY])
        Next
    Next

    $pSurface = _SDL_CreateRGBSurface($_SDL_SWSURFACE, $iW, $iH, 32, 0, 0, 0, 0)

    $Struct = DllStructCreate($tagSDL_SURFACE, $pSurface)
    $PtrStruct = DllStructGetData($Struct, "format")
    $Struct2 = DllStructCreate($tagSDL_PixelFormat, $PtrStruct)
    $Bpp = DllStructGetData($Struct2, "BytesPerPixel")
    $Pixels = DllStructGetData($Struct, "pixels")
    $Pitch = DllStructGetData($Struct, "pitch")

    $P = $Pixels + 0 * $Pitch + 0 * $Bpp

    $Struct = DllStructCreate("byte[" & $iW * $iH * $Bpp & "]", $P)
    DllStructSetData($Struct, 1, "0x" & $sResult)

    _SDL_SaveBMP($pSurface, $sFilename)
    _SDL_FreeSurface($pSurface)
EndFunc

The difference? The file is saved as bmp.

Edited by AdmiralAlkex
Posted

Thanks for all the help!!

AdmiralAlkex: Your example became incredibly slow with bigger images (even 100x100).

Malkey: That's perfect! It's really fast and does an excellent job. I can't thank you enough!

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
  • Recently Browsing   0 members

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