AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi Kombi von 2D mit 3D Elementen, auch ohne OpenGL ?

Kombi von 2D mit 3D Elementen, auch ohne OpenGL ?

Ein Thema von CloudyofSky · begonnen am 20. Nov 2006 · letzter Beitrag vom 23. Nov 2006
Antwort Antwort
Seite 1 von 2  1 2   
CloudyofSky

Registriert seit: 20. Nov 2006
7 Beiträge
 
#1

Kombi von 2D mit 3D Elementen, auch ohne OpenGL ?

  Alt 20. Nov 2006, 15:02
Hey Freunde der Kunst,

ich würde gerne ein Bild erstellen, auf dem ich kleinere Sachen animieren kann. Wie zum Beispiel in irgend welchen Adventuren wo ein Zimmer gezeigt wird auf dem sich die Uhr bewegt. Nur würde ich gerne anstelle der Uhr mehrere Möbel sich drehen lassen wollen (symbolisches Beispiel).

Die Bilder für die Animation liegen als einzelne Bilder vor. Die würde ich gerne in einer Datei zusammenfügen(gleich wie eine Video Datei). Sind eine Ansammlung von vorgerenderten JPegs. Ich mag sie nicht in eine Videodatei packen, weil die Verlustrate zu hoch ist, find ich zu mindest.

Mit TBitmap kann ich nun schon arbeiten, laden und so...auch schon Dateien dort zwischen lagern und später mit bitblt auf ein Image kopieren. Nur klappt das mit den JPegs nicht Und ich weis nicht wie ich die JPegs in eine Datei reinbekomme und später wieder raus, damit ich sie anzeigen kann.
Von JPeg zu dem Image, sollte ja auch irgend wie gehen.

Ich weis ich kling nun ein wenig so, als ob ich nun gar nicht programmieren kann, aber ich habe mich mit Grafik, per Programmierung, bie dato noch gar nicht beschäftigt und wollte nun mal doch anfangen.

Ich wäre froh über ein paar Antworten.
-------------------------
Gruß und Dank, Sky.
  Mit Zitat antworten Zitat
Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#2

Re: Kombi von 2D mit 3D Elementen, auch ohne OpenGL ?

  Alt 20. Nov 2006, 15:30
Zitat von CloudyofSky:
Hey Freunde der Kunst,
Ich weis ich kling nun ein wenig so, als ob ich nun gar nicht programmieren kann, aber ich habe mich mit Grafik, per Programmierung, bie dato noch gar nicht beschäftigt und wollte nun mal doch anfangen.
Hi und herzlich Willkommen in der DP

Ob es sich so anhört, ob du programmieren kannst oder nicht, ist doch egal! Klingt eigentlich so, als ob du ein bestimmtes Problem hast (JPEGs anzeigen und in einen Container speichern bzw. wieder laden), nicht nach mehr oder weniger. Und da bist du schon richtig in der DP, da wird dir schon geholfen werden.

Da trete ich auch gerne den Beweis für an:

Zitat von CloudyofSky:
Die Bilder für die Animation liegen als einzelne Bilder vor. Die würde ich gerne in einer Datei zusammenfügen(gleich wie eine Video Datei). Sind eine Ansammlung von vorgerenderten JPegs
Dazu muss ich gleich sagen, dass JPEGs nicht unbedingt optimal sind. Was du machst um sie anzuzeigen ist, dass du sie entpackst und dann wieder ein Bitmap hast, mit dem du arbeitest. Das ganze geht zwar relativ flink, aber dass wäre hier wirklich vor der Anzeige jeden JPEGS nötig (ggf. wieder und wieder). Einfacher wäre es da, wenn du ein Archiv (gepackt) von den gebrauchten Bildern hast, es entpackst (die entpackten Bitmaps können dann im Speicher gehalten werden) und dann die Bitmaps verwendest. Wird die Animation nicht mehr gebraucht kannst du dann einfach die Bitmaps (und ihren Speicher) frei geben.

