Hello all,

i coded a small routine to stretch bitmaps proporcionally, using FPU aritmethic instructions.

The problem is when is stores the value (fistp var3_WidthRatio ;----Beginning 2.3625), it just record the integer (2), not the rest.

How can i make them store the hole result for use on another part of the code ?

The code is:

; ##################################################
#######################

Paint_Proc proc hWin:DWORD, hDC:DWORD

LOCAL hOld:DWORD
LOCAL memDC :DWORD

LOCAL rect:RECT
LOCAL bmpWdt :DWORD ; The value of the final Width of BMP
LOCAL bmpHdt :DWORD ; The value of the final Heigth of BMP
LOCAL var1_BmpWidthOriginal : REAL4
LOCAL var2_BmpHeightOriginal : REAL4
LOCAL var3_WidthRatio : REAL4
LOCAL var4_HeightRatio : REAL4


invoke CreateCompatibleDC,hDC ; create memory device context
mov memDC, eax

invoke SelectObject,memDC,hBmp ; select bitmap handle into it
mov hOld, eax

invoke GetClientRect,hWnd,addr rect

.if movit == 0
; -------------------
; for normal repaint
; -------------------

; ----------Calculate the Width ratio (Client Width / Bmp Width)

mov var1_BmpWidthOriginal,320 ; Original value of the bitmap width
mov eax,rect.right ; 02F4 (756) in my case for client width
mov WidthClient,eax ; WidthClient = 02F4 (756)
fild WidthClient ; Store it (756)
fidiv var1_BmpWidthOriginal ; divide 756/320
fistp var3_WidthRatio ;----Beginning 2.3625


; ----------Calculate the Height ratio (Client Height / Bmp Height)

mov var2_BmpHeightOriginal,240
mov ebx,rect.bottom ; 020E (526) in my case for client height
mov HeightClient,ebx
fild HeightClient
fidiv var2_BmpHeightOriginal ; 526/240
fistp var4_HeightRatio ;----Beginning 2.1916666666666



mov bmpWdt,320 ; Width of the image = 320

mov bmpHdt,240 ; ---Height of the image


fild var3_WidthRatio ; Routine to put WidthRatio to RatioBuffer data (can be ripped)
fidiv RatioBufferWidthClient
fistp RatioBufferWidthClient

fild var4_HeightRatio ; Routine to put HeigthRatio to RatioBuffer data (can be ripped)
fidiv RatioBufferHeightClient
fistp RatioBufferHeightClient

.else
; --------------------------
; when you resize the window
; --------------------------
; **************************************************
******

mov eax,rect.right ; Grab the value of the new client width

mov bmpWdt,eax ; Small routine to calc the new bmp width. ; bmpwdt=EAX=Widthclient
fild bmpWdt ; Store the value of the new client width
fidiv RatioBufferWidthClient ; Divide for the ratio stored (2.3625). The problem is the ratio is 2 not 2.3625
; It can be divided by var3_WidthRatio, but the value is aproximated (no frations)
fistp bmpWdt ;(New value of bmp) ; Store as a new value for bmp width



mov ebx,rect.bottom

mov bmpHdt,ebx
fild bmpHdt
fidiv RatioBufferHeightClient ; Divide for the ratio stored (2.1916666666666). The problem is the ratio is 2 not 2.1916666666666
; It can be divided by var4_HeightRatio, but the value is aproximated (no frations)
fistp bmpHdt ;(New value of bmp)

.endif

mov eax,rect.right ; Routine to calc the coord of X point of the source (bitmap width)
sub eax,bmpWdt
shr eax,1 ; (ClientWidht-BitmapWidth)/2

mov ebx,rect.bottom ; Routine to calc the coord of Y point of the source (bitmap heigth)
sub ebx,bmpHdt
shr ebx,1 ; (ClientHeidht-BitmapHeidth)/2

invoke StretchBlt,hDC,eax,ebx,bmpWdt,bmpHdt,memDC,0,0,320
,240,SRCCOPY

mov movit,1

