News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Operations on bitmap file

Started by ktosik2, July 13, 2015, 07:25:32 PM

Previous topic - Next topic

ktosik2

#45
The main file (PNPZ.ASM) is a little big, there are many places where I put CreateDIBSection calls, names of menu items are in polish language, and they are doing something different than their names suggest.

dedndave

usually, you can just make a small test program
once that code is working, adapt it into your larger project

you can imagine how many man-hours it would take if all the forum members wrote a test piece   :biggrin:

dedndave

the paint code in the child proc looks, well, ok
it should draw the bitmap to the display DC, provided it makes it through the if/then/else stuff   :P

if you feel the program isn't reaching that point, you can put something in there to verify
i sometimes use a very short beep
    INVOKE  Beep,800,30
for example - that lets me know that the if/then/else structure is allowing the paint code to happen

not sure i really like that particular code, where you use strcmp to compare a dword handle   :redface:

another way is to use a debugger, set up as the JIT exception handler
you can temporarily insert INT 3 and, if you are getting to that point, the debugger will come up
    INT     3    ;stop code and open JIT handler

of course, you can do that with no JIT debugger, and the program will terminate with an invalid instruction exception

ktosik2

Ok, I try to do something else.
This is code in WM_PAINT section:

LOCAL redvalue: BYTE
LOCAL greenvalue: BYTE
LOCAL bluevalue: BYTE
(...)
.ELSEIF uMsg==WM_PAINT
INVOKE BeginPaint, hChild, ADDR ps
mov    hdc, eax
.IF czyWczytanoPlik==1
INVOKE CreateCompatibleDC, hdc
mov    hMemDC, eax
INVOKE SelectObject, hMemDC, hBitmap
;;INVOKE GetClientRect, hChild, ADDR rect
;;INVOKE BitBlt, hdc, 0, 0, rect.right, rect.bottom, hMemDC, 0, 0, SRCCOPY
;;INVOKE DeleteDC, hMemDC
;;INVOKE EndPaint, hChild, ADDR ps
INVOKE  BitBlt,hdc,0,0,imageWidth, imageHeight,hMemDC,0,0,SRCCOPY

mov redvalue, 0
mov greenvalue, 0
mov bluevalue, 255
RGB redvalue, greenvalue, bluevalue
mov colorref, eax
INVOKE SetPixel, hdc, 5, 5, colorref
INVOKE SetPixel, hdc, 4, 5, colorref
INVOKE SetPixel, hdc, 5, 4, colorref
INVOKE SetPixel, hdc, 4, 4, colorref

INVOKE GetPixel, hdc, 5, 5
mov colorref, eax
movzx eax, BYTE PTR [colorref + 2]
PrintDec eax ;blue color
INVOKE  DeleteDC, hMemDC
.ENDIF

and it is working right, when window is repainted, text eax = 255 appears in Debug Window.
But if I want to do this:

INVOKE GetPixel, hdc, 5, 5
mov colorref, eax

movzx eax, BYTE PTR [colorref + 2]
mov bluevalue, eax
PrintDec bluevalue

and this:

INVOKE GetPixel, hdc, 5, 5
mov colorref, eax

movzx eax, BYTE PTR [colorref + 2]
push eax
pop bluevalue

PrintDec bluevalue

I get: error A2070: invalid instruction operands in:

mov bluevalue, eax

and

pop bluevalue

What is wrong with this instructions? Is there a possibility to store for example blue color in bluevalue variable?

If I use:

LOCAL bluevalued: DWORD

instead of bluevalue after GetPixel it is working, but if I write

push BYTE PTR bluevalued

it is not working (invalid instruction operands). Why?

TouEnMasm

Quote
push BYTE PTR bluevalued

couldn't  push byte must be word (taking care of stack align 32..),DWORD
Fa is a musical note to play with CL

rrr314159

#50
Hi ktosik2,

congrats on getting the picture to display! :t Your new problem is much simpler, you're using byte where it must be dword.

LOCAL bluevalue: BYTE ; fine
mov bluevalue, eax   ; no good, dword can't go into a byte location

push eax        ; fine - these two lines another attempt to put eax into bluevalue
pop bluevalue ; no good, byte's can't be pushed / popped.


- Obvious fix is simply:

mov bluevalue, al

- Apparently because of these problems you tried making bluevalue a DWORD (bluevalued), which I think is not the right way to go. Without running the code, I think you should leave bluevalue a BYTE and always mov al, not eax, into it.

When reading from the bytes you're using

movzx eax, BYTE PTR [colorref + 2]

- That's fine but apparently u could simply

mov al, BYTE PTR [colorref + 2]