Zitat von CloudyofSky:
Mit TBitmap kann ich nun schon arbeiten, laden und so...auch schon Dateien dort zwischen lagern und später mit bitblt auf ein Image kopieren. Nur klappt das mit den JPegs nicht
Für JPEGs gibt es die TJPEGImage Komponente. Die ist ziemlich ähnlich zu der TBitmap aufgebaut. Mittels assign kannst du so einer Bitmap auch ein TJPEGImage zuweisen, also den Inhalt zwischen den beiden konvertieren. Dabei solltest du dann einfach mal in die OH schauen, Stichwort wäre hier dann noch BMPneeded (glaube es hieß so).

Ja, damit hast du schon alles um ein JPEG in eine Bitmap zu packen und mit der kannst du dann wie gewohnt arbeiten. Alternativ kannst du auch der Picture Eigenschaft des TImage direkt ein TJpegImage zuweisen.

Ja, was das speicher in einer Datei angeht, so hast du auch hier mehr als eine Möglichkeit. Die einfachste besteht darin, dass du einfach auf eine Komponente zurückgreifst, die die gesuchte Logik implementiert. In deinem Fall wäre das ja eigentlich nur das speichern von mehr als einer Datei in einem Container. Da würde sich dann z.B. eine Zip-Kapselung (z.B. Abbrevia) anbieten. Der Vorteil ist klar, du bekommst eine fertige Lösung. Ganz allgemein kannst du ein JPEG laden, indem du die Methode TJPEGImage.LoadFromFile ode TJPEGImage.LoadFromStream verwendest. Solltest du Daten aus einer Archiv entpacken, so kannst du hier mit einem TMemoryStream arbeiten, die Daten in diesen rein entpacken und dann an die LoadFromStream Methode übergeben. Dabei solltest du die Position des TMemorystream (gleichnamige Eigenschaft) vor dem Laden wieder auf 0 setzen (ist ein Zeiger auf die stelle ab der gelesen werden soll).
Alternativ kannst du natürlich auch ein properitäres Format erstellen. Da benötigst du dann ein paar Meta-Informationen. Eigentlich musst du dir nur überlegen, wie du den Anfang und das Ende eines JPEGs in dieser Datei markierst. Das kannst du mit speziellen Auszeichnungen oder einem Inhaltsverzeichnis oder beidem machen (in einer Zip Datei wird Ähnliches gemacht, allerdings halt auch eine Menge mehr, z.B. eine CRC32 Checksumme berechnet).

Frag einfach, wenn du irgendwo nicht weiter kommst!

Gruß Der Unwissende
  Mit Zitat antworten Zitat
CloudyofSky

Registriert seit: 20. Nov 2006
7 Beiträge
 
#3

Re: Kombi von 2D mit 3D Elementen, auch ohne OpenGL ?

  Alt 20. Nov 2006, 16:28
Wow - das war ja mal eine schnelle Antwort. Deshalb erst mal rechtherzlichen Dank dafür und auch gleichzeitig rechtherzlichen Dank für die begrüßenden Worte.

Die Idee mit den JPGs in Bitmaps klingt logisch und so werd ich es auch machen. Dann hab ich nur "einmal" die Ladezeit und dann ruhe, wenn es im Speicher liegt und muß den Rechner nicht unnötig umrechnen lassen.

Leider hab ich auch noch keine Ahnung von Streams

Wie könnte ich zB an Hand eines Beispiels 2 Bilder in so einen Stream legen?
-------------------------
Gruß und Dank, Sky.
  Mit Zitat antworten Zitat
Namenloser

Registriert seit: 7. Jun 2006
Ort: Karlsruhe
3.724 Beiträge
 
FreePascal / Lazarus
 
#4

Re: Kombi von 2D mit 3D Elementen, auch ohne OpenGL ?

  Alt 20. Nov 2006, 16:48
Meine idee wäre:

Alle Bilder nebeneinander in eine Datei. Das bild in den speicher laden, in ein TBitmap konvertieren, und die einzelnen bilder im programm trennen. (z.b. mit nem array of bitmap und bitblt)
  Mit Zitat antworten Zitat
CloudyofSky

Registriert seit: 20. Nov 2006
7 Beiträge
 
#5

Re: Kombi von 2D mit 3D Elementen, auch ohne OpenGL ?

  Alt 20. Nov 2006, 17:02
Und wie sollte das technisch Funktionieren(in Delphi)?

