NO

Author Topic: Graphics rotation problem  (Read 4003 times)

karkon

  • Guest
Graphics rotation problem
« on: February 25, 2015, 01:09:43 AM »
Hello, I am new to this forum and I will try to follow the correct protocol, but I apologize in advance if I do something wrong.

Graphics rotations using SetWorldTransform and StretchDIBits Windows API functions seems to have a problem in Pelles C V8 RC7.

I attach a sample code (full project attached as grbug.zip, main.c copied below) that displays a window with a bitmap in the center. The bitmap can be rotated using the keyboard left-right arrow keys. When the program is built with Pelles C V7 it behaves as expected. However, when it is built with Pelles C V8 RC7 the bitmap increases in size as it aproaches 45 degrees and then decreases to normal size in a ciclic way. It also shows some jerky behavior near a 45 degrees rotation.

Follows the code. The SetWorldTransform and StretchDIBits API functions are called from PaintWindow routine.
Code: [Select]
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <tchar.h>
#include <stdlib.h>
#include <math.h>
#include "main.h"

static LRESULT WINAPI MainWndProc(HWND,UINT,WPARAM,LPARAM);
static void InitGraphs(void);
static void PaintWindow(void);

static HANDLE ghInstance;
static HWND hwndMain;
static LPBITMAPINFO lpBmpInfo;
static char *lpBmpData;
static HBITMAP hbm;
static float angle=0;

int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
{
    WNDCLASSEX wc;
MSG msg;

    ghInstance = hInstance;

wc.cbSize=sizeof(WNDCLASSEX);
wc.lpszClassName="Grbug";
    wc.lpfnWndProc=MainWndProc;
    wc.style=CS_OWNDC|CS_VREDRAW|CS_HREDRAW|CS_DBLCLKS;
    wc.hInstance=ghInstance;
    wc.hIcon=LoadIcon(ghInstance, MAKEINTRESOURCE(IDR_ICO_MAIN));
    wc.hCursor=LoadCursor(NULL,IDC_ARROW);
    wc.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
    wc.cbClsExtra=0;
    wc.cbWndExtra=0;
wc.hIconSm=NULL;
    if (!RegisterClassEx(&wc))
        return(1);

    hwndMain=CreateWindow("Grbug",
"Graphics bug demo",
        WS_OVERLAPPEDWINDOW|WS_CLIPSIBLINGS|WS_MAXIMIZE,
        0,
        0,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        ghInstance,
        NULL
    );
    if (!hwndMain)
return(1);

    ShowWindow(hwndMain, nCmdShow);
    UpdateWindow(hwndMain);

for (;;)
{
BOOL fRet=GetMessage(&msg,NULL,0,0);
if (fRet==-1){
return(-1);
} else if (fRet == 0){
break;
} else {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

return(msg.wParam);
}

static LRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
    switch (msg){
case WM_CREATE:
InitGraphs();
return(0);
case WM_KEYDOWN:
switch (wParam){
case VK_LEFT:
angle+=0.05236;
if (angle>3.1416)
angle-=3.1416;
InvalidateRect(hwnd,NULL,TRUE);
UpdateWindow(hwnd);
break;
case VK_RIGHT:
angle-=0.05236;
if (angle<0)
angle+=3.1416;
InvalidateRect(hwnd,NULL,TRUE);
UpdateWindow(hwnd);
break;
default:
break;
}
return(0);
case WM_DESTROY:
PostQuitMessage(0);
return(0);
case WM_CLOSE:
if (lpBmpInfo!=NULL)
free(lpBmpInfo);
if (lpBmpData!=NULL)
free(lpBmpData);
DestroyWindow(hwnd);
return(0);
case WM_PAINT:
PaintWindow();
return(0);
        default:
            return(DefWindowProc(hwnd,msg,wParam,lParam));
    }
}

static void InitGraphs(void)
{
HDC hdc;
int ii;

hdc=GetDC(hwndMain);
if (hdc==NULL)
return;
ii=GetDeviceCaps(hdc,RASTERCAPS);
if (((ii&RC_BITBLT)==0)||((ii&RC_STRETCHDIB)==0))
return;

lpBmpInfo=malloc((256*sizeof(RGBQUAD))+sizeof(BITMAPINFOHEADER));
if (lpBmpInfo==NULL)
return;
hbm=LoadBitmap(ghInstance,MAKEINTRESOURCE(IDR_BMP_MAIN));
lpBmpInfo->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
lpBmpInfo->bmiHeader.biBitCount=0;
GetDIBits(hdc,hbm,0,0,NULL,lpBmpInfo,DIB_RGB_COLORS);
lpBmpData=malloc(lpBmpInfo->bmiHeader.biSizeImage);
if (lpBmpData==NULL)
return;
GetDIBits(hdc,hbm,0,lpBmpInfo->bmiHeader.biHeight,lpBmpData,lpBmpInfo,DIB_RGB_COLORS);
ReleaseDC(hwndMain,hdc);

return;

}

static void PaintWindow(void)
{
RECT rectclnt;
HDC hdc;
PAINTSTRUCT ps;
HRGN hRgn;
XFORM xform;

hdc=BeginPaint(hwndMain,&ps);
GetClientRect(hwndMain,&rectclnt);
hRgn=CreateRectRgnIndirect(&rectclnt);
SelectClipRgn(hdc,hRgn);
DeleteObject(hRgn);

SetGraphicsMode(hdc,GM_ADVANCED);
ModifyWorldTransform(hdc,&xform,MWT_IDENTITY);
ExtTextOut(hdc,rectclnt.left,rectclnt.top,ETO_CLIPPED|ETO_OPAQUE,&rectclnt," ",1,NULL);

xform.eM11=xform.eM22=cosf(angle);
xform.eM21=sinf(angle);
xform.eM12=-xform.eM21;
xform.eDx=(rectclnt.right+rectclnt.left)/2;
xform.eDy=(rectclnt.top+rectclnt.bottom)/2;
SetWorldTransform(hdc,&xform);

StretchDIBits(hdc,
-lpBmpInfo->bmiHeader.biWidth/2,
-lpBmpInfo->bmiHeader.biHeight/2,
lpBmpInfo->bmiHeader.biWidth,
lpBmpInfo->bmiHeader.biHeight,
0,
0,
lpBmpInfo->bmiHeader.biWidth,
lpBmpInfo->bmiHeader.biHeight,
lpBmpData,
lpBmpInfo,
DIB_RGB_COLORS,
SRCCOPY);

EndPaint(hwndMain,&ps);

return;
}

I apologize for the extension of the sample code, but even a very simple graphic program requires quite a lot of lines of code - at least with my admittedly poor programming skills.

In the meanwhile, is there any workaround for this problem?

Thanks for your help.

Offline Robert

  • Member
  • *
  • Posts: 247
Re: Graphics rotation problem
« Reply #1 on: February 25, 2015, 02:20:59 AM »
Hi Karkon:

Some of the math functions are not working as expected in Version 8 RC 7. For details please see

http://forum.pellesc.de/index.php?topic=6607.0

Robert Wishlaw

karkon

  • Guest
Re: Graphics rotation problem
« Reply #2 on: February 25, 2015, 11:31:35 AM »
Some of the math functions are not working as expected in Version 8 RC 7.

Thanks Robert, you are right. This makes more sense. I will perform a test with sines and cosines from a table to verify that the problem comes from the math functions and post here the results.

karkon

  • Guest
Re: Graphics rotation problem
« Reply #3 on: February 25, 2015, 12:47:29 PM »
Confirmed: this is the same math functions problem as in http://forum.pellesc.de/index.php?topic=6607.0