News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

draw a bitmap

Started by rafilla, June 06, 2006, 11:16:39 AM

Previous topic - Next topic

rafilla

Hello, I'm new in masm. I'm spanish. My question is about of having a segment of memory, how I draw it in the screen?
I don't know if you could understand me, my english isn't very well.
I want to have a VIDEO RAM, draw it, modify it in memory and automatically draw it in screen
I want that  in screen appears is a segment of memory.
HOW??

stanhebben

I suppose you want to do this in 16-bit real mode. (windows won't allow that)

The vga video ram starts at address 0A0000h, in which you can write directly. Use
   mov ax, 0A000h
   mov es, ax
to set es (you can use anothing segment register too, of course) to the video ram segment.

By default, your video ram will interpret the data as characters, but by using bios interrupt 10h you can set the video mode. Note that, using vga interrupts, you can only do low-resolution drawing.

Setting the vga mode to 320x200x256 colors, for example:
   mov ah, 0
   mov al, 13h
   int 10h

I'm not completely sure if 13h is 320x200, I grabbed it from a table. Higher resolution modes exist, but then you need to store more that 64K, and I have no idea about how to handle that. (in real mode)

Everything is also drawn automatically.

Stan

redskull

in case you're talking about protected mode windows programs, you need to use the following functions, in order:

GetDC - gets a device context to the screen
CreateCompatibleDC - creates a 'compatible DC' (in the memory)
CreateCompatibleBitmap - creates a bitmap identical to the size/resolution of the screen
SelectObject - selects the compatible bitmap into the memory DC
LineTo, Ellipse, Rectangle - draws on the memory DC
BitBlt - copies the contents of the memory DC to the actual Screen
ReleaseDC - release the screen
DeleteDC - removes the memory RAM
DeleteObject - erases the bitmap

It doesn't 'directly' modify the screen, like in real mode, but it's about as close as you can come

here's a good example for Ice's site

http://spiff.tripnet.se/~iczelion/files/ESF.zip
Strange women, lying in ponds, distributing swords, is no basis for a system of government

rafilla

Exactly as wrote redskull. Thank you redskull, thank you Stan.
I need this functions, GetDC, CreateCompatibledC and BitBlt. And now, how I modify this DC byte to byte?
Where is the documentation for this functions?
I still need to learn infinite things
Saludos desde España!!

mnemonic

Quote from: rafilla on June 06, 2006, 04:38:26 PM
Where is the documentation for this functions?

http://msdn.com
Where you will find many other things too.  :wink
Be kind. Everyone you meet is fighting a hard battle.--Plato
-------
How To Ask Questions The Smart Way

redskull

Do you have specific requirements to draw to the memory first?  I don't know exactly what you're aiming to do, but it's a common mistake (at least for me it was) to assume that windows graphics work like DOS graphics (having to draw the video memory to work the display).  If you're just asking a generic 'how to draw on the screen in Windows', you'll be happy to know you don't need to mess around with the CreateCompatibleDC and BitBlt, you just need to obtain the DC (Device Context) to the screen and use the drawing functions directly.  The Memory DC method is mostly used for animation to reduce screen flickering ("double buffering" or "dirty rectangles").  SetPixel and GetPixel can be used to work the screen byte for byte, at least from a graphics standpoint.  I'm not sure if you can use standard MOV instructions to work the memory of a DC, but I highly doubt it.

regards, alan
Strange women, lying in ponds, distributing swords, is no basis for a system of government

Phoenix

You can modify Bitmap Bits directly using GDIplus.dll flat api calls, have a look at GdipBitmapLockBits (MSDN, Google). This function returns a BitmapData-structure containing a pointer to your bitmap.

A while ago i have played with this function: http://www.masm32.com/board/index.php?topic=155.0
It is a simple fire simulation, done by direct (bitmap) memory manipulation.

Siekmanski

hello rafilla

Instead of using "CreateCompatibleBitmap" you can use "CreateDIBSection" and recieve a pointer to the bitmapdata, write to it and then blit it to screen.
Or if it has to be fast you can try DIRECTDRAW7 to acces the bitmap data directly.

stanhebben

I wrote this some time ago:

hWnd - target window
imgwidth - width of the image you want to draw
imgheight - height of the image
imgbits - the raw image, 32 bits per pixel

paintToWindow proc hWnd:DWORD, imgwidth:DWORD, imgheight:DWORD, imgbits:DWORD

LOCAL bmi:BITMAPINFO
LOCAL ps:PAINTSTRUCT
LOCAL targetdc:DWORD

push esi

lea eax, ps
push eax
push hWnd
call BeginPaint
mov targetdc, eax
test eax, eax
jz _cantcreatedc

mov bmi.bmiHeader.biSize, sizeof BITMAPINFOHEADER
mov bmi.bmiHeader.biBitCount, 32
mov eax, imgwidth
mov bmi.bmiHeader.biWidth, eax
mov ebx, imgheight
neg ebx
mov bmi.bmiHeader.biHeight, ebx
neg ebx
mov bmi.bmiHeader.biPlanes, 1
mov bmi.bmiHeader.biCompression, BI_RGB
mul ebx
shl eax, 2
mov bmi.bmiHeader.biSizeImage, eax
mov bmi.bmiHeader.biXPelsPerMeter, 0
mov bmi.bmiHeader.biYPelsPerMeter, 0
mov bmi.bmiHeader.biClrUsed, 0
mov bmi.bmiHeader.biClrImportant, 0

push DIB_RGB_COLORS
lea eax, bmi
push eax
push imgbits
push imgheight
push 0
push 0
push 0
push imgheight
push imgwidth
push 0
push 0
push targetdc
call SetDIBitsToDevice
test eax, eax
jz _cantsetbits

lea eax, ps
push eax
push hWnd
call EndPaint

pop esi
mov eax, 1
ret

_cantcreatedc:
; handle error here

pop esi
xor eax, eax
ret

_cantsetbits:
; handle error here

pop esi
xor eax, eax
ret

paintToWindow endp


I changed it a little to fit in a more general environment, but I hope this can be of any use to you.

Stan

asmfan

Stan, some questions on your proc. It's can be used while processing wm_paint only BeginPaint & EndPaint is recommended for this case only. The second one - can we fill the bitmapInfo (particullary header) beforehand (outside the wm_paint message processing)? And the last one - why do you store the negative value for height in infoHeader?
Thanks.
Russia is a weird place

stanhebben

This procedure must indeed only be used in response to a WM_PAINT message.

The bitmap header can indeed be reused between several calls, as long as all field are set correctly.

And as for the last question: Bitmaps are normally stored upside down. But by passing in a negative value for the height, this is no longer the case. That makes life a bit easier to me when I want to build up the image. (I use it for owner-drawn components)

Stan