I wanted to rotate a bitmap by 90 degrees, so I used the SetWorldTransform function but it doesn't work at all...  :sad: The image I see after calling this function is a normal image without any rotation...

My code


WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

LOCAL ps:PAINTSTRUCT
LOCAL hdc:HDC
LOCAL hMemDC:HDC
LOCAL rect:RECT
LOCAL xform:XFORM

.IF uMsg==WM_DESTROY
invoke DeleteObject,hFile0
invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_CREATE
invoke CreateWindowEx,NULL,ADDR EditClass,NULL,\
WS_VISIBLE or WS_CHILD or ES_LEFT or ES_MULTILINE or\
ES_AUTOHSCROLL or ES_AUTOVSCROLL,0,\
0,0,0,hWnd,EditID,\
hInstance,NULL
mov hwndEdit,eax

mov ofn1.lStructSize,SIZEOF ofn1
push hWnd
pop  ofn1.hWndOwner
push hInstance
pop  ofn1.hInstance
mov  ofn1.lpstrFilter, OFFSET FilterString
mov  ofn1.lpstrFile, OFFSET buffer
mov  ofn1.nMaxFile,MAXSIZE 
                         
invoke GetMenu,hWnd
mov  hMenu,eax

.ELSEIF uMsg==WM_COMMAND
mov eax,wParam
.IF lParam==0
.IF ax==IDM_OTWORZ
mov  ofn1.Flags, OFN_FILEMUSTEXIST or \
OFN_PATHMUSTEXIST or OFN_LONGNAMES or\
OFN_EXPLORER or OFN_HIDEREADONLY
invoke GetOpenFileName, ADDR ofn1
.IF eax==TRUE
mov eax, LR_CREATEDIBSECTION or  LR_LOADFROMFILE
invoke LoadImage,NULL, ofn1.lpstrFile, IMAGE_BITMAP,0,0,eax
mov hFile0,eax
invoke InvalidateRect,hWnd,NULL,TRUE

.ENDIF
.ELSEIF ax==IDM_KONIEC
invoke PostQuitMessage,0
.ENDIF
.ENDIF
.ELSEIF uMsg==WM_PAINT
invoke BeginPaint, hWnd, ADDR ps
invoke GetDC, hWnd ;?
mov hdc, eax
invoke CreateCompatibleDC, hdc
mov hMemDC, eax

invoke GetClientRect, hWnd, ADDR rect
invoke SelectObject, hMemDC, hFile0

invoke SetGraphicsMode, hdc, GM_ADVANCED

mov xform.eM11, 0
mov xform.eM12, 1
mov xform.eM21, -1
mov xform.eM22, 0
mov xform.ex, 0
mov xform.ey, 0

;invoke SetMapMode, hdc, MM_LOENGLISH
;invoke SetViewportOrgEx, hdc, 0, 0, NULL

invoke SetWorldTransform, hdc, ADDR xform

invoke BitBlt, hdc, 0, 0, rect.right, rect.bottom, hMemDC, 0, 0, SRCCOPY
invoke DeleteDC, hMemDC
invoke ReleaseDC, hWnd, hdc
invoke EndPaint, hWnd, ADDR ps
.ELSE
invoke DefWindowProc, hWnd, uMsg, wParam, lParam
ret
.ENDIF

xor eax, eax
ret
WndProc endp


Can anyone help me? please
Posted on 2006-05-21 04:40:25 by carlos_84
Ok... the only thing i can immediately see that might cause it not to work is that you're not running a new enough windows version: windows 95 (and i think 98) don't support GM_ADVANCED, so world transforms don't work on that.

Nope... just noticed another possibility - I seem to remember that you must set the transform back at the end of painting: add these lines

	invoke ModifyWorldTransform, hdc, NULL, MWT_IDENTITY
invoke SetGraphicsMode, hdc, GM_COMPATIBLE


Hope that helps,
Ossa

(by the way, there is no need to use GetDC to get the window DC - BeginPaint returns it anyway and will also set the element of the PAINTSTRUCT with it (ps.hdc))
Posted on 2006-05-21 05:18:09 by Ossa
I'm using WinXP

