Screenshot: Unterschied zwischen den Versionen

Aus DGL Wiki
Wechseln zu: Navigation, Suche
K (Der Kateogrie Technik oder Algorithmus zugeordnet)
()
Zeile 1: Zeile 1:
 
= Allgemeines zum Screenshot erstellen =
 
= Allgemeines zum Screenshot erstellen =
 
== Einleitung ==
 
== Einleitung ==
Ein '''Screenshot''' ist ein Abbild des aktuellen Bildschrim Inhaltes. In dem Falle von OpenGL greifen wir aber nicht auf das Fenster zurück sondern auf den [[Framebuffer]]. Neben dem eigentlichen Vorgang, nämlich der Besorgung der Bilddaten, ist es meißtens auch noch sinnvoll die Daten dem Benutzer verfügbar zu machen. Dies geschieht meistens in Form einer Bild-Datei oder eines Eintrages in der Zwischenablage.
+
Ein '''Screenshot''' ist ein Abbild des aktuellen Bildschirm Inhaltes. In dem Falle von OpenGL greifen wir aber nicht auf das Fenster zurück sondern auf den [[Framebuffer]]. Neben dem eigentlichen Vorgang, nämlich der Besorgung der Bilddaten, ist es meistens auch noch sinnvoll die Daten dem Benutzer verfügbar zu machen. Dies geschieht meistens in Form einer Bild-Datei oder eines Eintrages in der Zwischenablage.
  
 
== Bilddaten besorgen ==
 
== Bilddaten besorgen ==
Mit Hilfe des [[glReadPixels]] Befehl kann der [[Framebuffer]] ausgelesen werden. Für einen Screenshot sind meißtens die [[RGB]]-Werte interessant. Bei diesen Werten ergibt sich auch schon das erste Problem: OpenGL speichert die Daten in der Reinfolge Rot Grün Blau, wärend es in einigen Bildformaten (nämlich denen die auf Bitmaps aufbauen) üblich ist, die Daten in der Reinfolge Blau Grün Rot zu speichern. Glücklicherweise kann man in aktuellen OpenGL Versionen [[glReadPixels]] anweisen die Daten auch in dieser Reinfolge zu liefern.
+
Mit Hilfe des [[glReadPixels]] Befehls kann der [[Framebuffer]] ausgelesen werden. Für einen Screenshot sind meistens die [[RGB]]-Werte interessant. Bei diesen Werten ergibt sich auch schon das erste Problem: OpenGL speichert die Daten in der Reihenfolge Rot Grün Blau, während es in einigen Bildformaten (nämlich denen die auf Bitmaps aufbauen) üblich ist, die Daten in der Reihenfolge Blau Grün Rot zu speichern. Glücklicherweise kann man in aktuellen OpenGL Versionen [[glReadPixels]] anweisen die Daten auch in dieser Reihenfolge zu liefern.
  
Der [[glReadPixels]] Befehl für neue Grafikarten könnte in etwa so aussehen:
+
Der [[glReadPixels]] Befehl für neue Grafikkarten könnte in etwa so aussehen:
 
<pascal>
 
<pascal>
   // ungünstige Reinfolge Rot Grün Blau  
+
   // ungünstige Reihenfolge Rot Grün Blau  
 
   glReadPixels( 0, 0, Breite, Hoehe, GL_RGB, GL_UNSIGNED_BYTE, Daten );
 
   glReadPixels( 0, 0, Breite, Hoehe, GL_RGB, GL_UNSIGNED_BYTE, Daten );
   // auf neuren Grafikarten:
+
   // auf neueren Grafikkarten:
 
   glReadPixels( 0, 0, Breite, Hoehe, GL_BGR, GL_UNSIGNED_BYTE, Daten );
 
   glReadPixels( 0, 0, Breite, Hoehe, GL_BGR, GL_UNSIGNED_BYTE, Daten );
 
</pascal>
 
</pascal>
  
Was die einzelen Parameter bedeuten, könnt ihr im [[glReadPixels]] Artikel nachlesen. Es sei hier nur gesagt das das letzte Argument der Speicherplatz ist, an dem OpenGL die Daten abspeichern soll(meißt ein Pointer z.B. auf ein Array).
+
Was die einzelnen Parameter bedeuten, könnt ihr im [[glReadPixels]] Artikel nachlesen. Es sei hier nur gesagt das das letzte Argument der Speicherplatz ist, an dem OpenGL die Daten abspeichern soll (meist ein Pointer z.B. auf ein Array).
 +
 
 +
== Hinweis ==
 +
Unter [[SDL]] finden sich die Bilddaten schon in der [[SDL_Surface|Displaysurface]] unter ''pixels''.
  
 
= Speichern im TGA Format =
 
= Speichern im TGA Format =

Version vom 17. Oktober 2005, 12:51 Uhr

Allgemeines zum Screenshot erstellen

Einleitung

Ein Screenshot ist ein Abbild des aktuellen Bildschirm Inhaltes. In dem Falle von OpenGL greifen wir aber nicht auf das Fenster zurück sondern auf den Framebuffer. Neben dem eigentlichen Vorgang, nämlich der Besorgung der Bilddaten, ist es meistens auch noch sinnvoll die Daten dem Benutzer verfügbar zu machen. Dies geschieht meistens in Form einer Bild-Datei oder eines Eintrages in der Zwischenablage.

Bilddaten besorgen

Mit Hilfe des glReadPixels Befehls kann der Framebuffer ausgelesen werden. Für einen Screenshot sind meistens die RGB-Werte interessant. Bei diesen Werten ergibt sich auch schon das erste Problem: OpenGL speichert die Daten in der Reihenfolge Rot Grün Blau, während es in einigen Bildformaten (nämlich denen die auf Bitmaps aufbauen) üblich ist, die Daten in der Reihenfolge Blau Grün Rot zu speichern. Glücklicherweise kann man in aktuellen OpenGL Versionen glReadPixels anweisen die Daten auch in dieser Reihenfolge zu liefern.

