Laden...

"Allgemeiner Fehler in der GDI+" beim Speichern eines Bildes [==> weil der Stream geschlossen wurde]

Letzter Beitrag vor 5 Jahren 19 Posts 9.599 Views
"Allgemeiner Fehler in der GDI+" beim Speichern eines Bildes [==> weil der Stream geschlossen wurde]

Hallo zusammen.

Ich stoße hier nun schon seit einiger Zeit an diesen Fehler.
Ich weiß nicht, ob ich vor lauter Bäumen den Wald nicht mehr sehe, ob an mein Code irgendwas falsch ist oder ich vielleicht ein falschen Weg eingeschlagen habe um die Bilder zu Speichern/Öffnen.

Grundlegende Information:
Das Programm Speichert Persönliche daten und ich lass mir eine Vorschau anzeigen, wie die Daten gespeichert werden. (ohne Probleme) Wenn ich mir allerdings die daten wieder anzeigen lassen will um sie zu bearbeiten und dann erneut abzuspeichern erhalte ich den fehler > Fehlermeldung:

Allgemeiner Fehler in der GDI+

Das Bild wird im Hauptform geöffnet


 private void btnUpload_Click(object sender, EventArgs e)
        {

            OpenFileDialog op = new OpenFileDialog();
            op.Title = "Bitte wählen Sie ihr Bild aus";
            op.Multiselect = false;
            op.Filter = "Alle Bilder|*.png;*.bmp;*.jpg;*.gif|PNG-Bilder|*.png|BMP-Bilder|*.bmp|JPG-Bilder|*.jpg|GIF-Bilder|*.gif";
            op.FilterIndex = 1;
            DialogResult DR = op.ShowDialog();

            if(DR == DialogResult.OK)
            {

                tBild = Image.FromFile(op.FileName);
                this.pbUpload.Image = tBild;
                this.pbUpload.SizeMode = PictureBoxSizeMode.StretchImage;

            }
            else
            {
             
                tBild = this.pbUpload.Image;

            }
        
        }

& an 2 Klassen weiter gegeben. Einmal an die Klasse zum Speichern


sPath = "C:\\Cyber-Enterprise\\Aufnahmestelle" + "\\Datenspeicher\\";
            if(Directory.Exists(sPath) == false)
            {

                Directory.CreateDirectory(sPath);

            }

            varSpeichern();
            Daten d = new Daten(tName, tAlter, tFarbe, tHaltung, tRasse, tBild, vName, vStrasse, vWohnort, vEmail, Vermittelt, vNummer, vVermitteltAm);

            if(d.SpeicherDaten(sPath))
            {

                MessageBox.Show(tName + " wurde Erfolgreich gespeichert", "Speichern", MessageBoxButtons.OK, MessageBoxIcon.Information);
                allesLoeschen();

            }

und ein zweites mal an die klasse Vorschau


varSpeichern();

            Preview p = new Preview(tName, tAlter, tRasse, tFarbe, tHaltung, tGeschlecht, tKastriert, tImpfung, tBild, vName, vStrasse, vWohnort, vEmail, vNummer, vVermitteltAm, Vermittelt);
            p.showPreivew();

In der Klasse zum Speichern habe ich auch 2 Funktion um das Bild in ein String & umgekehrt zu wandeln


        private string ImageZuString(Image img, ImageFormat imgFormat)
        {

            string sImg;

            MemoryStream MS = new MemoryStream();            

            img.Save(MS, imgFormat); // Hier tritt der Fehler auf

            sImg = Convert.ToBase64String(MS.ToArray());
            MS.Close();

            return sImg;

        }

        public static Image StringZuImage(string sImage)
        {

            MemoryStream MS = new MemoryStream(Convert.FromBase64String(sImage));
            Image img = Image.FromStream(MS);
            MS.Close();

            return img;

        }