I've changed the code to:


invoke SetWorldTransform, hdc, ADDR xform

invoke BitBlt, hdc, 0, 0, rect.right, rect.bottom, hMemDC, 0, 0, SRCCOPY

invoke ModifyWorldTransform, hdc, NULL, MWT_IDENTITY
invoke SetGraphicsMode, hdc, GM_COMPATIBLE


but it didn't help
Posted on 2006-05-21 06:11:34 by carlos_84
I have not used SetWorldTransform but to rotate a bitmap I use the following from my graphics library. It works well and is fairly quick though not "lightning fast". Note that it will only work with 32 bit DIB sections...

GetRotatedBitmap FRAME hDIB,radians,clrBack
uses edi,esi,ebx
; From a C routine by Zafir Anjum
; This routine has been radically altered to support DIB sections
; instead of straight DDBs, that way the results can be used immediately
; and the pointers are easier to get.
LOCAL bminfo :DIBSECTION
LOCAL bmInfoResult :DIBSECTION
LOCAL cosine,sine :D ; REAL4
LOCAL tfloat,tfloat1 :D ; REAL4
LOCAL nHeight,nWidth :D
LOCAL negHeight :D
LOCAL nRowBytes :D
LOCAL lpDIBBits :D
LOCAL x1,x2,x3,maxx,minx,w :D
LOCAL y1,y2,y3,maxy,miny,h :D
LOCAL nResultRowBytes :D
LOCAL hDIBResult :D
LOCAL lpDIBBitsResult :D
LOCAL sourcex,sourcey :D
LOCAL bmi :BITMAPINFO
LOCAL ppvBits :D

mov eax,
bswap eax
shr eax,8
mov ,eax

invoke GetObjectA,,SIZEOF DIBSECTION,offset bminfo

mov eax,
mov ,eax
or eax,eax
jns >
; must be bottom up origin
xor eax,eax
ret
:
neg eax
mov ,eax

mov eax,
mov ,eax

mov eax,
shl eax,5 ; mul x 32 bpp
add eax,31
and eax,-31
shr eax,3
mov ,eax

mov eax,
cmp eax,BI_RGB
je >
; must be uncompressed
xor eax,eax
ret
:

mov eax,
mov ,eax

; I suck at FPU stuff

fld D
fcos
fstp D

fld D
fsin
fstp D

fild D
fmul D
fistp D

fild D
fmul D
fistp D

fild D
fmul D
fstp D

fild D
fmul D
fsub D
fistp D

fild D
fmul D
fstp D

fild D
fmul D
fadd D
fistp D


fild D
fmul D
fistp D

fild D
fmul D
fistp D

; Find the minimum x quantity
mov eax,
cmp eax,
jl >
mov eax,
:
cmp eax,
jl >
mov eax,
:
cmp eax,0
jl >
mov eax,0
:
mov ,eax

; Find the minimum y quantity
mov eax,
cmp eax,
jl >
mov eax,
:
cmp eax,
jl >
mov eax,
:
cmp eax,0
jl >
mov eax,0
:
mov ,eax

mov eax,
cmp eax,
jg >
mov eax,
:
cmp eax,
jg >
mov eax,
:
cmp eax,0
jge >
xor eax,eax
:
mov ,eax

sub eax,
mov ,eax

mov eax,
cmp eax,
jg >
mov eax,
:
cmp eax,
jg >
mov eax,
:
cmp eax,0
jge >
xor eax,eax
:
mov ,eax
sub eax,
mov ,eax

mov eax,
shl eax,5 ; mul x 32 bpp
add eax,31
and eax,-31
shr eax,3
mov ,eax

invoke GetDC,0
push eax
; invoke CreateIndependantBitmap,eax,,

mov D,SIZEOF BITMAPINFOHEADER
mov ecx,
mov ,ecx
mov ecx,
mov D,ecx
mov W,1
mov W,32
mov D,BI_RGB
invoke CreateDIBSection,eax,ADDR bmi,DIB_RGB_COLORS,ADDR ppvBits,NULL,NULL
mov ,eax
pop eax
invoke ReleaseDC,0,eax

