Jump to content

Output 2D-Array to image


Recommended Posts

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.

Link to comment
Share on other sites

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
Link to comment
Share on other sites

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
Link to comment
Share on other sites

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!

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...