Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi screenshot als jpeg (https://www.delphipraxis.net/4404-screenshot-als-jpeg.html)

ShoAn 27. Apr 2003 18:24


screenshot als jpeg
 
hi, ich möchte gern ein bildschirmfoto machen, aber das gleich als jpeg speichern. das beispiel http://www.delphipraxis.net/viewtopic.php?t=2905 von sakura klappt ganz gut, aber kann ich das nicht gleich mit der TJpegImage - komponente machen?? weil sonst müsste ich das immer umwandeln und das dauert mir zu lang :(
kann mir jemand helfen??

Alexander 27. Apr 2003 18:50

Du müsstest es schießen, umwandeln und dann anzeigen bzw. speichren...
Oder habe ich dich falsch verstanden?

ShoAn 27. Apr 2003 19:26

naja, das mit dem umwandeln wollt ich ja grad nicht machen, weil das mir zu lange dauert, wenn zum beispiel jede sekunde ein bild speichern möchte.

kann ich denn nicht gleich anstelle der TBitmap komponente, die TJpegImage komponente benutzen???

ich hab dann einfach versucht, das beispiel umzuschreiben. aber ich bleib ja schon an der stelle hängen:
Code:
...
var
  JPEG: TJpegImage;

begin
  JPEG.Width  := Form1.ClientWidth;
  JPEG.Height := Form1.ClientHeight;

...
da kommt die meldung, dass ich die größe einer JPEG-Grafik nicht ändern kann :(

Christian Seehase 27. Apr 2003 19:48

Moin ShoAn,

da das JPEG Format ja eine (verlustbehaftete) Komprimierung voraussetzt, muss diese ja irgendwann einmal einsetzen.
Eine Möglichkeit, ohne JPEG, wäre es einen Screenshot zu machen, und diesen dann mit Hilfe der ZLIB Kompo (zumindest in D5 Pro enthalten) zu komprimieren. Das geht eigentlich recht schnell.
(mitgestoppt hab' ich nicht, und einen Vergleich mit JPEG Komprimierung kann ich auch nicht anstellen).
Leider ist diese Kompo undokumentiert, allerdings hatten wir zu diesem Thema hier schon einen Thread.

Luckie 27. Apr 2003 20:01

Ich glaube kaum, dass das Umwandeln länger als eine Sekunde dauert.

ShoAn 27. Apr 2003 21:33

hmm, stimmt. ich hab mal geguckt, wo man den code nacheinander abarbeiten kann. und da sieht man, wo er am längsten brauch. das war nämlich da, wo er den screenshot selbst macht.

ich könnt ja mal sagen, was ich eigentlich vor hab ;)
und zwar, übers netzwerk ein kleines überwachungstool, dass vortlaufend screenshots macht und die dann an einen computer schickt. das ganze soll dann wenns fertig is wie ein film aussehn, aber da ja das screenshot machen so lange dauert, geht das net so gut.

RobertS 28. Apr 2003 07:22

Also ich habe so etwas in der Art schonmal gemacht,
ich mache alle 12 sek. ein Screenshot speichere den in einen Stream, verkleinere das Bild und speichere es als jpg mit einer anderen Endung auf die Platte.
Das Programm was die Sachen aneinder hängt ändert beim öffnen die Dateiendung und öffnet die jpg Dateien :)

Aber das dauert nicht lange das speichern und umwandeln, ich gehe mal von einem Rechner aus der nicht lngsamer ist als 800MHz

mfg
Robert

APP 28. Apr 2003 09:41

Hallo,
ich habe sowas ähnliches auch schon mal benötigt, allerdings weiß ich nicht wie schnell die Wandlungszeit ist...
Delphi-Quellcode:
PROCEDURE aScreenShot(CONST aFileName: STRING);
{*****************************************************************************
 *** Screenshot Utility mit Export als JGEP-File                          ***
 *** -------------------------------------------                           ***
 *** INPUT: aFileName, speicherziel                                      ***
 *** OUTPUT: n/a                                                          ***
 *** RESULT: n/a                                                          ***
 *[flapp 01/01/2003]**********************************************************}
VAR
  aDC                             : hDC;
  aBmp                            : TBitmap;    //
  aJpg                            : TJPEGImage;
  mh, hBmp                        : THandle;
BEGIN
  ajpg := TJPEGImage.Create;
  aBmp := TBitmap.Create;
  aBmp.Width := Screen.Width;
  aBmp.Height := Screen.Height;
  aDC := GetDC(0);
  hBmp := CreateCompatibleBitmap(aDC, Screen.Width, Screen.Height);
  mh := SelectObject(aDC, hBmp);
  TRY
    BitBlt(aBmp.Canvas.Handle, 0, 0, aBmp.Width, aBmp.Height,
      aDC, 0, 0, SRCCopy);
    ajpg.Assign(aBmp);
    ajpg.CompressionQuality := 30;
    ajpg.Compress;
    ajpg.SaveToFile(aFileName);
  FINALLY
    ajpg.Free;
    aBmp.Free;
    SelectObject(aDC, mh);
    DeleteObject(hBmp);
    ReleaseDC(0, aDC);
  END;
END;

ShoAn 28. Apr 2003 16:13

@RobertS: hehe, ich habn k6 2 300mhz ;)