Der glReadPixels Befehl für neue Grafikkarten könnte in etwa so aussehen:

  // ungünstige Reihenfolge Rot Grün Blau 
  glReadPixels( 0, 0, Breite, Hoehe, GL_RGB, GL_UNSIGNED_BYTE, Daten );
  // auf neueren Grafikkarten:
  glReadPixels( 0, 0, Breite, Hoehe, GL_BGR, GL_UNSIGNED_BYTE, Daten );

Was die einzelnen Parameter bedeuten, könnt ihr im glReadPixels Artikel nachlesen. Es sei hier nur gesagt das das letzte Argument der Speicherplatz ist, an dem OpenGL die Daten abspeichern soll (meist ein Pointer z.B. auf ein Array).

Hinweis

Unter SDL finden sich die Bilddaten schon in der Displaysurface unter pixels.

Speichern im TGA Format

Eine TGA-Datei hat einen relativ einfachen Aufbau. Als erstes kommen Header-Informationen und dannach die Daten. Der Header sieht so aus:

type 
  TTGAHEADER = packed record
    tfType : Byte;
    tfColorMapType : Byte;
    tfImageType : Byte;
    tfColorMapSpec : Array[0..4] of Byte;
    tfOrigX : Word; //Array [0..1] of Byte;
    tfOrigY : Word;
    tfWidth : Word;
    tfHeight : Word;
    tfBpp : Byte;
    tfImageDes : Byte;
  end;

Nun zur Speicherfunktion für ein Screenshot ohne Alpha Wert

procedure ScreenShot(const Name : string);
var 
  DataBuffer : array of Byte;
  f : file;
  tgaHeader : TTGAHEADER;
  width, height : integer;
  DataSize:Integer;
  viewport : Array[0..3] of integer;
begin

  glGetIntegerv(GL_VIEWPORT, @viewport);
  width := viewport[2];
  height := viewport[3];

  DataSize := Width * Height * 3;

  SetLength(DataBuffer,DataSize);

  // TGA Kopf mit Daten füllen
  ZeroMemory(@tgaHeader, SizeOf(tgaHeader));
  tgaHeader.tfImageType := 2; // TGA_RGB = 2
  tgaHeader.tfWidth := Width; 
  tgaHeader.tfHeight := Height;
  tgaHeader.tfBpp := 24;

  glReadPixels(0,0,Width, Height, GL_BGR, GL_UNSIGNED_BYTE, @DataBuffer[0]);
  
  //Datei erstellen
  AssignFile(f, Name);
  Rewrite( f,1 );
  try 
    // TGA Kopf in die Datei reinschreiben
    BlockWrite(F, tgaHeader, SizeOf(tgaHeader));

    // Die eigentlichen Bilddaten in die Datei schreiben
    BlockWrite(f, DataBuffer[0], DataSize );
  finally
    CloseFile(f);
  end;
end;

Speichern im BMP Format

Auch eine BMP-Datei hat einen relativ einfachen Aufbau. Als erstes kommen Header-Informationen, dann FileInfo-Informationen und dannach die Daten. Der Header sieht so aus:

 BITMAPINFOHEADER = packed record
    biSize: DWORD;
    biWidth: Longint;
    biHeight: Longint;
    biPlanes: Word;
    biBitCount: Word;
    biCompression: DWORD;
    biSizeImage: DWORD;
    biXPelsPerMeter: Longint;
    biYPelsPerMeter: Longint;
    biClrUsed: DWORD;
    biClrImportant: DWORD;
  end;

 BITMAPFILEHEADER = packed record
    bfType: Word;
    bfSize: DWORD;
    bfReserved1: Word;
    bfReserved2: Word;
    bfOffBits: DWORD;
  end;

Nun zur Speicherfunktion für ein Screenshot :

procedure ScreenShot(const Name : string);
 var F : file;
     FileInfo: BITMAPINFOHEADER;
     FileHeader : BITMAPFILEHEADER;
     pPicData:Pointer;
     Viewport : array[0..3] of integer;
begin
 ZeroMemory(@FileHeader, SizeOf(BITMAPFILEHEADER));
 ZeroMemory(@FileInfo, SizeOf(BITMAPINFOHEADER));

 glGetIntegerv(GL_VIEWPORT, @Viewport);

 FileInfo.biSize := SizeOf(BITMAPINFOHEADER);
 FileInfo.biWidth := Viewport[2];
 FileInfo.biHeight := Viewport[3];
 FileInfo.biPlanes := 1;
 FileInfo.biBitCount := 32;
 FileInfo.biSizeImage := FileInfo.biWidth*FileInfo.biHeight*(FileInfo.biBitCount div 8);

 FileHeader.bfType := 19778;
 FileHeader.bfOffBits := SizeOf(BITMAPINFOHEADER)+SizeOf(BITMAPFILEHEADER);
 FileHeader.bfSize := FileHeader.bfOffBits + FileInfo.biSizeImage;

 GetMem(pPicData, FileInfo.biSizeImage);

 glReadPixels(0, 0, Viewport[2], Viewport[3], GL_BGRA, GL_UNSIGNED_BYTE, pPicData);

  AssignFile(f, name);
  Rewrite( f,1 );
   BlockWrite(F, FileHeader, SizeOf(BITMAPFILEHEADER));
   BlockWrite(F, FileInfo, SizeOf(BITMAPINFOHEADER));
   BlockWrite(F, pPicData^, FileInfo.biSizeImage );
  CloseFile(f);

 FreeMem(pPicData, FileInfo.biSizeImage);
end;