Entwickler-Ecke
Multimedia / Grafik - Kleines Bild, z.B. Spielfigur, drehen
JayEff - So 09.10.05 17:28
Titel: Kleines Bild, z.B. Spielfigur, drehen
Hi Leute. Hab die Suche grade ne Stunde lang bemüht und hab tatsächlich was gefunden:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117:
| procedure RotateBitmapA(var Bitmap: TBitmap; const ADegrees: Cardinal; const clBack: TColor); const MaxPixelCount = 32768;
type pRGBArray = ^TRGBArray; TRGBArray = array [0..MaxPixelCount-1] of TRGBTriple;
var cosTheta : DOUBLE; i : INTEGER; iRotationAxis : INTEGER; iOriginal : INTEGER; iPrime : INTEGER; iPrimeRotated : INTEGER; j : INTEGER; jRotationAxis : INTEGER; jOriginal : INTEGER; jPrime : INTEGER; jPrimeRotated : INTEGER; RowOriginal : pRGBArray; RowRotated : pRGBArray; sinTheta : DOUBLE; Theta : DOUBLE; OldHeight : INTEGER; OldWidth : INTEGER; NewWidth : INTEGER; NewHeight : INTEGER; BitmapRotated : TBitmap; Back : RGBTriple; begin Back.rgbtBlue := GetBValue(clBack); Back.rgbtGreen := GetGValue(clBack); Back.rgbtRed := GetRValue(clBack);
Theta := ADegrees * PI /180; sinTheta := Sin(Theta); cosTheta := Cos(Theta);
OldWidth := Bitmap.Width; OldHeight := Bitmap.Height;
NewWidth := Abs(Round(OldHeight * sinTheta)) + Abs(Round(OldWidth * cosTheta)); NewHeight := Abs(Round(OldWidth * sinTheta)) + Abs(Round(OldHeight * cosTheta));
BitmapRotated := TBitmap.Create; BitmapRotated.Width := NewWidth; BitmapRotated.Height := NewHeight; BitmapRotated.PixelFormat := pf24bit; BitmapRotated.Canvas.Brush.Color := clBack; BitmapRotated.Canvas.FillRect(Rect(0, 0, NewWidth, NewHeight));
iRotationAxis := OldWidth div 2; jRotationAxis := OldHeight div 2;
for J := BitmapRotated.Height - 1 downto 0 do begin RowRotated := BitmapRotated.Scanline[J]; jPrime := 2*(J - (NewHeight - OldHeight) div 2 - jRotationAxis) + 1 ;
for I := NewWidth - 1 downto 0 do begin iPrime := 2*(I - (NewWidth - OldWidth) div 2 - iRotationAxis) + 1;
iPrimeRotated := Round(iPrime * CosTheta - jPrime * sinTheta); jPrimeRotated := Round(iPrime * sinTheta + jPrime * cosTheta);
iOriginal := (iPrimeRotated - 1) div 2 + iRotationAxis; jOriginal := (jPrimeRotated - 1) div 2 + jRotationAxis;
if (iOriginal >= 0) and (iOriginal <= Bitmap.Width - 1) and (jOriginal >= 0) and (jOriginal <= Bitmap.Height - 1) then begin RowOriginal := Bitmap.Scanline[jOriginal]; RowRotated[I] := RowOriginal[iOriginal] end end; end; Bitmap.Assign(BitmapRotated); BitmapRotated.Free; end; |
Na Klasse. Nach vielem Rumprobieren, bei dem ich des öfteren nur leere Images bekommen habe (Image1.Canvas.Draw(1,1,bit) wobei bit eine eigentlich gedrehte Bitmap ist), habe ich nun Folgendes getippselt:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| procedure TForm1.Button1Click(Sender: TObject); var bit:TBitmap; begin bit:=TBitmap.Create; bit.LoadFromFile('C:\bildchen.bmp'); Rotatebitmapa(bit,50,clWhite); bit.SaveToFile('C:\bildchen.bmp'); bit.Free; end; |
klappt ganz gut, nur... das ergebnis. wenns am anfang sowas ist:
passiert das:
einmal drehen:
zweimal drehen:
10 mal drehen:
http://jayy.de/10mal.JPG(ist zu groß...)
Ihr seht: Die Bitmap wird größer und ganz grieselig. Was kann man da machen?? gibt es keinen Algorithmus, der mir ein Ergebnis liefert, das genauso groß ist wie das alte, und auch nach mehrmaligem Drehen gleich bleibt? gut, das mehrmalige drehen ließe sich umgehen in dem man immer von ursprünglichen Image ausgeht und eine andere gradzahl benutzt, anders wirds wohl eh nicht gehen.
Zusammenfassung: Was ich brauche: Eine kleine Spielfigur in einer Image komponente oder ähnlichem Drehen. Was nicht klappt: Figur wird griselig, und nicht auf dem Image angezeigt, Image wird leer.
Lossy eX - So 09.10.05 20:28
Drehe doch immer das Original! Damit sollten die Ergebnisse in dem Fall so optimal wie möglich sein. Um es besser hinbekommen zu können müsstest du den Algo so umbauen, dass die Randpixel interpoliert werden. Die dürften dann transparent sein und somit hast du dein ganzes System ausgebremst. Aber auch dann solltest du auf die originale zurückgreifen, da durch jede Drehungen das Bild verändert wird.
Du kannst entweder auf so etwas wie
Graphics32 [
http://www.g32.org/graphics32/] umsteigen. Damit bleibst du aber auf der Softwarevariante was immer einen gewissen Geschwindigkeitsnachteil hat. Oder aber du steigst auf eine hardwarebeschleunigte Variante um. Im persönlich würde dafür
OpenGL [
http://www.delphigl.com] empfehlen.
[edit] habe irgendwie überlesen, dass es sich um eine
Spielfigur handelt. Wenn du vor hast ein Spiel zu machen würde ich dir in jedem Fall raten dir etwas anderes zu überlegen. Mit einem TImage und dem manuellen Rotieren dürftest du da recht schnell an die Grenzen des Machbarem gelangen.
JayEff - Mo 10.10.05 17:42
Es wird ein dermaßen simples Spiel ^^ Kleine Vektorberechnungen im zweidimensionalen mit Vogelperspektive... ich könnte die Spielfiguren in eine TImageList laden, also zu Programmstart 36 mal drehen und zwar immer um 10° mehr, so stand es in einem anderen Thread... Nur eines: interpolieren??? muss ich gleich mal danach Googlen. Bringt das dann am Ende den Effekt, dass das gesamte Bild NICHT größer wird, als es vorher war? :) das wär schonmal ein Fortschritt ^^
Lossy eX - Di 11.10.05 09:08
Also du solltest IMMER um das Originalbild drehen. Interpolieren x 36 sieht auch bescheiden aus. Wobei du das Problem haben dürftest, dass die Ränder deiner Figut auch weich würden. Und die Ränder weich zu zeichnen würde mehr oder weniger darauf hin hinaus laufen, dass du jedes Pixel einzen zeichnen müsstest. Was natürlich alles Andere als einfach ist.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!