invoke SelectObject,hDC,hOld ; reselect the old object
invoke DeleteDC,memDC ; delete the memory device context

return 0


Paint_Proc endp


________________________________

How to make fistp stores and frational number 2.3625 and 2.1916666666666 (for height ratio) ?
It just grabbs "2", instead the rest after the dot.

That's why the image seems to jump a little. But it alters all the ratio to 2, instead the proper values.

The file with the original questions was posted at

First Message
Posted on 2002-03-07 11:38:47 by Beyond2000!
fstp to store the real.
fistp to store the integer.
Posted on 2002-03-07 11:48:54 by bitRAKE
Tks Bitrake,

but changing to fstp var3_WidthRatio, is not working.

The image is gone after clicking on the windows.

It?s not holding the hole value, it?s doing something else

For instance:

at fstp var3_WidthRatio
St=1,834999999 (according to my client rect now)
stack ss:[0064FAA8]=-1,351212e-36


Increasing a fild var3_WidthRatio (to see wich value he is grabbing)

Shows that
stack ss:[0064FAA8]=3FEB3333 (decimal 1072378675)

The stack ss:[0064FAA8] (var3_WidthRatio)
is grabbing a hugh value, instead 1,8439999

I read about fstp (0) (2) and stuff....i don?t know how to make them work putting on the stack just 1,8439999.
Posted on 2002-03-07 12:41:54 by Beyond2000!
If you fstp, the FPU stores an IEEE floating point number - this is a special format. To use this number you must not use the FPU instructions with the i - it is not an integer. You might have to store both formats for your algo? Use the floating point number internally, and the integer externally.
Posted on 2002-03-07 12:48:10 by bitRAKE
I used fstp. i typed wrong


can you show me how to do it in the code ?

I still don?t get it
Posted on 2002-03-07 12:51:24 by Beyond2000!
I've add some comments to the code:
Paint_Proc proc hWin:DWORD, hDC:DWORD


LOCAL hOld:DWORD
LOCAL memDC :DWORD

LOCAL rect:RECT
LOCAL bmpWdt :DWORD ; The value of the final Width of BMP
LOCAL bmpHdt :DWORD ; The value of the final Heigth of BMP

; Although defined as REAL4 here, intergers are put into these
; as if they were DWORDS. The data types are all mixed in the
; code below.
LOCAL var1_BmpWidthOriginal : REAL4
LOCAL var2_BmpHeightOriginal : REAL4
LOCAL var3_WidthRatio : REAL4
LOCAL var4_HeightRatio : REAL4


invoke CreateCompatibleDC,hDC ; create memory device context
mov memDC, eax

invoke SelectObject,memDC,hBmp ; select bitmap handle into it
mov hOld, eax

invoke GetClientRect,hWnd,addr rect

.if movit == 0
; -------------------
; for normal repaint
; -------------------

; ----------Calculate the Width ratio (Client Width / Bmp Width)

; var1_BmpWidthOriginal is defined as [b]REAL4[/b], but used for [b]DWORD[/b]!
mov var1_BmpWidthOriginal, 320
mov eax,rect.right ; 02F4 (756) in my case for client width
mov WidthClient,eax ; WidthClient = 02F4 (756)
fild WidthClient ; Store it (756) -- [b]integer[/b]
; var1_BmpWidthOriginal is defined as [b]REAL4[/b], but used for [b]DWORD[/b]!
fidiv var1_BmpWidthOriginal ; divide 756/320 -- [b]integer[/b]
fstp var3_WidthRatio ; Store -- [b]REAL4[/b]


; ----------Calculate the Height ratio (Client Height / Bmp Height)

mov var2_BmpHeightOriginal, 240
mov ebx,rect.bottom ; 020E (526) in my case for client height
mov HeightClient,ebx
fild HeightClient
fidiv var2_BmpHeightOriginal ; 526/240
fstp var4_HeightRatio ; Store -- [b]REAL4[/b]


mov bmpWdt,320 ; Width of the image = 320

mov bmpHdt,240 ; ---Height of the image


