AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Bitmap erstellen und mit Direct2D zeichnen

Bitmap erstellen und mit Direct2D zeichnen

Ein Thema von milos · begonnen am 11. Mär 2014 · letzter Beitrag vom 25. Mär 2014
Antwort Antwort
Seite 2 von 3     12 3   
Benutzerbild von milos
milos

Registriert seit: 14. Jul 2008
Ort: Bern (CH)
508 Beiträge
 
Delphi 11 Alexandria
 
#11

AW: Bitmap erstellen und mit Direct2D zeichnen

  Alt 13. Mär 2014, 20:27
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.
Miniaturansicht angehängter Grafiken
pf.jpg  
Milos
  Mit Zitat antworten Zitat
nuclearping

Registriert seit: 7. Jun 2008
708 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#12

AW: Bitmap erstellen und mit Direct2D zeichnen

  Alt 13. Mär 2014, 20:45
Also du willst ein Bitmap über ein anderes zeichnen?
  Mit Zitat antworten Zitat
Benutzerbild von milos
milos

Registriert seit: 14. Jul 2008
Ort: Bern (CH)
508 Beiträge
 
Delphi 11 Alexandria
 
#13

AW: Bitmap erstellen und mit Direct2D zeichnen

  Alt 13. Mär 2014, 21:04
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.
Milos

Geändert von milos (13. Mär 2014 um 21:08 Uhr)
  Mit Zitat antworten Zitat
nuclearping

Registriert seit: 7. Jun 2008
708 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#14

AW: Bitmap erstellen und mit Direct2D zeichnen

  Alt 14. Mär 2014, 01:00
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 MSDN-Library durchsuchenStretchBlt verwenden.

Noch ein Wort zu ScanLine. Wenn man mit ScanLine zeichnen will, macht man das in der Regel nach dem Prinzip:

Delphi-Quellcode:
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;
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.

In diesem Fall sind es die RGB-Werte für die Palette, die direkt wieder im Bitmap-Speicher landen.
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.059 Beiträge
 
Delphi 10.4 Sydney
 
#15

AW: Bitmap erstellen und mit Direct2D zeichnen

  Alt 14. Mär 2014, 07:20
Ich finds ja genau so gruselig wie ihr alle aber ich kenne keine andere Methode es so hinzukrigen wie ich es gerne haben will...
Ich weiß, aller Anfang ist schwer, daher hier ein Anstoß.
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.

Geändert von TiGü (14. Mär 2014 um 08:09 Uhr)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.059 Beiträge
 
Delphi 10.4 Sydney
 
#16

AW: Bitmap erstellen und mit Direct2D zeichnen

  Alt 22. Mär 2014, 17:14
@milos:

Konntest du damit was anfangen?
  Mit Zitat antworten Zitat
Benutzerbild von milos
milos

Registriert seit: 14. Jul 2008
Ort: Bern (CH)
508 Beiträge
 
Delphi 11 Alexandria
 
#17

AW: Bitmap erstellen und mit Direct2D zeichnen

  Alt 23. Mär 2014, 06:04
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?
Milos
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.059 Beiträge
 
Delphi 10.4 Sydney
 
#18

AW: Bitmap erstellen und mit Direct2D zeichnen

  Alt 24. Mär 2014, 12:40
Habe ich nicht verstanden?

Zeige mal ein Screenshot vom Ist-Zustand und dann bastle per Zeichenprogramm mal ein Soll-Zustand.
  Mit Zitat antworten Zitat
nuclearping

Registriert seit: 7. Jun 2008
708 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#19

AW: Bitmap erstellen und mit Direct2D zeichnen

  Alt 24. Mär 2014, 13:01
Hat er doch schon oben, das Beispielbild.

@milos: Hast du dir schonmal - wie oben erwähnt - MSDN-Library durchsuchenStretchBlt angeschaut?

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.

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".

ScanLineP := Bitmap.ScanLine[Y] liefert dir einen Zeiger zu einer RGB(A)-"Y-Zeile". Und mit Inc(ScanLineP); kannst du dich in der X-Spalte vorwärtsbewegen.
Wenn du also etwas von Bild1 auf Bild2 per ScanLine zeichnen willst, brauchst du ... ? Richtig, zwei ScanLine-Zeiger.
Delphi-Quellcode:
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;
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.
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.059 Beiträge
 
Delphi 10.4 Sydney
 
#20

AW: Bitmap erstellen und mit Direct2D zeichnen

  Alt 24. Mär 2014, 14:03
Hat er doch schon oben, das Beispielbild.
Das zeigt mir aber nicht wie es jetzt ist und wie es sein soll!

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.
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:01 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz