Jump to content
Sign in to follow this  
Drifter

Bitmap Drawing without opening Ms Paint?

Recommended Posts

Drifter

Is it possible to put data into a bitmap file without opening Mspaint.exe? I will deal with what to do with each pixel but if there was a com object or some other way in which i could specify the dimensions of a picture and then set each pixels color with full RGB ("24-bit" ?) and then save the file somewhere that would be awesome!

I could do it opening mspaint but that way is messy! Does what I'm looking for exist? ;)

Share this post


Link to post
Share on other sites
AlmarM

I think you should take a look at _GDIPlus_Bitmap functions. ;)


Minesweeper

A minesweeper game created in autoit, source available.

_Mouse_UDF

An UDF for registering functions to mouse events, made in pure autoit.

2D Hitbox Editor

A 2D hitbox editor for quick creation of 2D sphere and rectangle hitboxes.

Share this post


Link to post
Share on other sites
Drifter

I think you're right. I did look all over but I guess I didn't know i was looking for GDI.

Would you write in individual pixels using _GDIPlus_GraphicsDrawLine() with the same start and end points?

I'll have a deeper look at this later, as I just found out I have to do something else. I'll post again if I get stuck. Thanks for the good starting place!

Share this post


Link to post
Share on other sites
AlmarM

You know what, i'll start learning these _GDIPlus_Bitmap functions myself too.

Might be useful, never used them before. ;)


Minesweeper

A minesweeper game created in autoit, source available.

_Mouse_UDF

An UDF for registering functions to mouse events, made in pure autoit.

2D Hitbox Editor

A 2D hitbox editor for quick creation of 2D sphere and rectangle hitboxes.

Share this post


Link to post
Share on other sites
Drifter

haha, nice one. I see how its used in general sort of, but the examples only show screen captures... *digs into the help file and gets his mental juices flowing* ;)

Edit: By the way, i think i did use this (GDI) to make a new form of clock (it uses a polar equation with 24 petals, each representing the passing of an hour)... but that was drawing directly to the screen, not using bitmaps. :)

Edited by Drifter

Share this post


Link to post
Share on other sites
Drifter

Looking at the example given in the help file with the create pen function we have

$hGraphic = _GDIPlus_GraphicsCreateFromHWND ($hGUI)
    $hPen = _GDIPlus_PenCreate ()
    _GDIPlus_GraphicsDrawLine ($hGraphic, 10, 150, 390, 150, $hPen

So could i do what i want if i just replaced $hGraphic with the file i want somehow? And if so how is that even done?

_GDIPlus_BitmapCreateFromFile() has no option to size the bitmap, and to be honest I'm not even sure if it returns the right type of object or if it would create a new file if it didn't already exist.

Share this post


Link to post
Share on other sites
AndyG

GDI+ is not nessecary...because *.BMP is a very easy Fileformat.

The header ist 54 Bytes long and decribes the properties of the Bitmap. In the most cases Bitmaps have no additional Colour-Palette, so the "Pixels" directly follow the Header. You can find the description of the 54 Header bytes after some googeling.

Here and here are examples of writing Bitmaps directly to file without the need of some gaphics stuff...(you will need the BMP created by the script of the first link to run the script of the 2nd link)

Share this post


Link to post
Share on other sites
Drifter

hmm, a novel idea, but i cant wrap my head around some of the stuff. Also I'd like standard RGB and no idea how to switch from BGR.... lol...

still thinking GDI+ to be honest unless i can start making sense of your first link... ;)

Share this post


Link to post
Share on other sites
AndyG

The "sense" is, that the BMP-Format is used to display Windows (and their content) onto the screen.

If you can handle the BMP-Format, it doesn´t make any difference to "write" a bitmap into a file or into a window! And there is no(t much) difference to "change Pixels" in a file or in a window.

Also I'd like standard RGB and no idea how to switch from BGR...

There is no need to "switch" from RGB to BGR if you are creating or working on bitmaps. If you "read" a bitmap from a file or a "pixel" from the screen, there is no RGB anywhere! BGR ist the only thing you will need ;) . I admit, that playing around with "Standard-RGB" (GDI+) and BGR-Bitmaps at the same time can be difficult sometimes, but where is written that the life is easy? (I think, someone has written a RGB2BGR-Function before :))

Share this post


Link to post
Share on other sites
Drifter

The "sense" is, that the BMP-Format is used to display Windows (and their content) onto the screen.

If you can handle the BMP-Format, it doesn´t make any difference to "write" a bitmap into a file or into a window! And there is no(t much) difference to "change Pixels" in a file or in a window.

I do think your idea is quite creative. However if what you say is true, shouldn't it be easy to go with GDI+ ?

All that I would need to do is use:

_GDIPlus_GraphicsDrawLine($hGraphic, 10, 150, 390, 150, $hPen)

and somehow have $hGraphic be a file instead of the screen, since I've worked with the screen before.

Apologies if I seem somewhat stubborn, but this approach seems easier to me... am I correct that it could be done in this way?

Share this post


Link to post
Share on other sites
AndyG

something like this?

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

    ; Initialize GDI+ library
    _GDIPlus_Startup ()
    _ScreenCapture_Capture("screenshot.bmp")  ;create some bitmap

;load bitmap
    $hBitmap = _GDIPlus_BitmapCreateFromFile (@scriptdir & "\screenshot.bmp")
;get context
    $hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
;draw somethinginto context
    $hPen = _GDIPlus_PenCreate()
    _GDIPlus_GraphicsDrawLine($hBuffer,10 , 10, 500,500, $hPen)
    _GDIPlus_GraphicsDrawRect($hBuffer, 100, 100, 400, 300)
    _GDIPlus_GraphicsDrawEllipse($hBuffer, 130, 100, 140, 70)

    ; Save bitmap to file
    _GDIPlus_ImageSaveToFile ($hbitmap, @scriptdir & "\screenshot_line.bmp")

    ; Clean up resources
    _GDIPlus_BitmapDispose ($hBitmap)

    ; Shut down GDI+ library
    _GDIPlus_ShutDown ()

shellexecute("screenshot_line.bmp")

Share this post


Link to post
Share on other sites
Drifter

Thats almost exactly what I need! :)

....except it needs to be a particular size...

;note: $height and $width are just here for representation...
_ScreenCapture_Capture("screenshot.bmp",0,0,$width,$height)

.... and i could do without the screenshot in the background. any idea how to "clear the canvas" without drawing black/white lines across the image? (not sure what i want BG color to be yet)

Maybe theres a square i could draw over the whole thing thats filled? ;)

So far all i can think of is _GDIPlus_GraphicsDrawRect() with a VERY thick pen? :P haha!

Edit: _GDIPlus_GraphicsFillRect() found it! thanks for your time and patience with my ways ;)

Edited by Drifter

Share this post


Link to post
Share on other sites
AndyG

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

    ; Initialize GDI+ library
    _GDIPlus_Startup ()

    $hdc=_WinAPI_GetDC(0)  ;DC Desktop
    $hbmp=_WinAPI_CreateCompatibleBitmap($hdc,500,500)   ;size
    $hbitmap=_GDIPlus_BitmapCreateFromHBITMAP($hBmp)    ;get bitmap



    $hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    ;draw somethinginto context
    $hPen = _GDIPlus_PenCreate(0xFFFEFF00)
    _GDIPlus_GraphicsDrawLine($hBuffer,10 , 10, 500,500, $hPen)
    _GDIPlus_GraphicsDrawRect($hBuffer, 100, 100, 400, 300,$hpen)
    _GDIPlus_GraphicsDrawEllipse($hBuffer, 130, 100, 140, 70,$hpen)

    ; Save bitmap to file
    _GDIPlus_ImageSaveToFile ($hbitmap, @scriptdir & "\screenshot_line.bmp")

    ; Clean up resources
    _GDIPlus_BitmapDispose ($hBitmap)

    ; Shut down GDI+ library
    _GDIPlus_ShutDown ()

shellexecute("screenshot_line.bmp")

Share this post


Link to post
Share on other sites
Drifter

very nice, thanks alot!

Share this post


Link to post
Share on other sites
UEZ