fld var3_WidthRatio ; -- [b]REAL4[/b]
fidiv RatioBufferWidthClient ; is this a DWORD or a REAL4?
fstp RatioBufferWidthClient

fld var4_HeightRatio ; Store -- [b]REAL4[/b]
fidiv RatioBufferHeightClient ; (same question?)
; Must store a REAL4 here, if you want to use REAL4 down further...
fstp RatioBufferHeightClient

.else
; --------------------------
; when you resize the window
; --------------------------
; **************************************************

******

mov eax,rect.right ; Grab the value of the new client width

mov bmpWdt,eax ; Small routine to calc the new bmp width. ; bmpwdt=EAX=Widthclient
fild bmpWdt ; Store the value of the new client width
fdiv RatioBufferWidthClient ; use [b]REAL4[/b]!
; this has to be [b]integer[/b] for external code use
fistp bmpWdt ;(New value of bmp) ; Store as a new value for bmp width



mov ebx,rect.bottom

mov bmpHdt,ebx
fild bmpHdt
fdiv RatioBufferHeightClient ; use [b]REAL4[/b]!
; this has to be [b]integer[/b] for external code use
fistp bmpHdt ;(New value of bmp)

.endif

mov eax,rect.right ; Routine to calc the coord of X point of the source (bitmap width)
sub eax,bmpWdt
shr eax,1 ; (ClientWidht-BitmapWidth)/2

mov ebx,rect.bottom ; Routine to calc the coord of Y point of the source (bitmap heigth)
sub ebx,bmpHdt
shr ebx,1 ; (ClientHeidht-BitmapHeidth)/2

invoke StretchBlt,hDC,eax,ebx,bmpWdt,bmpHdt,memDC,0,0,320

,240,SRCCOPY

mov movit,1

invoke SelectObject,hDC,hOld ; reselect the old object
invoke DeleteDC,memDC ; delete the memory device context

return 0

Paint_Proc endp
I didn't have a lot of time to re-write this. If you still don't understand then maybe I can add more later, or you should real the section in the Intel manual on FPU.
Posted on 2002-03-07 14:12:12 by bitRAKE
tks a lot, Bitrake,

i guess it?s working properly now.

I tryed what you said, but i am not skill enough to correct this kinda error.

About
fidiv RatioBufferWidthClient ; is this a DWORD or a REAL4?

It was a dword, but now i fixed it do Real4.

Before you answer I was trying to decrease the code parsing this part, in orther to

mov bmpWdt,eax ; Small routine to calc the new bmp width. ; bmpwdt=EAX=Widthclient
fild bmpWdt ; Store the value of the new client width
fdiv RatioBufferWidthClient , changed to goes directly to var3_WidthRatio

But it was not helping either.

Then i did what you said, changind a dword to a real4 value...

And now all seems to be Ok.

i?m checking the proportional values, and i think they are correct.

When i come home i?ll up the file.

This step was succesfully thanks to you, and now i?ll try to remove the flickering that appears, when resizing.

I?m checking the tutorial on ELF, and another posts on the board.

Tks a lot.
Posted on 2002-03-07 15:06:37 by Beyond2000!
The key is the letter Posted on 2002-03-07 15:34:22 by bitRAKE
Ok all done.


I made a few modification on the code, in orther to optimize it.


Here it:

.data

(...)
var4_HeightRatio REAL4 1.0
var3_WidthRatio REAL4 1.0

movit dd 0

.code
(...)
.elseif uMsg == WM_CREATE
mov movit ,0
mov var4_HeightRatio,1
mov var3_WidthRatio,1
(...)

Paint_Proc proc hWin:DWORD, hDC:DWORD

LOCAL hOld:DWORD
LOCAL memDC :DWORD

LOCAL rect:RECT
LOCAL bmpWdt :DWORD ; The value of the final Width of BMP
LOCAL bmpHdt :DWORD ; The value of the final Heigth of BMP
LOCAL var1_BmpWidthOriginal : DWORD
LOCAL var2_BmpHeightOriginal : DWORD


invoke CreateCompatibleDC,hDC ; create memory device context
mov memDC, eax