also jetzt geht eigentlich alles ganz gut. ich hab noch nebenbei reingemacht, dass man die größe von dem bild verändern kann:

Delphi-Quellcode:
procedure aScreenShot(const aFileName: String; Quality, Width, Height : Integer);
var
  aDC      : hDC;
  aBmp     : TBitmap;
  aJpg     : TJPEGImage;
  mh, hBmp : THandle;

begin
  ajpg       := TJPEGImage.Create;
  aBmp       := TBitmap.Create;
  aBmp.Width := Screen.DesktopWidth;
  aBmp.Height := Screen.DesktopHeight;
  aDC        := GetDC(0);
  hBmp       := CreateCompatibleBitmap(aDC, Screen.Width, Screen.Height);
  mh         := SelectObject(aDC, hBmp);

  try
    BitBlt(aBmp.Canvas.Handle, 0, 0, aBmp.Width, aBmp.Height, aDC, 0, 0, SRCCopy);

    ajpg.Assign(aBmp);

    aBmp.Width := Width;
    aBmp.Height := Height;
    aBmp.Canvas.StretchDraw(Rect(0, 0, aBmp.Width, aBmp.Height), ajpg);

    ajpg.assign(aBmp);
    ajpg.CompressionQuality := Quality;
    ajpg.Compress();
    ajpg.SaveToFile(aFileName);
  finally
    ajpg.Free;
    aBmp.Free;
    SelectObject(aDC, mh);
    DeleteObject(hBmp);
    ReleaseDC(0, aDC);
  end;
end;
kann mal jemand schnell trübergucken, ob das auch so performance-mäßig ok ist? weil, wenn ich jetzt auf den button klicke, bleibt meine maus sogar für knapp eine sekunde hängen ;) naja, vielleicht liegts auch an meiner alten krück ;)

Tim.exe 29. Apr 2003 14:53

@ ShoAn:

Mal ne ganz dumme Frage, wie ist den der ButtonClick dazu, also der Aufruf???

ShoAn 29. Apr 2003 15:16

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  aScreenShot('bildsche.jpeg', 75, 640, 480);
end;

Tim.exe 12. Aug 2003 07:29

Re: screenshot als jpeg
 
Den Thread möchte ich nochmal kurz beleben :wink:

Bei mir funktioniert das ganze nicht so einwandfrei.

Also ich habe als erstes die Funktion um einen Screenshot zu machen:
Delphi-Quellcode:
function GetScreenShot: TBitmap;
var
  Desktop: HDC;
begin
  Result := TBitmap.Create;
  Desktop := GetDC(0);
  try
    try
      Result.PixelFormat := pf32bit;
      Result.Width      := Screen.Width;
      Result.Height     := Screen.Height;
      BitBlt(Result.Canvas.Handle, 0, 0, Result.Width, Result.Height, Desktop, 0, 0, SRCCOPY);
      Result.Modified := True;
    finally
      ReleaseDC(0, Desktop);
    end;
  except
    Result.Free;
    Result := nil;
  end;
end;
Dann die Procedure um das Bild in TImage in Jpeg zu konvertieren:
Delphi-Quellcode:
procedure aScreenShot(const aFileName: String; Quality, Width, Height : Integer);
var
  aDC      : hDC;
  aBmp     : TBitmap;
  aJpg     : TJPEGImage;
  mh, hBmp : THandle;

begin
  ajpg       := TJPEGImage.Create;
  aBmp       := TBitmap.Create;
  aBmp.Width := Screen.DesktopWidth;
  aBmp.Height := Screen.DesktopHeight;
  aDC        := GetDC(0);
  hBmp       := CreateCompatibleBitmap(aDC, Screen.Width, Screen.Height);
  mh         := SelectObject(aDC, hBmp);

  try
    BitBlt(aBmp.Canvas.Handle, 0, 0, aBmp.Width, aBmp.Height, aDC, 0, 0, SRCCopy);

    ajpg.Assign(aBmp);

    aBmp.Width := Width;
    aBmp.Height := Height;
    aBmp.Canvas.StretchDraw(Rect(0, 0, aBmp.Width, aBmp.Height), ajpg);

    ajpg.assign(aBmp);
    ajpg.CompressionQuality := Quality;
    ajpg.Compress();
    ajpg.SaveToFile(aFileName);
  finally
    ajpg.Free;
    aBmp.Free;
    SelectObject(aDC, mh);
    DeleteObject(hBmp);
    ReleaseDC(0, aDC);
  end;
