PIL Bit-tiefe ändern || C# Codes für python verwendbar machen

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.
rennmaus
User
Beiträge: 217
Registriert: Dienstag 4. August 2020, 10:24

Das steht zumindest da, wenn ich ein Bild mache und dann aufm Laptop in die Eigenschaften gehe
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Also ich finde online MAXIMAL 16 Bit / Kanal, also 48 Bit total, für DSLRs. Das ist also in meinen Augen nicht so zu interpretieren, wie du das tust. 16.7Millionen Graustufen klingt auch milde übertrieben.
rennmaus
User
Beiträge: 217
Registriert: Dienstag 4. August 2020, 10:24

Ich habe das jetzt mir einer exe aus der C# datei gemacht... Ich probiere mich gerade an Klassen, läuft ganz gut! Wollt ihr mal sehen und mich verbessern? Wäre euch dankbar!

mfg
Christian
Benutzeravatar
__blackjack__
User
Beiträge: 14053
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Um .NET-DLLs aus CPython heraus zu nutzen gibt es übrigens ein Projekt: http://pythonnet.github.io/

Und natürlich IronPython, eine Python-Implementierung für die .NET-Laufzeitumgebung.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
rennmaus
User
Beiträge: 217
Registriert: Dienstag 4. August 2020, 10:24

Ah ok. Könntet ihr vielleicht mal kurz meine Klasse anschauen und sagen was ich besser machen könnte? :) aber nur wenn ihr wollt:

Code: Alles auswählen

import os
from PIL import Image
import subprocess
import sys


class Convert:

    counter = 0

    def __init__(self, img_dir, save_dir=os.path.join(os.path.join(os.environ['USERPROFILE']), 'Pictures')):
        """Filetypes = png gif bmp tiff"""
        self.img_dir = img_dir  # Wert wird der Klasse zugeordnet
        self.save_dir = save_dir  # Wert wird der Klasse zugeordnet
        filetypes = ["png", "tiff", "gif", "bmp"]
        if os.path.isfile(img_dir):  # Überpüft ob die Datei existiert, um einen Error abzufangen
            pass
        else:
            raise FileNotFoundError("The file wasn't found: " + img_dir)
        if os.path.isdir(save_dir):  # Überpüft ob der Pfad existiert, um einen Error abzufangen
            pass
        else:
            raise FileNotFoundError("The directory wasn't found: " + save_dir)
        if img_dir.split(".")[-1] in filetypes:
            pass
        else:
            raise Exception("File type must be one of the following: png, jpg, gif, tiff, ico, bmp")

    def _check_dir(self, directory):
        while directory.split("\\")[-1] in os.listdir(self.save_dir):  # Wenn die Datei schon existiert, wird verhindert, dass sie überschrieben wird.
            self.counter += 1

            path = directory.split(".")
            endung = path[-1]  # Die Endung wird "extrahiert"
            directory = path[0]  # Der Pfad wird "extrahiert"
            pfad = str(self.counter)+"."+endung  # Der Pfad wird wieder zusammengesetzt
            directory = os.path.join(directory +"_"+ pfad)  # Der Pfad wird fertiggestellt

        return directory  # Der richtige Pfad wird zurückgeliefert

    def to_jpg(self, qual=100):
        """Convert an image to jpg. Paramter: quality for the resulting jpg, standart set to 100"""
        try:
            image = Image.open(self.img_dir)  # Bild wird geöffnet
        except OSError:
            raise OSError("This path is not valid: " + self.img_dir)  # Wenn die datei nicht existiert, gibt es einen Errors

        if image.mode != 'RGB':
            image = image.convert('RGB')  # Bild wird in den richtigen Modus konvertiert

        _out = os.path.join(self.save_dir, "out.jpg")  # Der Pfad wird zusammengetzt

        out = self._check_dir(_out)  # Der Pfad wird überprüft

        image.save(out, "JPEG", quality=qual)  # Das Bild wird gespeichert

        # Das wiederholt sich auf alle methoden für das Konvertieren (to_...)

    def to_png(self):
        """Convert an Image to png"""
        try:
            image = Image.open(self.img_dir)
        except OSError:
            raise OSError("This path is not valid: " + self.img_dir)

        if image.mode != "RGBA":
            image = image.convert("RGBA")

        _out = os.path.join(self.save_dir, "out.png")

        out = self._check_dir(_out)

        image.save(out)

    def to_tiff(self):
        """Convert an Image to tiff"""
        try:
            image = Image.open(self.img_dir)
        except OSError:
            raise OSError("This path is not valid: " + self.img_dir)

        if image.mode != "CMYK":
            image.convert("CMYK")

        _out = os.path.join(self.save_dir, "out.tiff")

        out = self._check_dir(_out)

        image.save(out)

    def to_gif(self):
        """Convert an Image to GIF"""
        try:
            image = Image.open(self.img_dir)
        except OSError:
            raise OSError("This path is not valid: " + self.img_dir)

        if image.mode != "RGBA":
            image.convert("RGBA")

        _out = os.path.join(self.save_dir, "out.gif")

        out = self._check_dir(_out)

        image.save(out)

    def to_ico(self, alpha_channel="y"):
        """Convert Image to ico. Parameter: Alpha_channel = 'y'/'n'"""
        try:
            image = Image.open(self.img_dir)
        except OSError:
            raise OSError("This path is not valid: " + self.img_dir)

        if image.mode != "RGBA" and alpha_channel == "y":
            image.convert("RGBA")
        elif image.mode != "RGB" and alpha_channel != "y":
            image.convert("RGB")

        _out = os.path.join(self.save_dir, "out.ico")

        out = self._check_dir(_out)

        image.save(out)

    def bit(self, bits):
        """Changes to bit depth. NOT AVAILABLE FOR JPG AND ICO"""
        bits = str(bits)
        pfad = self.img_dir.split(".")[-1]
        _out = os.path.join(self.save_dir, "out."+str(pfad))

        out = self._check_dir(_out)
        args = [os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), "ConsoleApp1.exe"),
                self.img_dir, bits, out]
        subprocess.call(args)

    def to_pdf(self):
        """Convert Image to pdf"""
        try:
            image = Image.open(self.img_dir)
        except OSError:
            raise OSError("This path is not valid: " + self.img_dir)

        _out = os.path.join(self.save_dir, "out.pdf")

        out = self._check_dir(_out)

        image.save(out)

    def to_tif(self):
        """Convert Image to TIF"""
        try:
            image = Image.open(self.img_dir)
        except OSError:
            raise OSError("This path is not valid: " + self.img_dir)

        _out = os.path.join(self.save_dir, "out.TIF")

        out = self._check_dir(_out)

        image.save(out)

Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