invoke GetObjectA,,SIZEOF DIBSECTION,offset bmInfoResult
mov eax,
mov ,eax

xor edi,edi
L1:
xor esi,esi
L2:
mov eax,esi
add eax,
mov ,eax
fild D
fmul D
fstp D

mov eax,edi
add eax,
mov ,eax
fild D
fmul D
fadd D
fistp D

mov eax,esi
add eax,
mov ,eax
fild D
fmul D
fstp D

mov eax,edi
add eax,
mov ,eax
fild D
fmul D
fsub D
fistp D

cmp D,0
jl >>L3
mov eax,
cmp D,eax
jge >>L3
cmp D,0
jl >>L3
mov eax,
cmp D,eax
jge >>L3

mov ecx,
mov eax,
mul D
add ecx,eax
mov eax,
shl eax,2
add ecx,eax
mov ebx,

mov ecx,
mov eax,

mul edi
add ecx,eax
mov eax, esi
shl eax,2
add ecx,eax
mov ,ebx
jmp >>L4
L3:
mov ecx,
mov eax,
mul edi
add ecx,eax
mov eax,esi
shl eax,2
add ecx,eax
mov eax,
mov ,eax
L4:
inc esi
cmp esi,
jl <<L2

inc edi
cmp edi,
jl <<L1

mov eax,

RET
ENDF
Posted on 2006-05-21 09:41:49 by donkey
Maybe this can help?

I seem to remember that you must set the transform back at the end of painting

Accrorgind to PSDK, you have to do this ONLY if you want to go back to GM_COMPATIBLE mode.
The SetWorldTransform function will fail unless the graphics mode for the given device context has been set to GM_ADVANCED by previously calling the SetGraphicsMode function. Likewise, it will not be possible to reset the graphics mode for the device context to the default GM_COMPATIBLE mode, unless the world transformation has first been reset to the default identity transformation by calling SetWorldTransform or ModifyWorldTransform.
Posted on 2006-05-21 09:52:48 by ti_mo_n

I seem to remember that you must set the transform back at the end of painting

Accrorgind to PSDK, you have to do this ONLY if you want to go back to GM_COMPATIBLE mode.


I'm aware of that, but IIRC from when I fiddled about with it (nearly two years ago now, so I'm a bit rusty), I seemed to get very odd behavior if I finished the paint without returning to GM_COMPATIBLE.

I could well have remembered wrong though.

Ossa
Posted on 2006-05-21 10:24:17 by Ossa
XFORM works with floating point values, not integers.
Also you must call SetViewportOrgEx before SetWorldTransform.


		invoke SetGraphicsMode, hdc, GM_ADVANCED
invoke SetViewportOrgEx, hdc, 20, 20, NULL

mov xform.eM11, 0
mov xform.eM12, 3F800000h  ; 1.0
mov xform.eM21, 0BF800000h ; -1.0
mov xform.eM22, 0
mov xform.ex, 0
mov xform.ey, 0
invoke SetWorldTransform, hdc, ADDR xform



(I don't know about the height/width and required placement of the bitmap you are using, so the above SetViewportOrgEx mapping coordinates were chosen randomly. Obviously you'll need to adjust that to fit your needs.)
Posted on 2006-05-21 11:55:48 by arafel
thank's, now it's working (after changing to floating point values)

P.S. silly mistake ...  :oops:
Posted on 2006-05-21 15:29:27 by carlos_84

thank's, now it's working (after changing to floating point values)

P.S. silly mistake ...  :oops:

It's an easy enough mistake to do when assuming everything is a DWORD :)

A bit weird that the XFORM struct in the masm32 header files is defined as DWORDs when it should be REAL4s, considering that there's a few other structs in there that does use REAL4s.

Not that it would make a difference error-message wise anyway, and appearantly masm doesn't support floating-point immediate values: lala.asm(37) : error A2050: real or BCD number not allowed (that's for a struct defined using REAL4).
Posted on 2006-05-21 15:37:06 by f0dder