screenshot als Bild in PDF speichern

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
__deets__
User
Beiträge: 8416
Registriert: Mittwoch 14. Oktober 2015, 14:29

Samstag 1. August 2020, 23:02

Das was du als Screenshot bezeichnest ist ein Python Objekt. Aus dem Modul pyautogui. Das damit ein anderes Modul nicht viel anfangen kann, ist nicht weiter verwunderlich. Dein Auto kann wahrscheinlich auch nix mit dem Motor des Nachbarn anfangen.

Womit wer anders etwas anfangen kann, sind generische Bildformate. Das KANN PNG sein. Oder auch RGB (zb als numpy Array). Man muss also mindestens einen Weg finden, das Objekt in eines dieser Formate zu überführen.

Und dann kommt es noch darauf an, wie die Bibliothek ein genehmes Format annimmt. Es kann sein, das es nur ein Dateipfad ist. Dann kommst du ums Speichern nicht herum. Oder es erlaubt (in Python oft) die Angabe als „file like object“. Also etwas, das sich so verhält, wie eine Datei. Und da kommt dann io.BytesIO zum tragen. Damit „simuliert“ Python eine Datei im Speicher.

Du kannst also versuchen, das Screenshot objekt in ein BytesIO Objekt zu „speichern“ - dann ist es aber nur im Hauptspeicher. Und das dann zu „laden“ mit der PDF Bibliothek.
__deets__
User
Beiträge: 8416
Registriert: Mittwoch 14. Oktober 2015, 14:29

Samstag 1. August 2020, 23:02

Das was du als Screenshot bezeichnest ist ein Python Objekt. Aus dem Modul pyautogui. Das damit ein anderes Modul nicht viel anfangen kann, ist nicht weiter verwunderlich. Dein Auto kann wahrscheinlich auch nix mit dem Motor des Nachbarn anfangen.

Womit wer anders etwas anfangen kann, sind generische Bildformate. Das KANN PNG sein. Oder auch RGB (zb als numpy Array). Man muss also mindestens einen Weg finden, das Objekt in eines dieser Formate zu überführen.

Und dann kommt es noch darauf an, wie die Bibliothek ein genehmes Format annimmt. Es kann sein, das es nur ein Dateipfad ist. Dann kommst du ums Speichern nicht herum. Oder es erlaubt (in Python oft) die Angabe als „file like object“. Also etwas, das sich so verhält, wie eine Datei. Und da kommt dann io.BytesIO zum tragen. Damit „simuliert“ Python eine Datei im Speicher.

Du kannst also versuchen, das Screenshot objekt in ein BytesIO Objekt zu „speichern“ - dann ist es aber nur im Hauptspeicher. Und das dann zu „laden“ mit der PDF Bibliothek.
UniversalBastler
User
Beiträge: 14
Registriert: Samstag 1. August 2020, 12:08

Samstag 1. August 2020, 23:37

Sorry Leute,
bei stackoverflow habe ich den Hinweis gefunden und wie ich es mir schon gedacht habe ist die Lösung ganz einfach.

Ich weise mit

screenshot1 = pyautogui.screenshot("seiteL.png" ,region=(80,48, 880, 960))

gleich den Namen (seiteL.png) zu und dann mit

pdf.image("seiteL.png" ,10 ,40, 200)

schreibe ich den screenshot auf die PDF Seite.
Ich brauche nichts mehr zwischen zu speichern und alles ist gut.
Nochmals vielen Dank

Nachfolgend für alle die es interessiert der vereinfachte Teilcode

Code: Alles auswählen

import pyautogui
from time import sleep
from fpdf import FPDF 

pdf = FPDF()#PDF wird erstellt

screenshot1 = pyautogui.screenshot("seiteL.png" ,region=(80,48, 880, 960))#screeshot der ersten Seite (linke Hälfte)
sleep(1) #warten bist erledigt

pdf.add_page() #Seite wird dem PDF zugefügt
pdf.image("seiteL.png" ,10 ,40, 200) #screenshot (jetzt seiteL.png) wird auf der PDF Seite positioniert

sleep(1)

pdf.output("PDF-Test3.pdf", "F") #fertiges PDF wird gespeichert
print("Fertig")
__deets__
User
Beiträge: 8416
Registriert: Mittwoch 14. Oktober 2015, 14:29

Sonntag 2. August 2020, 07:10

