![]() |
AW: Bitmap erstellen und mit Direct2D zeichnen
Liste der Anhänge anzeigen (Anzahl: 1)
Ich finds ja genau so gruselig wie ihr alle aber ich kenne keine andere Methode es so hinzukrigen wie ich es gerne haben will...
Am liebsten wäre es mir sowieso ohne TBitmap auszukommen um auch Transparente Ebenen anwenden zu können. Im Anhang ist ein Bild wie ich es gerne hätte und wie es bisher auch funktioniert, nur halt mit der langsamen Pixels Methode... :/ Eigentlich sind das einfach nur 2 Bitmaps (Eigene Klasse) die Pixel für Pixel gezeichnet werden. |
AW: Bitmap erstellen und mit Direct2D zeichnen
Also du willst ein Bitmap über ein anderes zeichnen?
|
AW: Bitmap erstellen und mit Direct2D zeichnen
Ja, das sollte auch möglich sein.
Das Bild oben zeigt einen Hintergrund (256x144) und ein kleines Objekt. Wie man sehen kann werden die Bilder so gestreckt das man jedes Pixel klar sieht, und genau das will ich so haben. Edit: Ziel wäre eine kleine Game-Engine. |
AW: Bitmap erstellen und mit Direct2D zeichnen
Wenn's um Game-Engine geht: Hast du dir schon Andorra 2D angeschaut? Das ist eine DirectX / OpenGL Sprite Engine für Delphi.
Andernfalls: Für das was du machen willst, kannst du auch ![]() Noch ein Wort zu ScanLine. Wenn man mit ScanLine zeichnen will, macht man das in der Regel nach dem Prinzip:
Delphi-Quellcode:
ScanLine liefert dir einen Zeiger zurück. Das dient aber nicht nur zum lesen. Sondern das heisst auch, dass alle Werte, die du in / an / auf dem Zeiger manipulierst, direkt wieder in diesen Speicherbereich zurückgeschrieben werden.
type
TRGB = record R, G, B: Byte; end; PRGB = ^TRGB; var Bmp: TBitmap; x, y: Integer; RGB: PRGB; c: Byte; begin Randomize; Bmp := TBitmap.Create; try Bmp.PixelFormat := pf24Bit; Bmp.Width := 1000; Bmp.Height := 100; for y := 0 to Bmp.Height - 1 do begin RGB := Bmp.ScanLine[y]; for x := 0 to Bmp.Width - 1 do begin c := Round(255 / 100 * x / Bmp.Width * 100); RGB^.r := c; // Random(255); RGB^.g := c; // Random(255); RGB^.b := c; // Random(255); Inc(RGB); end; end; Bmp.SaveToFile('C:\Temp\Test.bmp'); finally FreeAndNil(Bmp); end; end; In diesem Fall sind es die RGB-Werte für die Palette, die direkt wieder im Bitmap-Speicher landen. |
AW: Bitmap erstellen und mit Direct2D zeichnen
Zitat:
Hintergrund- und Vordergrundobjekt sind in diesem simplen Beispiel gleich. Sobald das Prinzip aber verstanden ist, kannst du auch verschiedene Quellbitmaps nehmen.
Delphi-Quellcode:
unit MainForm;
interface uses Winapi.Windows, Winapi.D2D1, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Direct2D, Vcl.StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; Button3: TButton; Button4: TButton; Edit1: TEdit; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure Button4Click(Sender: TObject); procedure FormDestroy(Sender: TObject); private FCanvas : TDirect2DCanvas; FBitmap : TBitmap; FGameObject : ID2D1Bitmap; protected procedure CreateWnd; override; procedure WMPaint(var Message: TWMPaint); message WM_PAINT; procedure WMSize(var Message: TWMSize); message WM_SIZE; public property Canvas: TDirect2DCanvas read FCanvas; procedure Draw; procedure Loop(CountTo : integer); end; var Form1: TForm1; implementation {$R *.dfm} { TForm1 } procedure TForm1.Button1Click(Sender: TObject); var OD: TOpenDialog; begin OD := TOpenDialog.Create(self); OD.Filter := 'Bitmap|*.bmp'; if OD.Execute then begin FBitmap.LoadFromFile(OD.FileName); FGameObject := Canvas.CreateBitmap(FBitmap); end; Invalidate; end; procedure TForm1.Button2Click(Sender: TObject); begin loop(10); end; procedure TForm1.Button3Click(Sender: TObject); begin loop(100); end; procedure TForm1.Button4Click(Sender: TObject); begin loop(1000); end; procedure TForm1.CreateWnd; begin inherited; FCanvas := TDirect2DCanvas.Create(Handle); FBitmap := TBitmap.Create; FBitmap.LoadFromFile('5.bmp'); FGameObject := Canvas.CreateBitmap(FBitmap); end; procedure TForm1.Draw; var D2DRect : TD2DRectF; GameObjectRect : TRect; function GetBackgroundSize : TD2DRectF; begin Result.Top := ClientRect.Top; Result.Left := ClientRect.Left; Result.Right := ClientRect.Right; Result.Bottom := ClientRect.Bottom; end; function GetObjectSize : TD2DRectF; begin GetCursorPos(GameObjectRect.TopLeft); GameObjectRect.TopLeft := ScreenToClient(GameObjectRect.TopLeft); Result.Top := GameObjectRect.Top; Result.Left := GameObjectRect.Left; Result.Right := GameObjectRect.Left + FBitmap.Width div 8; Result.Bottom := GameObjectRect.Top + FBitmap.Height div 8; end; begin if Assigned(FGameObject) then begin D2DRect := GetBackgroundSize; Canvas.RenderTarget.DrawBitmap(FGameObject, @D2DRect); D2DRect := GetObjectSize; Canvas.RenderTarget.DrawBitmap(FGameObject, @D2DRect, 0.5); end; end; procedure TForm1.FormDestroy(Sender: TObject); begin FCanvas.Free; FBitmap.Free; end; procedure TForm1.Loop(CountTo: integer); var c : integer; begin c := 0; while c < CountTo do begin Invalidate; Application.ProcessMessages; Inc(c); if c mod 25 = 0 then edit1.Text := inttostr(c); end; edit1.Text := 'done'; end; procedure TForm1.WMPaint(var Message: TWMPaint); var PaintStruct: TPaintStruct; begin BeginPaint(Handle, PaintStruct); try Canvas.BeginDraw; try Draw; finally Canvas.EndDraw; end; finally EndPaint(Handle, PaintStruct); end; end; procedure TForm1.WMSize(var Message: TWMSize); var NewSize : TD2D1SizeU; begin if Assigned(Canvas) then begin NewSize := D2D1SizeU(ClientWidth, ClientHeight); ID2D1HwndRenderTarget(Canvas.RenderTarget).Resize(NewSize); end; inherited; end; end. |
AW: Bitmap erstellen und mit Direct2D zeichnen
@milos:
Konntest du damit was anfangen? |
AW: Bitmap erstellen und mit Direct2D zeichnen
Erstmal vielen Dank, dass du dir Mühe gegeben hast und mir sogar einen Code geschrieben hast ^^
Leider habe ich momentan nicht viel Zeit für mein Privatprojekt und konnte den Code deshalb nur einmal kurz kompillieren. Was ich bisher gesehen hab, passt mir eigentlich schon ganz gut, nur hätte ich gerne dass wenn ich ein Bitmap habe was z.B. 64x64 pixel ist und es dann gestreckt wird, wirklich jedes Pixel gestreckt wird wie man es bei dem Bild was ich hochgeladen habe ganz gut sehen kann. Dort wurde ein Pixel auf 10 gestreckt. (also pixel für pixel und nicht das ganze Bild verzerrt) Wäre dies noch möglich? |
AW: Bitmap erstellen und mit Direct2D zeichnen
Habe ich nicht verstanden? :gruebel:
Zeige mal ein Screenshot vom Ist-Zustand und dann bastle per Zeichenprogramm mal ein Soll-Zustand. |
AW: Bitmap erstellen und mit Direct2D zeichnen
Hat er doch schon oben, das Beispielbild.
@milos: Hast du dir schonmal - wie oben erwähnt - ![]() Wenn du ein Bild nach einem bestimmten Filter strecken willst (also in dem Fall "Pixel-Wiederholung"), brauchst du einen Algorithmus, der das erledigt. Ich weiß nicht, ob die VampyreImagingLibrary sowas dabei hat oder die Graphics32. Andernfalls hast du hier schon alle Werkzeuge genannt bekommen, die du dafür brauchst, um das schnell und effizient zu machen. Stichwort: ScanLine. :mrgreen: Wenn du willst, dass in einem Zielbild ein Pixel aus dem Quellbild in einem 5x5- oder 10x10-Block gezeichnet wird, musst du mit entsprechenden Schleifen jeden Pixel im Quellbild auslesen und im Zielbild diesen Pixel im gewünschten Block "nachbilden".
Delphi-Quellcode:
liefert dir einen Zeiger zu einer RGB(A)-"Y-Zeile". Und mit
ScanLineP := Bitmap.ScanLine[Y]
Delphi-Quellcode:
kannst du dich in der X-Spalte vorwärtsbewegen.
Inc(ScanLineP);
Wenn du also etwas von Bild1 auf Bild2 per ScanLine zeichnen willst, brauchst du ... ? Richtig, zwei ScanLine-Zeiger. :mrgreen:
Delphi-Quellcode:
Wenn du also willst, dass ein Pixel von Bitmap1 in Bitmap2 X-und-Y-mal wiederholt wird, musst du - unter Berücksichtung der Bilddimensionen - die X-Schleife entsprechend anpassen und erweitern.
uses
Winapi.Windows; type PRGBQuadArray = ^TRGBQuadArray; TRGBQuadArray = Array[0..0] of TRGBQuad var ScanLine_Source, ScanLine_Target: PRGBQuadArray; X, Y: Integer; begin // Annahme: Bitmap1.Width = Bitmap2.Width und Bitmap1.Height = Bitmap2.Height! for Y := 0 to Bitmap1.Height - 1 do begin ScanLine_Source := Bitmap1.ScanLine[Y]; ScanLine_Target := Bitmap2.ScanLine[Y]; for X := 0 to Bitmap1.Width - 1 do begin ScanLine_Target[X]^ := ScanLine_Source[X]^; { Das gleiche wie ScanLine_Target[X]^.rgbBlue := ScanLine_Source[X]^.rgbBlue; ScanLine_Target[X]^.rgbGreen := ScanLine_Source[X]^.rgbGreen; ScanLine_Target[X]^.rgbRed:= ScanLine_Source[X]^.rgbRed; ScanLine_Target[X]^.rgbReserved:= ScanLine_Source[X]^.rgbReserved; } end; end; end; |
AW: Bitmap erstellen und mit Direct2D zeichnen
Zitat:
Ob etwas pixelig wirkt hängt doch von der ursprünglichen Größe der Textur und der Ausgabe-Größe auf den Bildschirm zusammen?! Ein 8 x 8 Pixel großes Bitmap auf ein Panel von 64 x 64 Pixel gezeichnet -> Pixelbrei! Ein FullHD-Bild auf 400 x 300 -> scharf! Ggf. in der DrawBitmap-Methode den InterpolationMode noch auf D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR setzen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:29 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz