Sign in to follow this  
Followers 0
dpryan

Create Image from Matrix

5 posts in this topic

I would like to save an image (PNG or BMP) to disk based on data that I have in a sparse matrix. (There are only a handful of pixels that I need to paint, even though the total image size may be large.)

Ideally, the image would be able to have transparency, but I can live without.

I'm not sure if this is the correct approach, but I've created a dummy GUI with a graphics object, and painted some of the pixels using something like the following:

$Graphic = GUICtrlCreateGraphic (0,0,100,100)

GUICtrlSetGraphic($Graphic,$GUI_GR_COLOR,$color)

GUICtrlSetGraphic($Graphic,$GUI_GR_PIXEL,$x,$y)

When I display the GUI, the graphic looks correct. But I'm not sure how to save that image to disk. Ideally, I wouldn't have to even display the GUI (since I really just want to convert the matrix to an image file).

I've tried some combinations of _GDIPlus_ImageGetGraphicsContext and _GDIPlus_BitmapCreateFromGraphics, and I think ultimately I'll need to use _GDIPlus_ImageSaveToFile, but I feel like I'm not hitting the right combination of functions.

Any ideas?

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

I guess displaying the GUI, using _ScreenCapture_CaptureWnd, and deleting the GUI works well enough for now.

I'd still like to know if there is a better solution.

Perhaps it's possible to create an image array using DllStructCreate("DWORD[10000]")? Then edit the pixels by using DllStructSetData and pass a pointer to the array to _WinAPI_CreateBitmap (specifying a 32 bit per pixel image). Not sure.

Edited by dpryan

Share this post


Link to post
Share on other sites

Here is how i will do it... i am a off of coding practice so ask wherever you want to know or you don`t understand, i will try to answer.

#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>
#include <winapi.au3>

Global Const $IMAGE_BITMAP = 0
Global Const $STM_SETIMAGE = 0x172

Global $iWidth = 100
Global $iHeight = 100

; Creating GUI, Save Button and Pic Control...
$hGUI = GUICreate("Graphic")
GUISetBkColor(0xABCDEF)
$iPic = GUICtrlCreatePic("", 0, 0, $iWidth, $iHeight)
$iButton1 = GUICtrlCreateButton("Save To File...", 0, 370, 200, 30)
$iButton2 = GUICtrlCreateButton("Generate Random Image...", 200, 370, 200, 30)

; Creating an empty image and getting the graphic context...
_GDIPlus_Startup()
$hImage = _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight)
$hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage)

; Drawing random points...
$hPen = _GDIPlus_PenCreate(0xFF000000)
Local $i
For $y = 0 To $iHeight
    For $x = 0 To $iWidth
        $i = Random(0, 1, 1)
        If $i = 1 Then
            _GDIPlus_PenSetColor($hPen, 0xFFFFFFFF) ; If i = 1 then white
        Else
            _GDIPlus_PenSetColor($hPen, 0xFF000000) ; If i = 0 then black
        EndIf
        _GDIPlus_GraphicsDrawRect($hGraphic, $x, $y, 1, 1, $hPen) ; Creating Squares of 1X1(dots)
    Next
Next

; Showing the Image in the Pic Control...
$hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
GUICtrlSendMsg($iPic, $STM_SETIMAGE, $IMAGE_BITMAP, $hBitmap)
_WinAPI_DeleteObject($hBitmap)

; Showing the GUI and the starting the main loop...
GUISetState()

While True
    $iMsg = GUIGetMsg()
    Switch $iMsg
        Case -3
            _GDIPlus_PenDispose($hPen)
            _GDIPlus_GraphicsDispose($hGraphic)
            _GDIPlus_ImageDispose($hImage)
            _GDIPlus_Shutdown()
            Exit
        Case $iButton1
            _GDIPlus_ImageSaveToFile($hImage, @DesktopDir & "\temp.png")
        Case $iButton2
            Local $i
            For $y = 0 To $iHeight
                For $x = 0 To $iWidth
                    $i = Random(0, 1, 1)
                    If $i = 1 Then
                        _GDIPlus_PenSetColor($hPen, 0xFFFFFFFF) ; If i = 1 then white
                    Else
                        _GDIPlus_PenSetColor($hPen, 0xFF000000) ; If i = 0 then black
                    EndIf
                    _GDIPlus_GraphicsDrawRect($hGraphic, $x, $y, 1, 1, $hPen) ; Creating Squares of 1X1(dots)
                Next
            Next
            $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
            GUICtrlSendMsg($iPic, $STM_SETIMAGE, $IMAGE_BITMAP, $hBitmap)
            _WinAPI_DeleteObject($hBitmap)
    EndSwitch

WEnd

Func _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight, $iStride = 0, $iPixelFormat = 0x0026200A, $pScan0 = 0)
    Local $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromScan0", "int", $iWidth, "int", $iHeight, "int", $iStride, "int", $iPixelFormat, "ptr", $pScan0, "int*", 0)
    If @error Then Return SetError(@error, @extended, 0)
    Return $aResult[6]
EndFunc   ;==>_GDIPlus_BitmapCreateFromScan0
1 person likes this

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

Wow, perfect. Just what I was looking for. Thanks for the "_GDIPlus_BitmapCreateFromScan0" function.

Looks like your magic code works like this:

Create an image: $hImage = _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight)

Get a graphics handle to the image object: $hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage)

Draw to that graphics object: _GDIPlus_GraphicsDrawXXXXX functions

Get a bitmap from the image: $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)

Save to disk: _GDIPlus_ImageSaveToFile($hImage, $filepath)

Edit: I guess you don't need to "get the bitmap from the image" unless you're painting it to a GUI (which I'm not doing).

Edited by dpryan

Share this post


Link to post
Share on other sites

Wow, perfect. Just what I was looking for. Thanks for the "_GDIPlus_BitmapCreateFromScan0" function.

Looks like your magic code works like this:

Create an image: $hImage = _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight)

Get a graphics handle to the image object: $hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage)

Draw to that graphics object: _GDIPlus_GraphicsDrawXXXXX functions

Get a bitmap from the image: $hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)

Save to disk: _GDIPlus_ImageSaveToFile($hImage, $filepath)

Edit: I guess you don't need to "get the bitmap from the image" unless you're painting it to a GUI (which I'm not doing).

That is right!

Share this post


Link to post
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
Sign in to follow this  
Followers 0