Wie oben beschrieben, wenn ich nun ein Kontakt erneut öffne, die daten ändere & speichern will erhalte ich den allgemeinen Fehler in der GDI.
Außer, ich lade das Bild beim Bearbeiten erneut hoch (was natürlich sehr unangebracht ist, falls man mal nicht daran denkt, das Bild erneut mit hochzuladen)

jemand villeicht ein Dnek anstoß?

PS: Ich habe auch versucht, dass Bild vorm abspeichern intern nochmal zu Kopieren, hat mir allerdings nicht viel gebracht oder ich habs an der Falschen stelle Kopiert.

Für denkanstöße wäre ich sehr dankbar. 😃

du darfst den MemoryStream des Bildes nicht schließen,
durch das du das Image erstellt hast.

Ich hab mir jetzt nur den Teil angeschaut wo das Bild gespeichert wird und der ist meiner Sicht okay. Am wahrscheinlichsten ist das dass gewünschte Image Format nicht unterstützt wird bzw. nicht aus dem Source Format konvertierbar ist. (Das GDI+ ist leider nicht sehr genau wenn es um Fehlerbeschreibungen geht)

Spyke: Den MemoryStream nicht schließen?? Würde es dadurch nicht erst recht probleme geben da der MemoryStream sonst dauerhaft durchlaufen würde?

Sebastian: hmmm.. ok und was kann ich dagegen tun? Und wenn das image format nicht unterstützen würde würde es mir die bilder doch erst garnicht anzeigen\speichern?
Das problem ist halt wirklich nur beim öffnen und erneuten speichern des bildes.

Habe auch versucht vor dem speichern zu sagen, dass das bild = das aus dem picterbox ist aber das hat leider auch nichts gebracht 😦

Hallo Gh0st21,

der Stream muss offen bleiben, so steht es auch in der MSDN Doku:

Der Stream muss für die Lebensdauer der Image geöffnet bleiben.

Ist immer gut, wenn man mal in die Doku schaut, besonders wenn irgendwas nicht funktioniert.

herbivore

@herbivore

img.Save(MS, imgFormat); // Hier tritt der Fehler auf

Mag sein das er danach noch was falsch macht, das Problem zeigt sich aber Im Moment davor.

Sebastian bin mir zu 99,9 % sicher das das problem ist weil der Stream geschlossen wurde.
Selbst kopieren/klonen des Image Objektes bringt da nixs.

Wie herbivore richtig hervorhob, der Stream darf nicht vorher entsorgt werden solange das Image objekt noch benötigt wird.

Hallo Sebastian.Lange,

ich hatte gesehen, wo der Fehler auftritt, aber wenn der Stream geschlossen ist, kann es potenziell bei jeder Operation knallen, denn man weiß ja nicht, wann GDI versucht auf den (geschlossenen) Stream zuzugreifen.

Beim Speichern werden alle Pixeldaten benötigt. Das ist durchaus ein Augenblick, bei dem es wahrscheinlich ist, dass (erneut) aus dem Input-Stream gelesen werden muss. Entsprechend kann nach dem Laden geschlossene Stream durchaus die Ursache für das Problem beim Speichern sein.

Auf jeden Fall sollte Gh0st21 seinen Code zu umstellen, dass der Stream offen bleibt. Zum einen ist das sowieso richtig(er) und sicherer. Und wenn dadurch der Fehler behoben ist, brauchen wir nicht weiter spekulieren.

herbivore

Ja sowieso und überhaupt richtiger, war aber alles nicht Antwort auf die Frage und löst nicht das Problem in dieser Codezeile. Du versuchst ein einzelnes technisches Problem mit einem grundlegenden Prinzip zu beantworten, was dem Fragesteller mit Sicherheit nicht hilft. (wenn alle die doku lesen und verstehen brauchst es auch kein mycsharp.de mehr) Die Frage ist warum wirft die Image.Save Methode eine Exception? Darauf mit irgendwelchen Hinweisen bzg. des Streams zu antworten würde mir nur einfallen wenn ich dem Fragesteller schlichtweg nicht glaube und meine es besser zu wissen.