Bilder nebeneinander legen, also vorher alle Bilder in ein Bildbearbeitungprogramm nebeneinander legen und speichern.
Dann im Programm per Maske(?) über eine Positionsangabe ein Bild holen und es dann ausgeben.

hmm...in der Theorie klingt es gut.
-------------------------
Gruß und Dank, Sky.
  Mit Zitat antworten Zitat
Namenloser

Registriert seit: 7. Jun 2006
Ort: Karlsruhe
3.724 Beiträge
 
FreePascal / Lazarus
 
#6

Re: Kombi von 2D mit 3D Elementen, auch ohne OpenGL ?

  Alt 20. Nov 2006, 17:15
etwa so:
Delphi-Quellcode:
var bilder: array of TBitmap;

{...}

procedure bilderladen;
var i: integer;
    breite: integer;
    bild: TBitmap;
const
    filename = 'c:\animation.jpg'; //z.b.
    anzahl = 16; //z.b.
begin
  bild := TBitmap.create;
  setlength(bilder,anzahl);
  try
    bild.loadfromfile(filename); // Funktioniert, weil TBitmap Nachfahre von tGraphic ist
    breite := bild.width div anzahl;
    for i := 0 to anzahl-1 do
    begin
      bilder[i] := tBitmap.create;
      bilder[i].width := breite;
      bilder[i].height := bild.height;
      bitblt(bilder[i].canvas.handle,0,0,breite,bild.height,bild.canvas.handle,
        i*breite,0,srccopy);
    end;
  finally
    bild.free;
  end;
end;
Dann kannst du auf alle einzelnen Frames zugreifen. Ungetestet, müsste aber gehen...

edit: achja, du musst natürlich die unit jpeg einbinden
  Mit Zitat antworten Zitat
Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#7

Re: Kombi von 2D mit 3D Elementen, auch ohne OpenGL ?

  Alt 20. Nov 2006, 18:51
Zitat von CloudyofSky:
Leider hab ich auch noch keine Ahnung von Streams

Wie könnte ich zB an Hand eines Beispiels 2 Bilder in so einen Stream legen?
Das ist ganz einfach. Alles was du zum Thema Streams wissen musst findest du in der OH (unter TStream, TFileStream und TMemoryStream). Ein Stream ist eigentlich sehr einfach aufgebaut. Ein TStream-Objekt hat immer zwei Enden, eines in das Bytes reinkommen und eines wo diese wieder rauskommen. Du kannst dabei bestimmen wo diese Enden jeweils hinzeigen. Alles was du mit so einem Stream machst hat keine große Logik. Du kannst eine Menge von Bytes ablegen (ohne dass es wichtig ist ob es Zahlen sind, Bilder, Musik) und natürlich auch Bytes lesen, nicht mehr.
Das ist schon fast alles was man über einen Stream wissen muss. Hier liegen die Vorteile (sehr flinkes Arbeiten, sehr hohe Flexibilität), aber auch die Nachteile. So kannst du zwar eine Menge von Bytes auslesen, aber das bleiben halt Typlose Bytes, die musst du schon selbst interpretieren.

Auch wenn man eine Menge vorgefertigter Komponenten findet, kann es schnell mal sein, dass du auf ein Dateiformat triffst, für dass du noch keine Delphi-Komponente findest. In einem solchen Fall wirst du dann (wahrscheinlich) einen Stream verwenden, die Daten einlesen und interpretieren. Ist also das, was auch gemacht wird, wenn du z.B. eine Bitmap lädtst.
Jetzt gibt es schon fertige Dateitypen und viele davon haben eine Version > 1.0, das kommt nicht von ungefähr. Man lernt einfach aus den Problemen, die andere Formate mit sich brachten. Du findest hier häufig eine Menge Meta-Informationen, die nötig sind um verschiedene Dateien möglichst flexibel zu interpretieren. So kannst du z.B. in einem Tiff mehr als ein Bild speichern (ein Multipage-Tiff), so haben Zip-Archive für jede gespeicherte Datei auch die CRC32 Checksumme gespeichert usw.

Deshalb ist meine Empfehlung vorab, dass du hier eher auf eine existierende Lösung zurückgreifst, da du hier a) nichts selbst lösen musst und b) von den Erfahrungen der Entwickler profitierst.