Dann speichert pyautogui halt direkt. Es ist aber immer noch zwischengespeichert. Und das PNG fliegt irgendwo rum.
Sirius3
User
Beiträge: 12423
Registriert: Sonntag 21. Oktober 2012, 17:20

Sonntag 2. August 2020, 07:12

Du speicherst ja trotzdem zwischen, auch wenn das nun die Funktion screenshot direkt für dich erledigt. Aber wenn du meinst, dass das dir Lösung ist, die du gesucht hast, dann ist ja gut. Jetzt muss nur noch der überflüssige Code weg:

Code: Alles auswählen

import pyautogui
from fpdf import FPDF 

pdf = FPDF()

pyautogui.screenshot("seiteL.png" ,region=(80,48, 880, 960))#screeshot der ersten Seite (linke Hälfte)

pdf.add_page()
pdf.image("seiteL.png" ,10 ,40, 200) #screenshot (jetzt seiteL.png) wird auf der PDF Seite positioniert

pdf.output("PDF-Test3.pdf", "F") #fertiges PDF wird gespeichert
print("Fertig")
UniversalBastler
User
Beiträge: 14
Registriert: Samstag 1. August 2020, 12:08

Sonntag 2. August 2020, 10:32

Okay, das mit dem Zwischenspeichern war vielleicht von mir falsch ausgedrückt.
Natürlich muss der screenshot bzw. das Objekt oder Bild irgendwo im Speicher landen sonst könnte man es ja nicht in die PDF Schreiben.
Es ging aber darum, das nicht jedes mal auf die Festplatte zu schreiben.

@Sirius3
vielen Dank für die weitere Bereinigung des Codes. Zumindest das erste sleep(1) hätte ich gedacht, das es gebraucht wird weil angeblich der screenshot durchaus mehrere hundert Millisekunden brauchen kann. Aber es scheint auch so zu gehen :D
Dass ich die Variable screenshot1 gar nicht brauche erscheint mir (hinterher) auch klar.
Auf jeden Fall wieder was dazu gelernt :geek:
__deets__
User
Beiträge: 8416
Registriert: Mittwoch 14. Oktober 2015, 14:29

Sonntag 2. August 2020, 10:39

Du *schreibst* das doch jetzt auf die Festplatte. Du instruierst pyautogui das fuer dich zu machen, aber das ist auch der einzige Unterschied. Das wird *immer* noch auf die Platte geschrieben. Und vor allem auch in einen relativen Pfad, das heisst, dass die Datein irgendwo landen - und nicht kontrolliert zB im TEMP-Verzeichnis. Wenigstens dahingehend wuerde ich das Programm noch ueberarbeiten.
UniversalBastler
User
Beiträge: 14
Registriert: Samstag 1. August 2020, 12:08

Sonntag 2. August 2020, 11:42

Du *schreibst* das doch jetzt auf die Festplatte.
Ich habe es gerade auch festgestellt. :o
Aber das macht dann doch pyautogui.screenshot() selbstständig oder?
Na gut, dann soll es halt so sein :cry:
Wo das hingeschrieben wird habe ich im Griff, da kann ich einfach den Pfad mit angeben.
Sirius3
User
Beiträge: 12423
Registriert: Sonntag 21. Oktober 2012, 17:20

Sonntag 2. August 2020, 12:12

Wie schon geschrieben, muss man tief in die Klasse eingreifen, um das zu ändern.

Code: Alles auswählen

import pyautogui
from io import BytesIO
from fpdf import FPDF

class Fpdf(FPDF):
    def load_resource(self, reason, file):
        if hasattr(file, "read"):
            return file
        return FPDF.load_resource(self, reason, file)

pdf = Fpdf()
image = BytesIO()
screenshot1 = pyautogui.screenshot(region=(80,48, 880, 960))#screeshot der ersten Seite
screenshot1.save(inage, fornat="png")
image.seek(0)
pdf.add_page() #Seite wird dem PDF zugefügt
pdf.image(image,10, 40, 200, type="png") #screenshot wird auf der PDF Seite positioniert

pdf.output("PDF-Test3.pdf", "F") #fertiges PDF wird gespeichert
print("Fertig")
[/quote]
UniversalBastler
User
Beiträge: 14
Registriert: Samstag 1. August 2020, 12:08

Sonntag 2. August 2020, 15:05