Klassenvariablen sind kein Ersatz für Instanzattribute.
os.path.join mit nur einem Argument aufzurufen ist unsinnig.
Wenn im if-Block nur `pass` steht, dann dreht man die Bedingung um.
In `_check_dir`: Pfade verarbeitet man nicht mit String-Operationen. Statt per os.listdir zu prüfen, würde man nur die Existenz des Pfads prüfen.
Willst Du wirklich den Pfad immer weiter mit _-Teilen erweitern?
In den ganzen to_-Methoden: Das Exceptionhandling ist totaler Quatsch, weil Du die eigentliche Fehlermeldung in eine weniger aussagekräftige umwandelst.
_check_dir wird gar nicht mit einem Verzeichnis aufgerufen, sondern mit einem Dateinamen.
Die ganzen to_Methoden sind fast identisch und könnten ohne Probleme in eine Methode zusammengefasst werden.
Insgesamt macht die Klasse wenig Sinn.
Du hast ein Inputfile und ein Outputfile. Das wäre deutlich lesbarer, wenn es eine convert-Funktion gäbe, die diese beiden Argumente bekommt.
Bleibt also:

Code: Alles auswählen

def make_unique_filename(filename):
    counter = 0
    original_filename, extension = os.path.splitext(filename)
    while os.path.exists(filename):
        counter += 1
        filename = f"{original_filename}_{counter}{extension}"
    return filename


def convert(inputfilename, outputfilename, qual=100, alpha_channel="y"):
    outputfilename = make_unique_filename(outputfilename)
    image = Image.open(inputfilename)  # Bild wird geöffnet
    _, extension = os.path.splitext(outputfilename)
    if extension == '.jpg':
        if image.mode != 'RGB':
            image = image.convert('RGB')  # Bild wird in den richtigen Modus konvertiert
        type = "JPEG"
        image.save(outputfilename, "JPEG", quality=qual)  # Das Bild wird gespeichert
        return
    elif extension in ('.png', '.gif'):
        if image.mode != "RGBA":
            image = image.convert("RGBA")
    elif extension == '.tiff':
        if image.mode != "CMYK":
            image.convert("CMYK")
    elif extension == '.ico':
        if image.mode != "RGBA" and alpha_channel == "y":
            image.convert("RGBA")
        elif image.mode != "RGB" and alpha_channel != "y":
            image.convert("RGB")
    image.save(outputfilename)


def bit(inputfilename, outputfilename, bits):
    """Changes to bit depth. NOT AVAILABLE FOR JPG AND ICO"""
    outputfilename = make_unique_filename(outputfilename)
    args = [os.path.join(os.path.dirname(os.path.abspath(__file__)), "ConsoleApp1.exe"),
            inputfilename, str(bits), outputfilename]
    subprocess.call(args)
Zuletzt geändert von Sirius3 am Donnerstag 11. Februar 2021, 14:17, insgesamt 1-mal geändert.
rennmaus
User
Beiträge: 217
Registriert: Dienstag 4. August 2020, 10:24

Ich übe :)
Antworten