Bottom line use al when dealing with bytes and if needed, push / pop eax
I am NaN ;)

ktosik2

rrr314159, thanks for your help (and for congratulations)!

ktosik2

Because I can't make a dib section (in pvBits) from loaded image,  I want to do something different.

1. Load an image.
2. When it is displaying for the first time in WM_PAINT section, create blank dib section with CreateDIB24 (thanks DednDave!).
3. In loop:  use GetPixel to get color of the pixel and write it to pvBits of the new blank one created by CreateDIB24.

I have few problems with this and I can't solve 2 of them.
The code should looks more or less like this:

.IF firstShow==1
INVOKE CreateCompatibleDC, hdc
mov    hMemDC, eax
INVOKE SelectObject, hMemDC, hBitmap
INVOKE  BitBlt,hdc,0,0,imageWidth, imageHeight,hMemDC,0,0,SRCCOPY

INVOKE CreateDIB24, imageWidth, imageHeight
mov hBitmapOryginal, eax ;hBMP
mov pvBitsOryginal, edx

mov ypos,0
mov ecx, imageHeight
.WHILE ypos < ecx
mov xpos, 0
mov ecx, imageWidth
.WHILE xpos < ecx
INVOKE GetPixel, hdc, xpos, ypos
mov colorref, eax
INVOKE GetRValue, colorref
mov redvalue, al
INVOKE GetGValue, colorref
mov greenvalue, al
INVOKE GetBValue, colorref
mov bluevalue, al

mov eax, ypos
mul imageHeight
add eax, xpos

mov edx, pvBitsOryginal
xor ebx, ebx
mov bl, bluevalue
;mov bh, greenvalue

; mov DWORD ptr [edx+eax], ebx not working properly with eax
; mov DWORD ptr [edx+ypos*imageHeight+xpos], ebx

mov DWORD ptr [edx], ebx
mov DWORD ptr [edx+3], ebx
mov DWORD ptr [edx+6], ebx
mov DWORD ptr [edx+9], ebx
mov DWORD ptr [edx+12], ebx

inc xpos
mov ecx, imageWidth
.ENDW

inc ypos
mov ecx, imageHeight
.ENDW
INVOKE  DeleteDC, hMemDC
mov firstShow,0
.ENDIF



First problem is connected with calculating positions of next pixels. If I write something like this:

mov DWORD ptr [edx+eax], ebx

it is not really the position of the pixel, the image looks strange, and at this line:

mov DWORD ptr [edx+ypos*imageHeight+xpos], ebx

there is an error: constant expected. How to do it properly?

And the second problem. In code I have BYTE variables and I can do such things:

mov bl, bluevalue
; mov bh, greenvalue
mov DWORD ptr [edx], ebx

I can put bluevalue and greenvalue into pixel in pvBits, but I don't know how to put all three color components into pixel in pvBits. How to do it?

dedndave

the way i usually use a DIB section

create the DIB section in WM_CREATE code
delete the DIB section in WM_DESTROY code

in WM_PAINT code...
BeginPaint
create compatible DC (memory DC)
select the DIB section into the memory DC
then BitBlt from the memory DC to the display DC
delete the memory DC
EndPaint

optionally, you can create the memory DC in WM_CREATE and "keep it alive"
but - that uses system resources
and, creating and deleting a memory DC is very fast, so it doesn't slow paint down

dedndave

i think this one shows you what i mean
it's not a 24-bit DIB, but the code is otherwise the same

ktosik2

Thanks DednDave for tips and the example.
Could someone help me to solve the first problem that I described in my previous post (the second I solved)? Later I will need it because I will have to modify the images, and I will have to access to the pixels.

TouEnMasm


This example is made for you,he modify the bitmap with c++(It's a mix code asm,c++)
See the .cpp
It's an animated region who can use all the graphic format supported by Windows (in resource or file)
http://masm32.com/board/index.php?topic=1917.msg19916#msg19916
Fa is a musical note to play with CL

ktosik2

Thank you for this example, thank you all for your help!

dedndave

unless you specify a negative value for DIB height, rows are written in bottom-to-top order
this is the "natural" order for BMP files (an old windows 1.0 thing - upside down and backwards)

because it is a 24-bit DIB, each pixel uses 3 bytes: blue, green, red (backwards - lol)
so, the first 3 bytes of the buffer are for the bottom row, left column

there is a rule that applies to ALL BMP files and DIB's
the number of bytes for each row must be evenly divisable by 4

so, if you have a DIB that is 11 pixels wide (11x3 = 33), each row will use 36 bytes
the extra bytes are usually filled with 0's

from that information, you can calculate the buffer offset for any X,Y position