Speichern von Image als JPG auf Festplatte

MiMa

Top Contributor
Aktuell habe ich ein Problem welches ich schon seit einger Zeit versuche zu lösen aber nicht mehr weiter weis.
In einer Variable bild vom Typ Image liegt der Inhalt im Speicher.
Java:
public static void speichernBild(Image bild, String dateiname) {
        try {
            BufferedImage bufferedImage = SwingFXUtils.fromFXImage(bild, null);
            if (bufferedImage != null)
                System.out.println("Das Buffered Image ist nicht leer");

            File output = new File(dateiname);
            System.out.println("Der Dateiname : " + dateiname);
            ImageIO.write(bufferedImage, "jpg", output);

            if (new File(dateiname).exists()){
                System.out.println("Das Bild wurde gespeichert : " + dateiname);
            } else{
                System.out.println("Das Bild wurde nicht gespeichert");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    } // speichernBild

Das Bild wird auf Festplatte gespeichert und kann es mir auch ansehen.

Jetzt habe ich eine weitere Methode, die Bilder Skallieren soll
Code:
public static Image skaliereBild(Image bild, int maximaleBreite, int maximaleHöhe) {
        int ursprünglicheBreite = (int) bild.getWidth();
        int ursprünglicheHöhe = (int) bild.getHeight();

        // Überprüfen, ob eine Skalierung erforderlich ist
        if (ursprünglicheBreite <= maximaleBreite && ursprünglicheHöhe <= maximaleHöhe) {
            return bild; // Keine Skalierung erforderlich
        }

        // Berechnen der Skalierungsfaktoren
        double faktorBreite = (double) maximaleBreite / ursprünglicheBreite;
        double faktorHöhe = (double) maximaleHöhe / ursprünglicheHöhe;
        double skalierungsfaktor = Math.min(faktorBreite, faktorHöhe);

        // Skalieren des Bildes
        int neueBreite = (int) (ursprünglicheBreite * skalierungsfaktor);
        int neueHöhe = (int) (ursprünglicheHöhe * skalierungsfaktor);

        BufferedImage skaliertesBufferedImage = new BufferedImage(neueBreite, neueHöhe, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = skaliertesBufferedImage.createGraphics();
        g2d.drawImage(SwingFXUtils.fromFXImage(bild, null), 0, 0, neueBreite, neueHöhe, null);
        g2d.dispose();

        return SwingFXUtils.toFXImage(skaliertesBufferedImage, null);
    }

Wenn ich ein Bild habe welches im Original 1200x1200 Pixel, gross ist und ich die Methode wie folgt aufrufe

Code:
Image skaliertesBild = Bild.skaliereBild(coverBild, 600, 600);
if (skaliertesBild != null) {
                System.out.println("Das Skallierte Bild ist nicht null");
                int breite = (int) skaliertesBild.getWidth();
                int hoehe = (int) skaliertesBild.getHeight();
                System.out.println("Das Bild hat die Größe: " + breite + "x" + hoehe);

            } else {
                System.out.println("Das Skallierte Bild ist null");
            }

Erhalte ich folgendes in der Konsole
Das Skallierte Bild ist nicht null
Das Bild hat die Größe: 600x600
Das Buffered Image ist nicht leer
Das Bild wurde gespeichert : D:\temp\CoverBild_skaliert.jpg
Allerdings wird die gespeicherte Datei nirgends auf der Festplatte gefunden.
Ich vermute, das es nicht geschrieben wurde. Dann habe ich die Speichern Methode erweitert mit der existenzprüfung und habe richtig vermutet, das Bild wurde nicht geschrieben.
Ein Bild welches unter 600x600 liegt wie 500x500, wurde von der Skallieren methode nicht verändert und unbearbeitet zurück gegeben. Dieses wurde auch ordnungsgemäss auf Festplatte gespeichert. Bilder die grösser sind als 600x600 wurden skalliert, und laut Konsolenausgabe sind diese nicht null oder leer und haben auch die richtige Breite und Höhe 600x600 aber lassen sich irgendwie nicht speichern???

Hat jemand eine Idee woran das liegen kann?
Mein Projekt ist meine Methoden-Bibliothek welches JavaFX 20 enthält aber keine grafische Oberfläche.
In diesem Projekt schreibe ich hauptsächlich Methoden die ohne Oberfläche arbeiten.

Vielen Dank
 
Zuletzt bearbeitet:

KonradN

Super-Moderator
Mitarbeiter
Also prinzipiell sieht das, was du an Code zeigst, korrekt aus.

Aber du zeigst nicht den genauen Code, der die Meldungen gebracht hat. Evtl. zeigst Du den genauen Code, der das skalierte Bild dann speichert. Dein Code endet mit der Ausgabe der Größe und du zeigst nicht den Code, der die weiteren Meldungen anzeigt. Evtl. hast Du irgend eine Abweichung zu dem Code zum Speichern, den Du zuerst gezeigt hast.

Was zu dem Code noch auffällt: Die write Methode gibt ein boolean zurück. Das solltest Du auch prüfen. Wenn da false zurück gegeben wurde, dann bedeutet das, dass kein passender Writer gefunden wurde. Das könnte meines Wissens nach der Fall sein, wenn Du Dich beim Typ vertippt haben solltest.
 

Oneixee5

Top Contributor
ImageIO.write hat eine Rückgabe: false if no appropriate writer is found.
Hast du diese schon mal ausgewertet?

String writerNames[] = ImageIO.getWriterFormatNames();
Gibt dir die möglichen Bildformate für dein sytem zurück.
 

MiMa

Top Contributor
@Oneixee5
Ja habe geprüft und daran dürfte es nicht liegen.

@KonradN
weiss nicht welchen genauen Code du meinst?
Hier ist der Code um die Methoden auf zu rufen. Dabei wird das Image aus eine MP3 Datei extrahiert und weiterverarbeitet.
Java:
Image coverBild = metaDaten.getAlbumCover();
        if (coverBild != null) {
            // Speichere das Originalbild
            Bild.speichernBild(coverBild, metaDaten.getQuelle().getParent() + File.separator + metaDaten.getNameOhneEndung() + "_org.jpg");

            // Skaliere das Bild
            Image skaliertesBild = Bild.skaliereBild(coverBild, 600, 600);

            if (skaliertesBild != null) {
                System.out.println("Das Skalierte Bild ist nicht null");
                int breite = (int) skaliertesBild.getWidth();
                int hoehe = (int) skaliertesBild.getHeight();
                System.out.println("Das Bild hat die Größe: " + breite + "x" + hoehe);

            } else {
                System.out.println("Das Skalierte Bild ist null");
            }

            // Speichere das skalierte Bild
            Bild.speichernBild(skaliertesBild, metaDaten.getQuelle().getParent() + File.separator + metaDaten.getNameOhneEndung() + "_skaliert.jpg");
        } else {
            System.out.println("Fehler beim Laden des Bildes.");
        }

Das ist die Ausgabe in der Konsole
Das Buffered Image ist nicht leer
Der Dateiname : D:\DMS\01 Postfach\1-01 Sweet But Psycho_org.jpg (Orginalbild ohne Skalierung)
Das Bild wurde gespeichert : D:\DMS\01 Postfach\1-01 Sweet But Psycho_org.jpg
Das Skallierte Bild ist nicht null
Das Bild hat die Größe: 600x600
Das Buffered Image ist nicht leer
Der Dateiname : D:\DMS\01 Postfach\1-01 Sweet But Psycho_skaliert.jpg (Dateiname für das Skalierte Bild)
Das Bild wurde nicht gespeichert
 

KonradN

Super-Moderator
Mitarbeiter
Ich habe es mir jetzt etwas angeschaut und das Problem dürfte das BufferedImage sein, welches zurück gegeben wird. Du kannst einmal beim Speichern ausgeben lassen:

Java:
            System.out.println(bufferedImage.getColorModel());
            System.out.println(bufferedImage.getType());

Ebenso solltest Du den Rückgabewert vom write Aufruf auswerten. Der müsste bei Dir auch false sein.

Leider nur Vermutungen, da ich jetzt keine Zeit mehr habe, es zu verifizieren:

Das Problem wird sein, dass SwingFXUtils.fromFXImage ein Ergebnis liefert, das auch einen Alpha Kanal hat. JPEG unterstützt keinen Alpha Kanal.

Mögliche Lösungen:
  • Statt jpg gibst Du ein Format an, das auch einen Alpha Kanal unterstützt. Das könnte z.B. PNG sein.
  • Du kannst das Ziel BufferedImage vorab erzeugen (z.B. als BufferedImage.TYPE_INT_RGB) und dann als zweiten Parameter im fromFXImage Aufruf übergeben. Dann hast Du ein BufferedImage one Alpha Kanal und kannst dieses dann als JPG speichern.

Aber wie gesagt: Noch reine Vermutung aber ich habe keine Zeit mehr es zu vertiefen.

Edit: Das fromFXImage kann alleine nicht das Problem sein, denn in meinem Test hatte ich ein Image geladen und da war noch TYPE_INT_RGB. Aber beim Scaling mit einem TYPE_INT_RGB BufferedImage und dann dem toFXImage / fromFXImage ist es kein TYPE_INT_RGB - da veränderte sich bei mir der Typ.
 
Zuletzt bearbeitet:

KonradN

Super-Moderator
Mitarbeiter
Jetzt konnte ich doch nicht abbrechen - es gab in der vorherigen Antwort ein Edit, denn mir war halt eingefallen, dass mein Verdacht nicht sein konnte. Und zuerst dachte ich, dass im Scaling ein falscher Typ beim BufferedImage angegeben worden wäre ... das war aber nicht der Fall.

Der mögliche Fix (Lösungsvorschlag, den ich schon gemacht habe) wäre damit etwas wie:
Java:
            BufferedImage newImage = new BufferedImage((int)bild.getWidth(), (int)bild.getHeight(), BufferedImage.TYPE_INT_RGB);
            BufferedImage bufferedImage = SwingFXUtils.fromFXImage(bild, newImage);
beim speichern des Bildes. Das hatte dann in meinen Tests funktioniert.
 

MiMa

Top Contributor
Vielen Dank, deine vermutung war richtig.
Ich habe die Zeile korrigiert
Java:
ImageIO.write(bufferedImage, "png", output);
und auch die Dateiendung beim speichern der Datei (png) angepasst.
Jetzt werden die beiden Bilddateien korrekt gespeichert.
Einmal das mit der Originalgrösse und das Skalierte.

Das mit dem jpg werde ich aber noch versuchen hin zu bekommen.
 

MiMa

Top Contributor
Ich habe jetzt die Speichern Methode umgeschrieben und jetzt funktioniert das speichern auch im jpg Format.

Java:
public static void speichernBildJPEG(Image bild, String dateiname) throws IOException {
        BufferedImage bufferedImageWithAlpha = SwingFXUtils.fromFXImage(bild, null);

        // BufferedImage ohne Alphakanal erstellen
        BufferedImage bufferedImageWithoutAlpha = new BufferedImage(bufferedImageWithAlpha.getWidth(),
                bufferedImageWithAlpha.getHeight(),
                BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = bufferedImageWithoutAlpha.createGraphics();
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g2d.drawImage(bufferedImageWithAlpha, 0, 0, null);
        g2d.dispose();

        // Als JPEG speichern
        File ausgabeDatei = new File(dateiname + ".jpg");
        ImageIO.write(bufferedImageWithoutAlpha, "jpg", ausgabeDatei);
    } // speichernBildJPEG

Vielen Dank für die Hilfe
 

KonradN

Super-Moderator
Mitarbeiter
Damit wird das Bild doppelt verarbeitet:
  • erst wird in dem fromFXImage Aufruf das Bild kopiert
  • dann kopierst Du es ein zweites Mal mit dem Graphics2D im draw aufruf.

In #6 hatte ich Dir aufgezeigt, wie Du es nur einmal verarbeitest: Erzeugung der gewünschten BufferedImage Instance und dann Aufruf von fromFXImage mit dieser Bitmap als Parameter. (Und falls Du viele Bilder verarbeiten solltest: Der Speicherverbrauch ist doppelt so hoch, da Du zwei BufferedImage Instanzen hast. in #6 habe ich zwar zwei Variablen, aber die BufferedImage Instanz ist die selbe).
 

MiMa

Top Contributor
Danke dir, hab es korrigiert und funktioniert gut.

Java:
public static void speichernBildJPG(Image bild, String dateiname) throws IOException {
        // Ein BufferedImage ohne Alphakanal direkt erstellen und mit FX Image rendern
        BufferedImage bildOhneAlpha = new BufferedImage((int) bild.getWidth(), (int) bild.getHeight(), BufferedImage.TYPE_INT_RGB);
        SwingFXUtils.fromFXImage(bild, bildOhneAlpha);

        // Als JPEG speichern
        File ausgabeDatei = new File(dateiname + ".jpg");
        ImageIO.write(bildOhneAlpha, "jpg", ausgabeDatei);
    } // speichernBildJPG
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
C Image laden und Speichern - Image wird auf JPanel nicht angezeigt AWT, Swing, JavaFX & SWT 4
P nicht sichtbares JPanel / JFrame als Image speichern AWT, Swing, JavaFX & SWT 3
T Image skaliert in Variable speichern AWT, Swing, JavaFX & SWT 6
G Swing Image speichern / 0 Byte AWT, Swing, JavaFX & SWT 7
L JPanel als Image speichern AWT, Swing, JavaFX & SWT 3
G Image Object speichern oder in ein BufferedImage umwandeln AWT, Swing, JavaFX & SWT 2
D JPanel als Image speichern? AWT, Swing, JavaFX & SWT 5
K Image aus einem JPanel ziehen und speichern AWT, Swing, JavaFX & SWT 2
J Eingaben aus Textfield & ComboBox speichern und in ComboBox wieder ausgeben AWT, Swing, JavaFX & SWT 3
officialmaxl JavaFX Textfield getTextfield() in String speichern AWT, Swing, JavaFX & SWT 1
missy72 JavaFX ObservableList in einer ArrayList speichern. AWT, Swing, JavaFX & SWT 7
B Swing Sudoku: Laden / Speichern von Zahlen aus/in mehrere JTextFields aus/in eine(r) Textdatei AWT, Swing, JavaFX & SWT 9
J Warum kann ich die Spaltennummer in der Konsole anzeigen, diese aber nicht speichern ? AWT, Swing, JavaFX & SWT 6
F Output Stream / File Dateien / Speichern AWT, Swing, JavaFX & SWT 13
D String als Textdatei in ausgewähltem Speicherplatz speichern AWT, Swing, JavaFX & SWT 32
A Swing Datei lässt sich zwar speichern, aber nicht laden (Inhalt im JTextField anzeigen) AWT, Swing, JavaFX & SWT 18
S URLS speichern von Internetseiten AWT, Swing, JavaFX & SWT 3
S Bild neu skalieren - Bild in Bild speichern? AWT, Swing, JavaFX & SWT 6
P Adressbuch Werte speichern AWT, Swing, JavaFX & SWT 21
G Eingabe in JTextField in Array speichern und in JList ausgeben AWT, Swing, JavaFX & SWT 7
G JTextField Eingabe in DB speichern AWT, Swing, JavaFX & SWT 68
B TableView als PDF speichern AWT, Swing, JavaFX & SWT 8
cool_brivk24 libGDX Welt speichern AWT, Swing, JavaFX & SWT 0
R Scene speichern AWT, Swing, JavaFX & SWT 7
D Inhalt von JTextField in MySQL speichern. Wie ? AWT, Swing, JavaFX & SWT 1
J Text in ein Textfeld eingeben und speichern AWT, Swing, JavaFX & SWT 27
S Swing jScrollPane - pro Eintrag der Liste, die jCheckBoxes Speichern die in dem Eintrag aktiviert wurden AWT, Swing, JavaFX & SWT 2
A Swing Wie Daten in der Form speichern? Array oder ArrayList AWT, Swing, JavaFX & SWT 2
I JavaFX formatierter Text in PDF speichern AWT, Swing, JavaFX & SWT 4
GenerationLost JavaFX FileChooser speichern ohne Zieldatei? AWT, Swing, JavaFX & SWT 12
A Swing Gemaltes Bild über saveDialog speichern unter AWT, Swing, JavaFX & SWT 15
S AWT Daten über TextField und Button in array speichern AWT, Swing, JavaFX & SWT 5
U Eingabe von TextField in variable speichern AWT, Swing, JavaFX & SWT 2
M Kamerabilder in ein Ordner speichern AWT, Swing, JavaFX & SWT 12
F Gezeichnetes als bild speichern AWT, Swing, JavaFX & SWT 4
I JavaFX Speichern der eingefügten Einträge beim Neustart des Programms AWT, Swing, JavaFX & SWT 2
I Variabeln speichern in Desktop Anwendung AWT, Swing, JavaFX & SWT 2
N Swing Benötige Hilfe um ein Swing Canvas zu speichern AWT, Swing, JavaFX & SWT 4
D Objekte einer Oberfläche in eine Datei/Ordner speichern AWT, Swing, JavaFX & SWT 9
S JavaFX Fenstergrösse automatisch Speichern und Laden AWT, Swing, JavaFX & SWT 4
J Swing Fenstereinstellungen speichern AWT, Swing, JavaFX & SWT 2
M Combo Box auswahl in eine Datenbank speichern AWT, Swing, JavaFX & SWT 1
M ausgewählte Inhalt von ListItem inn ComboBox in der Tabelle speichern AWT, Swing, JavaFX & SWT 0
M Bild Beschreibung mit ImageIO speichern AWT, Swing, JavaFX & SWT 1
J Swing JTable speichern AWT, Swing, JavaFX & SWT 2
C GUI öfters durchlaufen und hinterher Bild speichern AWT, Swing, JavaFX & SWT 1
S Panelzeichnung speichern AWT, Swing, JavaFX & SWT 2
O JTextfield und JComboBox Wert in SQL Database speichern AWT, Swing, JavaFX & SWT 4
J Bilder als Variable an einem Objekt speichern AWT, Swing, JavaFX & SWT 3
M Bild aus JLabel resizen und speichern AWT, Swing, JavaFX & SWT 0
A Swing Malprogramm Bild speichern? AWT, Swing, JavaFX & SWT 9
G Subimage von BufferedImage speichern AWT, Swing, JavaFX & SWT 4
Y JavaFX Bild speichern und Pfad dazu abspeichern AWT, Swing, JavaFX & SWT 2
D JPanel Graphic2D als BufferedImage Speichern AWT, Swing, JavaFX & SWT 5
A JFileChooser Datei speichern AWT, Swing, JavaFX & SWT 4
B Bildverlust bei Speichern in .jar-Archiv AWT, Swing, JavaFX & SWT 3
J 2D-Grafik Bildteile in ein anderes Bild speichern AWT, Swing, JavaFX & SWT 12
B Datenübergabe zwischen Tabs und Daten speichern AWT, Swing, JavaFX & SWT 2
J JFileChooser - Datei speichern AWT, Swing, JavaFX & SWT 7
J JTree speichern AWT, Swing, JavaFX & SWT 4
kodela Teil eines Panels als Graphik speichern AWT, Swing, JavaFX & SWT 3
T Modell als XML Speichern / Laden AWT, Swing, JavaFX & SWT 9
P TextField beim klicken von JButton speichern AWT, Swing, JavaFX & SWT 17
P Öffnen, Speichern von Dat. über DialogBoxen AWT, Swing, JavaFX & SWT 10
B Zustand eines GUI speichern AWT, Swing, JavaFX & SWT 8
I Dialog zum Speichern? AWT, Swing, JavaFX & SWT 16
M JTable Drucken NullpointerException +JTable speichern AWT, Swing, JavaFX & SWT 6
J Swing JTable-Daten Speichern und bei zeilen-änderung beibehalten. AWT, Swing, JavaFX & SWT 6
M Datei Speichern unter Dialog - SWT AWT, Swing, JavaFX & SWT 3
T SWT:Datei speichern / öffnen AWT, Swing, JavaFX & SWT 6
T speichern funktioniert,aber öffnen nicht AWT, Swing, JavaFX & SWT 2
W Grafik von JFrame korrekt speichern AWT, Swing, JavaFX & SWT 7
M Position eines JLabels speichern? AWT, Swing, JavaFX & SWT 3
A BufferedImage nach dem Speichern immer schwarz AWT, Swing, JavaFX & SWT 8
J Speichern, Event, Hintergrund getAppletContext AWT, Swing, JavaFX & SWT 2
S JTable - Sortierung beibhalten / Speichern. AWT, Swing, JavaFX & SWT 3
C Checkbox-zustände in einem JFrame speichern AWT, Swing, JavaFX & SWT 8
R Graphics-Object speichern AWT, Swing, JavaFX & SWT 4
B Panel als Bild speichern AWT, Swing, JavaFX & SWT 11
Daniel_L Grafik erstellen, drin zeichnen und dann speichern AWT, Swing, JavaFX & SWT 2
K Swing Komponente als Bild speichern AWT, Swing, JavaFX & SWT 11
E Profilsichten speichern und dynamsich erzeugen?! AWT, Swing, JavaFX & SWT 2
N JTable direkt editierenund in Datenbanken speichern AWT, Swing, JavaFX & SWT 5
D Swing JTable in Datei speichern und laden AWT, Swing, JavaFX & SWT 3
R JComboBox Ausgabe in String speichern AWT, Swing, JavaFX & SWT 3
F Wert zu Eintrag in ComboBox speichern?! AWT, Swing, JavaFX & SWT 7
0 Ausschnitt eines JPanels als Bild speichern AWT, Swing, JavaFX & SWT 4
A Programmieren einer Agenda mit einer Liste (als Applet und .txt zum Speichern) AWT, Swing, JavaFX & SWT 7
B JTextPane formatierten Inhalt speichern AWT, Swing, JavaFX & SWT 2
R TextField auslesen & in Objekteigenschaften speichern AWT, Swing, JavaFX & SWT 22
B textdatei speichern AWT, Swing, JavaFX & SWT 9
K Swing JFileChooser zum Speichern - FileFilter AWT, Swing, JavaFX & SWT 2
jgh Speichern von User-GUI-Einstellungen AWT, Swing, JavaFX & SWT 2
B Swing Suche JFileChooser zum Speichern AWT, Swing, JavaFX & SWT 2
N gezeichnete Graphiken speichern und wieder anzeigen AWT, Swing, JavaFX & SWT 8
M AWT Datei auf server speichern und beschreiben AWT, Swing, JavaFX & SWT 7
U Wo eingeloggten Benutzer "speichern" AWT, Swing, JavaFX & SWT 10
J Aus einer JList den Inhalt als Textdatei speichern AWT, Swing, JavaFX & SWT 15
C Bild in einer Datenbank speichern? AWT, Swing, JavaFX & SWT 7
Z JTable: Speichern probleme AWT, Swing, JavaFX & SWT 12

Ähnliche Java Themen

Neue Themen


Oben