bitmap rotation
-
Hi.. Also mein Problem ist, dass ich ein Bild (bitmap) rotieren lassen will und es einfach nicht klappen will

Zunächst hab ich es so versucht, wie es hier beschrieben wird: http://www.forumromanum.de/member/forum/forum.cgi?USER=user_18391&ACTION=view&ENTRY=1000650082&mainid=1000650082
Wenn ich dies nun versuche (also rotateflag usw.), kommt zwar keine Fehlermeldung, aber ein Bild kommt auch nicht (schon garnicht ein rotiertest -.-)
Nun war mein nächster Versuch es mit getPixel und setPixel zu probieren (also per Hand). Glücklicherweise hab ich gleich eine page gefunden, die dies (angeblich) beschreibt: http://www.codeguru.com/Cpp/G-M/bitmap/specialeffects/article.php/c1743/
Dummweise benutzt das Programm CDC, was wohl ein typ ist, der in den MFC definiert wird. Da ich Borland c++ benutzte hab ich aber keine MFC classes (jedenfalls findet er keine AFXWIN.H -.-).
Nach dieser (erneuten) Enttäuschung dacht ich mir einfach: "ach, mach ich einfach 2 bitmaps und dann mach ich meine rotation mit setPixel und getPixel. Den cdc quatsch lass ich einfach weg :)"
Nachdem ich erfolgreich alles nach "CDC" anmutende aus dem Programm gelöscht hatte, fiel mir auf, dass setPixel und getPixel nicht funktioniert :o. Ich probierte zunächst eine BITMAP "test" zu machen und dann per test.setPixel(test,5,6,RGB(0,0,0)); einen schwarzen Pixel auf das Bild zu machen. Dies ergab (oder ergibt) den Fehler: "E2316 'setPixel' ist kein Element von 'tagBITMAP' in Funktion GetRotatedBitmap(HBITMAP__ ,float,unsigned long) in Zeile 76"
Nun dacht ich mir: "naja versuchs mal mit HBITMAP". Bei HBITMAP ergibt das Ganze folgenden, interessanten Fehler: "E2294 Auf linker Seite der Struktur ist . oder . erforderlich in Funktion GetRotatedBitmap(HBITMAP__ *,float,unsigned long) in Zeile 76"Nach zahlreichen anderen Versuchen irgendwie das Bitmap gedreht zu kriegen, wende ich mich nun an Euch mit der Bitte:
Kann mir hier vielleicht irgend einer erklären, wie zum teufel ich ein HBITMAP oder auch eine Surface mit BORLAND c++ drehen kann. Am besten so, dass ich als C++ newbie das auf verstehen (am besten auch umsetzen) kann
Danke 
-
Ich kann dir zwar keine fertige Lösung anbieten aber in der MSDN hab ich folgendes gefunden: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_0iwe.asp
Es ist praktischerweise eine einzige API-Funktion (aber leider nur verfügbar auf NT-basierenden Systemen). Nur welche Parameter man übergeben muss damit es eine Bitmap rotiert weiß ich nicht...
-
ok .. nu hab ichs zwar geschafft mein rotes TEST-Bild zu rotieren, aber nachher ist es weiß -.-. Zum rotieren hab ich folgende Methode genutzt:
HBITMAP GetRotatedBitmapNT( HBITMAP hBitmap, float radians, COLORREF clrBack ) { // Create a memory DC compatible with the display HDC sourceDC, destDC; sourceDC = CreateCompatibleDC( NULL ); destDC = CreateCompatibleDC( NULL ); // Get logical coordinates BITMAP bm; ::GetObject( hBitmap, sizeof( bm ), &bm ); float cosine = (float)cos(radians); float sine = (float)sin(radians); // Compute dimensions of the resulting bitmap // First get the coordinates of the 3 corners other than origin int x1 = (int)(bm.bmHeight * sine); int y1 = (int)(bm.bmHeight * cosine); int x2 = (int)(bm.bmWidth * cosine + bm.bmHeight * sine); int y2 = (int)(bm.bmHeight * cosine - bm.bmWidth * sine); int x3 = (int)(bm.bmWidth * cosine); int y3 = (int)(-bm.bmWidth * sine); int minx = min(0,min(x1, min(x2,x3))); int miny = min(0,min(y1, min(y2,y3))); int maxx = max(0,max(x1, max(x2,x3))); int maxy = max(0,max(y1, max(y2,y3))); int w = maxx - minx; int h = maxy - miny; // Create a bitmap to hold the result HBITMAP hbmResult = ::CreateCompatibleBitmap(CreateCompatibleDC( NULL ), w, h); HBITMAP hbmOldSource = (HBITMAP)SelectObject( sourceDC, hBitmap ); HBITMAP hbmOldDest = (HBITMAP)SelectObject( destDC, hbmResult ); //Draw the background color before we change mapping mode HBRUSH hbrBack = CreateSolidBrush( clrBack ); HBRUSH hbrOld = (HBRUSH)SelectObject( destDC, hbrBack ); PatBlt( destDC, 0, 0, w, h, PATCOPY ); ::DeleteObject( SelectObject( destDC, hbrOld ) ); // We will use world transform to rotate the bitmap SetGraphicsMode(destDC, GM_ADVANCED); XFORM xform; xform.eM11 = cosine; xform.eM12 = -sine; xform.eM21 = sine; xform.eM22 = cosine; xform.eDx = (float)-minx; xform.eDy = (float)-miny; SetWorldTransform( destDC, &xform ); // Now do the actual rotating - a pixel at a time BitBlt(destDC,0,0,bm.bmWidth, bm.bmHeight,sourceDC, 0, 0, SRCCOPY ); // Restore DCs ::SelectObject( sourceDC, hbmOldSource ); ::SelectObject( destDC, hbmOldDest ); return hbmResult; }die hier aufgerufen wird:
BOOL LoadPic(LPCSTR lpcFileName, LPDIRECTDRAWSURFACE7 *lplpDestSurf7, DDSURFACEDESC2 *lpDestDesc2) { HBITMAP hbm; BITMAP bm; HDC hdcPic, hdcSurf; hbm = (HBITMAP)LoadImage(NULL, lpcFileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION); //hier wird Rotationsmethode aufgerufen hbm = GetRotatedBitmapNT(hbm,3.1415,NULL); if (hbm == NULL) { MessageBox(NULL, "Konnte Bild nicht laden", NULL, MB_OK); return FALSE; } GetObject(hbm, sizeof(bm), &bm); lpDestDesc2->dwSize = sizeof(DDSURFACEDESC2); lpDestDesc2->dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; lpDestDesc2->ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; lpDestDesc2->ddsCaps.dwCaps2 = 0; lpDestDesc2->dwWidth = bm.bmWidth; lpDestDesc2->dwHeight = bm.bmHeight; if (lpDirectDraw->CreateSurface(lpDestDesc2, lplpDestSurf7, NULL) != DD_OK) { MessageBox(NULL, "Erzeugen der Bildzeichenfläche fehlgeschlagen!", NULL, MB_OK); DeleteObject(hbm); return FALSE; } if ((*lplpDestSurf7)->GetSurfaceDesc(lpDestDesc2) != DD_OK) { MessageBox(NULL, "Konnte komplette Bildsurfacebeschreibung nicht hohlen", NULL, MB_OK); DeleteObject(hbm); return FALSE; } hdcPic = CreateCompatibleDC(NULL); //ein Gerät im Speicher erzeugen SelectObject(hdcPic, hbm); //diesem nun das Bild zuweisen, dabei //werden vom GDI die Farben angepasst //hohlen des Gerätehandels der Bildzeichenfläche if ((*lplpDestSurf7)->GetDC(&hdcSurf) != DD_OK) { MessageBox(NULL, "GetDC der Bildzeichenfläche fehlgeschlagen", NULL, MB_OK); DeleteDC(hdcPic); DeleteObject(hbm); return FALSE; } //das kopieren der Bildinhalte von einem Gerät zum anderen BitBlt(hdcSurf, 0, 0, bm.bmWidth, bm.bmHeight, hdcPic, 0, 0, SRCCOPY); //Gerätehandel der Bildzeichenfläche wieder freigeben (*lplpDestSurf7)->ReleaseDC(hdcSurf); //dieses Gerät wieder entfernen, da es nicht mehr benötigt wird DeleteDC(hdcPic); //das Bitmap wird nicht länger gebraucht -> Speicherfreigabe DeleteObject(hbm); return TRUE; }die wiederrum in winmain aufgerufen wird
LoadPic("Test.bmp",&lpddsBitmap,&bitmapsurface); SetRect(&rectbitmap, 220, 165, 420, 315);und später dann
lpddsBack->Blt(&rectbitmap, lpddsBitmap, NULL, DDBLT_WAIT, NULL);wenn ich ein buntes auto-bild reinmache, bleibt nur ein weißer strich vom vorher so bunten auto übrig oo