Sebastian, aus meiner Sicht und Erfahrung ist der geschlossene Stream das Problem und die Antwort auf die Frage.

Alles weitere sind nur Vermutungen, solange sich der Fragesteller nicht weiter äußerst und das Stream problem nicht beseitigt hat.

Hallo Sebastian.Lange,

du irrst. Damit wir nicht weiter spekulieren müssen, habe ich es ausprobiert. Wenn man das folgende Testprogramm startet (und es im Arbeitsverzeichnis eine Bitmap x.bmp gibt), bekommt man genau den beschrieben Fehler und zwar beim Aufruf von Save:

Fehlermeldung:
Ausnahmefehler: System.Runtime.InteropServices.ExternalException: Allgemeiner Fehler in GDI+.
bei System.Drawing.Image.Save(Stream stream, ImageCodecInfo encoder, EncoderParameters encoderParams)
bei App.Main() in tmp.cs:Zeile 15.

Löscht man die Zeile fs.Close(); oder kommentiert sie aus, verschwindet der Fehler.

Es ist also so, wie Spyke und ich von Anfang an gesagt haben.

using System;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;

static class App
{
   public static void Main ()
   {
      FileStream fs = new FileStream ("x.bmp", FileMode.Open);
      Image img = Image.FromStream(fs);
      fs.Close();

      MemoryStream ms = new MemoryStream();
      img.Save(ms, ImageFormat.Bmp);
      ms.Close ();
   }
}

herbivore

Hallo zusammen,
kann mir jemand weiterhelfen? Ich habe eigentlich den identischen Code wie oben beschrieben und auch das identische Fehlerbild. Leider hilft es auch nichts den MemoryStream offen zu halten. Also wenn ich die Zeile MS.Close() auskommentiere tritt der Fehler immernoch auf.

Wäre dankbar für eure Hilfe 🙂

Liebe Grüße Tony

Hallo theSoulT,

ich habs nicht noch mal probiert, aber laut Text verschwindet der Fehler, wenn man **fs**.Close() entfernt, nicht **ms**.Close ().

herbivore

Servus herbivore,

nur nutzen leider weder der threadersteller noch ich fs.Close().
Also wir haben das beide nicht in unserem Code 😄

Dann eröffne bitte gemäß [Hinweis] Wie poste ich richtig? ein eigenes Thema.
Keiner hier kann hellsehen, wie Dein Code aussieht. 😉

PS: Du schreibst, dass Du den identischen Code hättest, der dann doch anders aussieht. 🤔

nur nutzen leider weder der threadersteller noch ich fs.Close().

und herbivore hat die Lösung gepostet, wieso das aber wichtig ist.
Es würde daher sinn machen, wenn Du die Hilfestellungen durchlesen und befolgen würdest 👍

aber meiner sieht identisch aus 😃
Er hat kein fs.close() und ich auch nicht 😛

Er hat kein fs.close() und ich auch nicht 😛

Und genau das hat herbivore (vor rund 4 Jahren) beantwortet.

Les diese Antwort mit der Lösung von herbivore durch (und befolge sie).
Wenn Du die bereits hier genannte Lösung nicht befolgen magst, dann weiß ich auch nicht, wie man Dir da noch helfen kann.

Löscht man die Zeile fs.Close(); oder kommentiert sie aus, verschwindet der Fehler.

herbivore

Das Problem sit, das ich dieseLÖsung nicht nutzen kann, weilin dem Code kein fs.close() vorhanden ist 😦
Aber ich werde nochmal ein neues thema mit meinem code eröffnen. Vllt reden wir ja auch aneinander vorbei 😃

Aber ich werde nochmal ein neues thema mit meinem code eröffnen.

siehe Allgemeiner Fehler in der GDI+