end;
Um einen Screenshot manuell zu schiessen folgendes:
Delphi-Quellcode:
Image1.Picture := nil;
Image1.Picture.Bitmap := GetScreenshot;
Um den Screenshot manuell zu speichern (Datum.Caption ist der Name und in den SpinEdits steht die Bildgröße in Pixel):
Delphi-Quellcode:
procedure TForm1.suiButton2Click(Sender: TObject);
begin
Try
        aScreenShot('Screenshots\Screenshot ' + ' ' +Datum.Caption+' Uhr.jpg', 75, SpinEdit1.Value, SpinEdit2.Value);
        Except
        MKDir(ExtractFilepath(Application.Exename)+'Screenshots');
        aScreenShot('Screenshots\Screenshot ' + ' ' +Datum.Caption+' Uhr.jpg', 75, SpinEdit1.Value, SpinEdit2.Value);
end;
end;
Soweit funktioniert alles, wenn ich einen Screenshot aber automatisch (über Timer) schiessen und speichern will, z.B. jede Std. wird manchmal der erste Screenshot gemacht (nach einer Std) und bei jedem weitern erfolgt eine Fehlermeldung von wegen "...kann nicht gespeichert werden..." Code:
Delphi-Quellcode:
procedure TForm1.TScreenshotsTimer(Sender: TObject);
begin
        Image1.Picture := nil;
        Image1.Picture.Bitmap := GetScreenshot;
        Try
        aScreenShot('Screenshots\Screenshot ' + ' ' +Datum.Caption+' Uhr.jpg', 75, SpinEdit1.Value, SpinEdit2.Value);
        Except
        MKDir(ExtractFilepath(Application.Exename)+'Screenshots');
        aScreenShot('Screenshots\Screenshot ' + ' ' +Datum.Caption+' Uhr.jpg', 75, SpinEdit1.Value, SpinEdit2.Value);
end;
end;
Liegt es an der Timer Procedure oder ist die Umwandlungsprozedure (BMP->JPG) zu langsam???

alcaeus 12. Aug 2003 09:22

Re: screenshot als jpeg
 
Also Tim.exe, unter welchen Umständen tritt bei dir denn dieser Fehler auf? Ich hab das ganze jetzt probiert, und es funzt perfekt. Ich habe nur den Dateinamen des Pics geändert, aber ich kann mir nicht vorstellen dass das den Unterschied macht.

Tim.exe 12. Aug 2003 09:39

Re: screenshot als jpeg
 
Hallo,

also es kommt eine Fehlermeldung das die Datei nicht gespeichert werden kann (Screenshot wurde aber zuvor getätigt). Jetzt ist die Frage ob er das Verzeichnis "Screenshots" nicht findet oder ob es ein Problem mit dem Dateinamen gibt. Wie gesagt wird der erste Screenshot nach einer Std einwandfrei getätigt und gespeichert. Der zweite (nach 2 Std) nicht mehr (getätigt schon aber Fehler beim speichern).

Ich teste es im Moment in der Arbeit (Win2000). Wenn der Fehler kommt poste ich den Screenshot. Im Moment sieht es gut aus, der erste Screenshot wurde bereits gemacht. Sollte der zweite und alle anderen folgenden auch klappen dann liegt es wohl an meinem WinXP Prof zu Hause. Könnte das sein?

alcaeus 12. Aug 2003 11:00

Re: screenshot als jpeg
 
Also, ich verwende zu Hause auch WinXP Pro, habe aber keine Probleme. Versuch mal das Intervall zu verkürzen, dann kann man die ganze Sache einfacher testen. Es ist aber möglich dass es Probleme mit dem Verzeichnis gibt, versuch mal die ganzen Screenshots auf C:\ abzuspeichern. Das hat bei mir gefunzt...

Tim.exe 12. Aug 2003 11:09

Re: screenshot als jpeg
 
Also hier in der Arbeit klappt es wunderbar. Werde es heute abend nochmal probieren und es dann auch mal auf C: speichern lassen. Ich melde mich dann wieder, vielen Dank :D

Tim.exe 12. Aug 2003 13:49

Re: screenshot als jpeg
 
Liste der Anhänge anzeigen (Anzahl: 1)
So, nu ist es auch bei Win2000 geschehen, siehe Anhang:

alcaeus 12. Aug 2003 13:52

Re: screenshot als jpeg
 
Aber vorher funktionierts immer? Hast du auch sicher noch genug Festplattenspeicher übrig? Das sieht mir nämlich nach so einem Problem aus...

Tim.exe 12. Aug 2003 14:18

Re: screenshot als jpeg
 
Hallo,

ja hab ich, aber da fällt mir noch was ein:

Als ich es heute morgen ausführlich getestet habe lief die Delphi IDE, habe das Programm also aus Delphi heraus gestartet gehabt. Jetzt bei diesem Fehler lief nur die *.exe, ohne Delphi.


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:47 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