invoke SelectObject,memDC,hBmp ; select bitmap handle into it
mov hOld, eax

invoke GetClientRect,hWnd,addr rect

.if movit == 0
; -------------------
; for normal repaint
; -------------------

; ----------Calculate the Width ratio (Client Width / Bmp Width)

mov var1_BmpWidthOriginal,320 ; Original value of the bitmap width
mov eax,rect.right ; 02F4 (756) in my case for client width
mov WidthClient,eax ; WidthClient = 02F4 (756)
fild WidthClient ; Store it (756) -- integer


fidiv var1_BmpWidthOriginal ; divide 756/320 -- integer
fstp var3_WidthRatio ;----Beginning 2.3625 Store -- REAL4


; ----------Calculate the Height ratio (Client Height / Bmp Height)

mov var2_BmpHeightOriginal,240
mov ebx,rect.bottom ; 020E (526) in my case for client height
mov HeightClient,ebx
fild HeightClient
fidiv var2_BmpHeightOriginal ; 526/240
fstp var4_HeightRatio ;----Beginning 2.1916666666666 Store -- REAL4



mov bmpWdt,320 ; Width of the image = 320

mov bmpHdt,240 ; ---Height of the image


.else
; --------------------------
; when you resize the window
; --------------------------
; ********************************************************

mov eax,rect.right ; Grab the value of the new client width

mov bmpWdt,eax ; Small routine to calc the new bmp width. bmpwdt=EAX=Widthclient
fild bmpWdt ; Store the value of the new client width
fdiv var3_WidthRatio ; Divide for the ratio stored (2.3625).
; used REAL4!
; this has to be integer for external code use
fistp bmpWdt ;(New value of bmp) ; Store as a new value for bmp width



mov ebx,rect.bottom

mov bmpHdt,ebx
fild bmpHdt
fdiv var4_HeightRatio ; Divide for the ratio stored (2.1916666666666).
; used REAL4!
; this has to be integer for external code use
fistp bmpHdt ;(New value of bmp)

.endif

mov eax,rect.right ; Routine to calc the coord of X point of the source (bitmap width)
sub eax,bmpWdt
shr eax,1 ; (ClientWidht-BitmapWidth)/2

mov ebx,rect.bottom ; Routine to calc the coord of Y point of the source (bitmap heigth)
sub ebx,bmpHdt
shr ebx,1 ; (ClientHeidht-BitmapHeidth)/2

invoke StretchBlt,hDC,eax,ebx,bmpWdt,bmpHdt,memDC,0,0,320,240,SRCCOPY

mov movit,1

invoke SelectObject,hDC,hOld ; reselect the old object
invoke DeleteDC,memDC ; delete the memory device context

return 0


Paint_Proc endp

------- ONLY problem with flickering on NT/2k ----- i'm trying to fix it right now

Here is the final file
Posted on 2002-03-07 19:11:33 by Beyond2000!
Beyond2000!, looks really good - very solid code.
	.data?

var4_HeightRatio REAL4 ?
var3_WidthRatio REAL4 ?

movit dd ?
These are always initialized during
execution - don't really need to do both.
Posted on 2002-03-07 20:00:16 by bitRAKE
Tks again bitRAKE

I changed to dd ?


Thanks for the complement too :alright:


I'm trying to solve the flickering.

I am checking the instructions that E?in post.

The app flicks on Win2K/NT. I'll try to code a backbuffer for it.

I don't now hot to do it now, but i am looking for it.

it doesn't sems to be so hard, i hope.

Oh,....
i removed
.elseif uMsg == WM_CREATE
; mov movit ,0
; mov var4_HeightRatio,1
; mov var3_WidthRatio,1

too.

just using

.elseif uMsg == WM_CREATE
(...)


Oh, and it's using 968k to 1008k in memory usage. I assume this is due to the bitmap loading. The bigger the bitmap in resource more memory used.

I'll see if i can use less memory even with bigger bitmaps. Like the function invoke DeleteObject
Posted on 2002-03-07 20:26:50 by Beyond2000!
Neither E?in, or Chris Hobbs tutorials are helping