Try this:

#include <GDIPlus.au3>
_GDIPlus_Startup()

$hBitmap = _GDIPlus_BitmapCreateFromScan0(500, 500)
$hContext = _GDIPlus_ImageGetGraphicsContext($hBitmap)
_GDIPlus_GraphicsSetSmoothingMode($hContext, 2)

$hBrush = _GDIPlus_BrushCreateSolid(0xFF8090F0)
_GDIPlus_GraphicsClear($hContext, 0xFF000000)

_GDIPlus_GraphicsFillRect($hContext, 10, 10, 480, 480, $hBrush)
_GDIPlus_BrushSetSolidColor($hBrush, 0x8050F0F0)
_GDIPlus_GraphicsFillEllipse($hContext, 100, 100, 300, 300, $hBrush)
_GDIPlus_GraphicsDrawString($hContext, "Fast hack by UEZ 2010 ;-)", 180, 240)

_GDIPlus_ImageSaveToFile($hBitmap, @ScriptDir & "\Test.jpg")

_GDIPlus_BrushDispose($hBrush)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_GraphicsDispose($hContext)
_GDIPlus_Shutdown()

ShellExecute(@ScriptDir & "\Test.jpg")
Exit

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

Br,

UEZ

PS: Here another version! I overlooked the version from AndyG's (post#13) during coding the example above ;)

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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites
Drifter

ummmm.... that's nice.... but i just want to know how I can make GDI draw a single pixel, it doesn't seem to want to.

Share this post


Link to post
Share on other sites
UEZ

Only a pixel in the middle of the window:

#include <GDIPlus.au3>
_GDIPlus_Startup()

$hBitmap = _GDIPlus_BitmapCreateFromScan0(500, 500)
$hContext = _GDIPlus_ImageGetGraphicsContext($hBitmap)
_GDIPlus_GraphicsSetSmoothingMode($hContext, 2)

$hBrush = _GDIPlus_BrushCreateSolid(0xFF000000)
_GDIPlus_GraphicsClear($hContext, 0xFFFFFFFF)

_GDIPlus_GraphicsFillRect($hContext, 250, 250, 2, 2, $hBrush)

_GDIPlus_ImageSaveToFile($hBitmap, @ScriptDir & "\Test.jpg")

_GDIPlus_BrushDispose($hBrush)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_GraphicsDispose($hContext)
_GDIPlus_Shutdown()

ShellExecute(@ScriptDir & "\Test.jpg")
Exit

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

Or without using a brush:

#include <GDIPlus.au3>
_GDIPlus_Startup()

$hBitmap = _GDIPlus_BitmapCreateFromScan0(500, 500)
$hContext = _GDIPlus_ImageGetGraphicsContext($hBitmap)
_GDIPlus_GraphicsSetSmoothingMode($hContext, 2)
_GDIPlus_GraphicsClear($hContext, 0xFFFFFFFF)

_GDIPlus_BitmapSetPixel($hBitmap, 250, 250, 0xFF000000)
_GDIPlus_BitmapSetPixel($hBitmap, 251, 250, 0xFF000000)
_GDIPlus_BitmapSetPixel($hBitmap, 250, 251, 0xFF000000)
_GDIPlus_BitmapSetPixel($hBitmap, 251, 251, 0xFF000000)

_GDIPlus_ImageSaveToFile($hBitmap, @ScriptDir & "\Test.jpg")

_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_GraphicsDispose($hContext)
_GDIPlus_Shutdown()

ShellExecute(@ScriptDir & "\Test.jpg")
Exit

Func _GDIPlus_BitmapSetPixel($hBitmap, $iX, $iY, $iARGB = 0xFFFFFFFF)
    Local $aRet
    $aRet = DllCall($ghGDIPDll, "int", "GdipBitmapSetPixel", "hwnd", $hBitmap, "int", $iX, "int", $iY, "dword", $iARGB)
    Return
EndFunc ;==>_GDIPlus_BitmapSetPixel

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

Br,

UEZ

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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites
Drifter

Nice one ;)

Don't even need a pen, thanks alot!

Edited by Drifter

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  

×