Sorry, soweit bin ich noch nicht.
Trotzdem Danke :mrgreen:
Benutzeravatar
noisefloor
User
Beiträge: 2933
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: Görgeshausen
Kontaktdaten:

Montag 3. August 2020, 06:54

Hallo,

ReportLab ist mächtiger, weil es (viel) mehr Möglichkeiten hat. Aber deswegen ist es nicht wirklich komplizierter:

Code: Alles auswählen

>>> import pyautogui
>>> from reportlab.platypus import SimpleDocTemplate, Image
>>> from reportlab.lib.pagesizes import A4
>>> from io import BytesIO
>>> image = BytesIO()
>>> screenshot1 = pyautogui.screenshot(region=(80,48, 200, 200))
>>> screenshot1.save(image, format='png')
>>> doc = SimpleDocTemplate("image.pdf", pagesize=A4)
>>> story=[]
>>> story.append(Image(image))
>>> doc.build(story)
Das PDF mit den Screenshot ist dann im Verzeichnis, wo das Skript liegt, als "image.pdf" gespeichert.

Gruß, noisefloor
Benutzeravatar
__blackjack__
User
Beiträge: 6559
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Montag 3. August 2020, 11:25

@noisefloor: Kleine Korrektur: Das PDF ist dann im aktuellen Arbeitsverszeichnis gespeichert. Ob das das gleiche ist in dem das Skript liegt, hängt davon ab wie/von wo man das startet.
long long ago; /* in a galaxy far far away */
UniversalBastler
User
Beiträge: 14
Registriert: Samstag 1. August 2020, 12:08

Montag 3. August 2020, 12:39

Hallo,
Vielen Dank aber ihr bringt mich an meine Grenzen :oops:
Also mit BytesIO und reportlap muss ich mich dann doch mal beschäftigen.
Ich bin eigentlich davon ausgegangen, dass mit screenshot1.save(image, format='png') das png Bild auf die Festplatte gespeichert wird, finde es aber nicht.
Oder liegt das an dem BytesIO ? Gut, muss ich mich erst einarbeiten.
Das reportlab muss ich auch tiefer eintauchen, das Bild (Screenshot eines halben Bildschirm's) kann sicher auch hier so skaliert werden, dass es auf eine A4 Seite passt.
Benutzeravatar
noisefloor
User
Beiträge: 2933
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: Görgeshausen
Kontaktdaten:

Montag 3. August 2020, 13:45

Hallo,
Ich bin eigentlich davon ausgegangen, dass mit screenshot1.save(image, format='png') das png Bild auf die Festplatte gespeichert wird, finde es aber nicht.
Tut's auch. Das Bild sollte da liegen, wo das aktuelle Arbeitsverzeichnis des Skripts ist.
Oder liegt das an dem BytesIO ? Gut, muss ich mich erst einarbeiten.
Nein. Mit BytesIO erzeugst du ein "file-like object", also ein Objekt, was sich wie eine Datei verhält (aber nicht unbedingt eine ist). Mit BytesIO sparst du dir den Zwischenschritt des Speicherns auf ein Laufwerk, das Bild bzw. die "Datei" wird im Speicher gehalten.
Das reportlab muss ich auch tiefer eintauchen, das Bild (Screenshot eines halben Bildschirm's) kann sicher auch hier so skaliert werden, dass es auf eine A4 Seite passt.
Ja, aber nicht über ReportLab. Die Platypus.Image Klasse kennt keine Größenangaben. Das musst du vorher machen. PyAutoGUI.screenshot liefert dir ja ein PIL Objekt, das hat Methoden, um das Bild zu skalieren:

Code: Alles auswählen

>> from pyautogui import screenshot
>>> image = screenshot()
>>> image
<PIL.PngImagePlugin.PngImageFile image mode=RGB size=1366x768 at 0x7F6286F1C610>
>>> image.size
(1366, 768)
>>> image = image.resize((800, 450))
>>> image.size
(800, 450)
Gruß, noisefloor
Sirius3
User
Beiträge: 12423
Registriert: Sonntag 21. Oktober 2012, 17:20

Montag 3. August 2020, 15:52

@UniversalBastler: image ist ein BytesIO-Objekt, `save` speichert also nur was im Speicher und nicht auf Festplatte. Das ist doch das, was Du möchtest.

@noisefloor: resize verändert doch nur die Pixelanzahl und hat erstmal nichts damit zu tun, wie groß das Bild dann auf der PDF-Seite dargestellt wird.
Antworten