Schauen wir uns aber trotzdem mal dein Problem mit Streams an:
Du möchtest mehr als eine Datei in einer Art Container speichern. Jetzt gibt es verschiedene Möglichkeiten, wie du die Datei organisierst. Das Hauptproblem ist, dass du nicht weißt wie viele Dateien in so einem Container gespeichert sind. Hast du mehr als eine Datei im Container, so kannst du nicht mit Sicherheit sagen, wo eine Datei anfängt und eine andere endet. Der einfachste Weg um hier Abhilfe zu schaffen besteht darin, dass du einfach ein Tupel in den Container schreibst. Schreibst du erst die Länge als Integer/Cardinal und dann die Datei. Der Vorteil liegt darin, dass ein Integer (auf 32 Bit maschinen) immer genau 4 Byte groß ist. Liest du also die ersten 4 Byte, weißt du wie groß die gespeicherte (folgende) Datei ist. Wenn hinter dieser Datei noch mind. 4 Byte im Container stehen, geben diese folgenden 4 Byte die größe der nächsten Datei an.
Das ist schon alles.

Das ganze in Delphi
Delphi-Quellcode:
// kopieren der Bytes aus dem Stream in den Container
procedure addToContainer(const Stream : TStream; const Container : TStream);
begin
  // prüfen ob die Streams zugewiesen wurden
  if assigned(Stream) and assigned(Container) then
  begin
    // schreiben der Länge des folgenden Streams
    Container.write(Stream.Size, sizeOf(Integer));

    // schreiben der eigentlichen Daten des Streams
    // Der Parameter 0 als Länge ist hier speziell belegt
    // es wird der komplette Stream vom Anfang bis Ende kopiert
    Container.copyFrom(Stream, 0);
  end; // if assigned(Stream) and assigned(Container)
end;
Das wäre der Code, um einen Stream in den Container einzufügen. Bei beiden Parametern handelt es sich um Streams, das ermöglicht hier viel Flexibilität. Ein solcher Stream kann mit der SaveToStream Methode von einer Komponente gefüllt werden oder halt aus einer Datei stammen. Ein einfaches Beispiel:
Delphi-Quellcode:
var Container : TStream;
    buffer : TStream;
    bitmap : TBitmap;