I don't know what is doing wrong.

The is the altered code for eliminating screen flicker
Posted on 2002-03-08 01:00:40 by Beyond2000!
The problem here is that the CS_HREDRAW and CS_VREDRAW styles force a complete redraw of the window which you try to do as well. So remove them and add in the following code which does all the drawing first to a back buffer and then blits it to your window.

In the data? section add
bDc dd ?

bBm dd ?
bBw dd ?
bBh dd ?

In the WM_CREATE message put
invoke CreateCompatibleDC,0

mov bDc,eax

In WM_SIZE
invoke InvalidateRect,hWnd,0,0

And in Paint_Proc after
GetClientRect
    mov eax,rect.right

mov edx,rect.bottom
or eax,0Fh
or edx,0Fh
cmp eax,bBw
jne Chg
cmp edx,bBh
je nChg
Chg:mov bBw,eax
mov bBh,edx
invoke DeleteObject,bBm
invoke CreateBitmap,bBw,bBh,1,32,0
mov bBm,eax
invoke SelectObject,bDc,eax
nChg:

invoke FillRect,bDc,addr rect,0

And replace StretchBlt with
invoke StretchBlt,bDc,eax,ebx,bmpWdt,bmpHdt,memDC,0,0,320,240,SRCCOPY	

invoke BitBlt,hDC,0,0,rect.right,rect.bottom,bDc,0,0,SRCCOPY
And finally in WM_DESTROY
invoke DeleteDC,bDc

invoke DeleteObject,bBm
Posted on 2002-03-08 07:20:24 by Eóin
Tks a lot Eoin.


Is the backbuffer responsable for the white screen ? I mean , can i change to the windows color (gray, black etc) ?

Or if i change the background with an menu, is this the responsable ?
invoke CreateBitmap,bBw,bBh,1,32,0

On win98 the central image is not being shown.

I had to change to what Bitrake told

.data?
var4_HeightRatio REAL4 ?
var3_WidthRatio REAL4 ?

movit dd ?
removed the related mov on WM_CREATE.

And changed

invoke StretchBlt,bDc,eax,ebx,bmpWdt,bmpHdt,memDC,0,0,320,240,SRCCOPY

to
invoke StretchBlt,hDC,eax,ebx,bmpWdt,bmpHdt,memDC,0,0,320,240,SRCCOPY.

I didn?t test on win2k yet (i?m not at home now).

If it stills don?t work on win2k after those changes, maybe The
Paint_Proc function should have another variable.

Like:

Paint_Proc proc hWin:DWORD, hDC:DWORD,bDC:DWORD

and remove bDC from the data? section.


Or it could have 02 calls. Like (this work on W98):

invoke StretchBlt,hDC,eax,ebx,bmpWdt,bmpHdt,memDC,0,0,320,240,SRCCOPY

invoke StretchBlt,bDc,eax,ebx,bmpWdt,bmpHdt,memDC,0,0,320,240,SRCCOPY

invoke BitBlt,hDC,0,0,rect.right,rect.bottom,bDc,0,0,SRCCOPY

I?ll test it later. If anyone can test it now....it will be welcome to report any bugs on the code.
Posted on 2002-03-08 09:03:17 by Beyond2000!
Here is the altered file
Posted on 2002-03-08 11:24:35 by Beyond2000!
I noticed on the most recent file that you duplicated the StretchBlt function at the end of the Paint procedure. Once I commented one out it ran properly.

Oh yeah I also had to remove the CS_xREDRAW styles from the WndClass struct at the start, that removed the flickering.
mov wc.style,          CS_BYTEALIGNWINDOW

As for the colour of the background, sure you can change it. I used FillRect with 0 as the brush parameter (the last one) so it defaulted to white. You can easily create your own brushs through the API, eg CreateSolidBrush .

And if there was anything you want explained from the code just ask, I was busy yesterday so I didn't comment it. :rolleyes:
Posted on 2002-03-09 12:52:08 by Eóin