begin
  Container := TFileStream.Create('PFAD\ZUR\DATEI.xyz', fmCreate or fmShareExclusive);
  
  // Ressourcen-Schutzblöcke stellen sicher, dass eine erzeugte Ressource auch
  // wieder frei gegeben wird
  try
    bitmap := TBitmap.Create;
    try
      bitmap.LoadFromFile('Pfad zu irgendeiner Bitmap);

buffer := TMemoryStream.Create;

try
bitmap.SaveToStream(buffer);
addToContainer(buffer, Container);
finally
buffer.Free;
end;

// hier könntest du jetzt noch beliebige andere Bilder Laden und so einfügen
// oder auch Dateien oder oder oder
finally
bitmap.Free;
end;
finally
Container.Free;
end;
end;
So ungefähr kann das hinzufügen aussehen. Natürlich wirkt es immer etwas aufgefüllt mit den ganzen Schutzblöcken, aber diese stellen nun mal sicher, dass du Speicher auch bei einem Fehler wieder frei gibst. Gerade wenn du ganz generell mal das .Free vergisst, kann es bei der Arbeit mit Bildern schnell sein dass der gesamte Speicher belegt ist.
Ja, zu guter Letzt kommt noch das Laden aus dieser Datei. Der Aufbau ist dabei einfach, du liest erst 4 Byte (die Länge) und danach die Anzahl von Bytes, die du halt als Länge gelesen hast.

Delphi-Quellcode:
function readNextFromContainer(const Container : TStream) : TStream;
var length : Integer;
begin
  // prüfen ob es noch mindest 4 Byte im Stream gibt
  if Container.Position + sizeOf(Integer) < Container.Size then
  begin
    // lesen der Länge
    Container.Read(length, sizeOf(Integer));

    // prüfen ob die Länge gültig ist
    if Container.Position + length < Container.Size then
    begin
      result := TMemoryStream.Create;
      result.CopyFrom(Container, length);
    end // if Container.Position + length < Container.Size

    else
    begin
      result := nil;
    end;
  end // if Container.Position + sizeOf(Integer) < Container.Size

  else
  begin
    // keine weitere Datei im Container
    result := nil;
  end;
end;
Ja, damit bekommst du einen Stream aus dieser Funktion zurück. Ist dieser nil, heißt dass das es keine weiteren gespeicherten Daten im Container gibt. Wie du hier vielleicht schon bemerkt hast, der Positionszeiger eines Streams wird aut. inkrementiert. Liest du x Bytes, dann zeigt der nun auf das 11 Byte. Somit muss man sich nicht um das inkrementieren beim Lesen/Schreiben kümmern, sollte ihn aber immer auf einen definierten Wert setzen. Beim Anlegen ist diese Position aut. 0.

Ja, hoffe es hilft etwas weiter.

Gruß Der Unwissende
  Mit Zitat antworten Zitat
CloudyofSky

Registriert seit: 20. Nov 2006
7 Beiträge
 
#8

Re: Kombi von 2D mit 3D Elementen, auch ohne OpenGL ?

  Alt 21. Nov 2006, 15:43
Wow - rechtherzlichen Dank!!!!!

Ich setz mich gerade an den Rechner und werd es gleich mal probieren.
-------------------------
Gruß und Dank, Sky.
  Mit Zitat antworten Zitat
CloudyofSky

Registriert seit: 20. Nov 2006
7 Beiträge
 
#9

Re: Kombi von 2D mit 3D Elementen, auch ohne OpenGL ?

  Alt 22. Nov 2006, 12:03
@NamenLozer:
Hab deine Variante ausprobiert und bis auf den Punkt das ich das JPeg nicht laden kann, weil er das in das Bitmap nicht reinladen kann, gehts. Ich habe das Bild einfach als Bitmap gespeichert und schon konnte ich alles anwenden.

Nur eine Sache geht nicht. Ich habe nun alle Bilder in dem Feld drin. Und genau ein Bild kann ich der TImage Komponente zuweisen, alle weiteren werden scheinbar ignoriert.

Hab ich nun irgend was falsch gemacht? Ändern tue ich das ganze per:
Delphi-Quellcode:
  procedure TForm1.Button1Click(Sender: TObject);
  begin
    bitblt(Image1.Canvas.Handle, 0, 0, breite, hoehe, Bilder[pos].Canvas.Handle, 0, 0, srccopy);
    inc(pos);
    if pos > anzahl then pos := 0;
  end;
Danke für die Hilfe bisher!

Edit: Hab es gefunden, per Image1.Repaint. Das hatte ich vergessen gehabt
-------------------------
Gruß und Dank, Sky.
  Mit Zitat antworten Zitat
CloudyofSky

Registriert seit: 20. Nov 2006
7 Beiträge
 
#10

Re: Kombi von 2D mit 3D Elementen, auch ohne OpenGL ?

  Alt 22. Nov 2006, 14:02
@Der_Unwissende:
Ich habe nun auch deines Ausprobiert und mit dem was du geschrieben hast, klappt es prima, kann sogar sehen das er die Datei anlegt. Was jedoch nicht klappt ist, das ich ein Bild draus lade und dieses dann per TImage ausgeben kann

Meine Prozedure sieht so dazu aus:
Delphi-Quellcode:
  procedure TForm1.Button2Click(Sender: TObject);
  var
    Stream : TStream;
  begin
    bitmap := TBitmap.Create;
    Stream := TStream.Create;
    try
      Stream := readNextFromContainer(Container);
      if Stream <> NIL then
      begin
        bitmap.LoadFromStream(Stream);
        bitblt(Image1.Canvas.Handle, 0, 0, bitmap.Width, bitmap.Height, bitmap.Canvas.Handle, 0, 0, srccopy);
      end;
    finally
      Stream.Free;
      bitmap.Free;
    end;
  end;
Die Fehlermeldung sagt etwas von einer "Privilegierte Anweisung".
-------------------------
Gruß und Dank, Sky.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

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 02:40 Uhr.
Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf