Laden...

Fehler beim Speichern eines Bildes nach Rotieren

Erstellt von interzone vor 17 Jahren Letzter Beitrag vor 17 Jahren 21.789 Views
i
interzone Themenstarter:in
95 Beiträge seit 2005
vor 17 Jahren
Fehler beim Speichern eines Bildes nach Rotieren

hallo allerseits!

habe absolut keinen plan warum folgender code eine exception wirft:


Image RotateImg = Image.FromFile(File);
RotateImg.RotateFlip(System.Drawing.RotateFlipType.Rotate90FlipNone);
RotateImg.Save(File);

Eine nicht behandelte Ausnahme des Typs 'System.Runtime.InteropServices.ExternalException' ist in system.drawing.dll aufgetreten.

Zusätzliche Informationen: In GDI+ ist ein allgemeiner Fehler aufgetreten.

wenn ich die datei 'File' umbenenne funktionierts... 😭

danke im vorraus...

1.271 Beiträge seit 2005
vor 17 Jahren

Das wirkt so als würde das Bild nicht gefunden werden. Was meinst du mit "File umbenennen"? Anderen Pfad angeben?

A wise man can learn more from a foolish question than a fool can learn from a wise answer!
Bruce Lee

Populanten von Domizilen mit fragiler, transparenter Außenstruktur sollten sich von der Translation von gegen Deformierung resistenter Materie distanzieren!
Wer im Glashaus sitzt, sollte nicht mit Steinen werfen.

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo interzone,

ich denke, die Bild-Datei ist einfach noch zum Lesen offen und kann deshalb nicht geschrieben werden.

Da hilft nur die Datei selbst einlesen (und schließen), z.B. in einen MemoryStream und aus dem MemoryStream das Images erzeugen und rotieren. Dann sollte das Speichern klappen.

herbivore

i
interzone Themenstarter:in
95 Beiträge seit 2005
vor 17 Jahren

ich hab mir auch schon gedacht, dass das ganze zu rasch runter läuft. die datei gibts sicher - er schmiert erst beim .save ab...

werds mal mit dem memorystream probieren...

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo interzone,

das ist keine Frage von zu rasch, sondern die Datei bei Image.FromFile solange geöffnet bleibt, bis Image.Dispose aufgerufen wird.

herbivore

i
interzone Themenstarter:in
95 Beiträge seit 2005
vor 17 Jahren

er will auch so nicht:


FileStream fs = File.OpenRead(file);
byte[] data = new byte[fs.Length];
Common.ReadWholeArray(fs, data);
fs.Close();
				
Stream tmpStream = new MemoryStream(data);

Image RotateImg = Image.FromStream(tmpStream);			RotateImg.RotateFlip(System.Drawing.RotateFlipType.Rotate90FlipNone);
RotateImg.Save(file);

bild wird korrekt eingelesen und gedreht. beim speichern murrt er wieder herum...

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo interzone,

zum Zeitpunkt des Speicherns ist mit deinem Code sichergestellt, dass die Datei bereits geschlossen ist. Daher muss der allgemeiner GDI+-Fehler wohl doch eine andere Ursache haben. Leider weiß ich nicht welche. Sorry!

herbivore

i
interzone Themenstarter:in
95 Beiträge seit 2005
vor 17 Jahren

hab grade einen haltepunkt gesetzt bei der save methode und dann mal kurz die eben geöffnete datei probiert zu bearbeiten/löschen - siehe da auch der explorer meldet, dass er auf die datei nicht zugreifen darf.

es dürfte also noch zugriff auf die datei geben...

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo interzone,

öffnest du die Datei in dem Programm noch an anderer Stelle? Ist vielleicht noch irgendwo ein Image.FromFile übrig geblieben?

Wenn das nicht hilft, dann guck doch mal mit dem ProcessExplorer von Sysinternals wer zugreift.

herbivore

i
interzone Themenstarter:in
95 Beiträge seit 2005
vor 17 Jahren

habe auch grade probiert das fertige bild auf den memorystream zu speichern nach dem rotieren - es kommt diesselbe fehlermeldung... 😭

edit: so hab jetzt nochmal herumgespielt und lass mein programm ein paar andere dinge bearbeiten bevor save() kommt - jetzt bekomm ich zirka jeden 2ten versuch das bild gespeichert...

4.221 Beiträge seit 2005
vor 17 Jahren

Eigentlich ist die Lösung ganz simpel



			/*using System.IO;
			using System.Drawing.Imaging;*/

			string file=@"C:\Bilder\Test.bmp";

			//File laden
			using(Image rotateImg=Image.FromFile(file))
			{
				//Image-Format zwischenspeichern
				ImageFormat format=rotateImg.RawFormat;
				//denn beim RotateFlip ist das ImageFormat weg
				rotateImg.RotateFlip(System.Drawing.RotateFlipType.Rotate90FlipNone);
				//Save mit dem ursprünglichen ImageFormat
				rotateImg.Save(file,format);
			}


Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

i
interzone Themenstarter:in
95 Beiträge seit 2005
vor 17 Jahren

funktioniert nicht. bringt mich wieder an meinen anfangspunkt...

4.221 Beiträge seit 2005
vor 17 Jahren

Original von interzone
funktioniert nicht. bringt mich wieder an meinen anfangspunkt...

Bei mir funzt das ....

Kannst Du das Bild überhaupt mit irgendwas öffnen (oder ist es bei einem früheren Testlauf zerstört worden ?)

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

i
interzone Themenstarter:in
95 Beiträge seit 2005
vor 17 Jahren

jep eigentlich schon. ich hab das ganze als eine art fileexplorer aufgebaut, wähle das bild aus und es erscheint in einer vorschauansicht. darunter sind die symbole für links/rechtsrotation. ausgeführt wird momentan also nur dein code (lesezugriff mit allen programmen möglich, schreiben gesperrt) und das bild ist schon in der picturebox für die vorschau geladen...

4.221 Beiträge seit 2005
vor 17 Jahren

Mach mal ein leeres Projekt

Einen Button... Code reinpasten ... Testen !

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

i
interzone Themenstarter:in
95 Beiträge seit 2005
vor 17 Jahren

werkt brav... ich probier mal disposen des images aus der vorschau picturebox...

edit: ich habs! GC.Collect() reingeschmissen und es funktioniert brav...

danke für eure hilfe!

4.221 Beiträge seit 2005
vor 17 Jahren

GC.Collect ist meist eine schlechte Idee 🙂

Und in diesem Fall total unnötig....

Ich habe das Sample noch ein wenig angepasst, so dass das Image immer angezeigt wird.



			/*using System.IO;
			using System.Drawing.Imaging;*/

			string file=@"C:\Bilder\Test.bmp";

			//Cleanup aus Vorlauf
			if (this.pictureBox1.Image!=null)
			{
				this.pictureBox1.Image.Dispose();
				this.pictureBox1.Image=null;
			}
			//File laden (ohne using ... da das Image nach dem Durchlauf ja immer noch angezeigt wird.
			Image rotateImg=Image.FromFile(file);
			//File anzeigen
			this.pictureBox1.Image=rotateImg;
			//Image-Format zwischenspeichern
			ImageFormat format=rotateImg.RawFormat;
			//denn beim RotateFlip ist das ImageFormat weg
			rotateImg.RotateFlip(System.Drawing.RotateFlipType.Rotate90FlipNone);
			//Save mit dem ursprünglichen ImageFormat
			rotateImg.Save(file,format);

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo interzone,

GC.Collect ist meist eine schlechte Idee 🙂

Zustimmung!

Wenn es mit CG.Collect klappt, liegt das vermutlich daran, dass für ein Bild, auf das schon keine Referenz mehr besteht, vergessen wurde Dispose aufzurufen.


img = Image.FromFile(file);
//...
// hier fehlt Dispose
img = null;
GC.Collect (); // <= holt als Nebeneffekt das Dispose nach

Natürlich kann das in deinem Programm versteckter sein. Außerdem kann eine Referenz nicht nur durch Nullsetzen verloren gehen, sondern es gehen z.B. auch alle Referenzen in lokalen Variablen verloren, wenn der Block, in dem sie deklariert sind, verlassen wird.

herbivore

i
interzone Themenstarter:in
95 Beiträge seit 2005
vor 17 Jahren

ich glaub ich habs jetzt endgültig gelöst - und das ohne gc.collect()... 8)

wenn ich einen filename gewählt hab möcht ich nämlich das vorschaubild anzeigen - dieses wird von meinem programm geladen und bearbeitet und dann erst in die picturebox geschrieben. da das ganze in einer anderen methode war hab ich mir gedacht, dass kanns nicht sein, dass hier das file noch offen bleibt, das geht automatisch zu - die ganze methode ist nämlich schon längst fertig bevor die rotationsroutine ins spiel kommt...

4.221 Beiträge seit 2005
vor 17 Jahren

Nur so als Tipp für die Fehlersuche.... Wenn man den Grund für einen Fehler nicht findet... explizit nur diese Funktion in einem neuen Projekt testen.... oder das Projekt zurückbauen bis es wieder läuft.

Nur so können Seiteneffekte ausgschlossen werden.

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

6.862 Beiträge seit 2003
vor 17 Jahren

Naja, bevorzuge lieber NUnit, sind schnell geschrieben solche Tests und du hast auch keine Seiteneffekte da nur der Testcode ausgeführt wird.

Baka wa shinanakya naoranai.

Mein XING Profil.

v
24 Beiträge seit 2006
vor 17 Jahren

hi interzone, das selbe problem habe ich auch!

aber ich glaub ich weiß was es hat, der fehler kommt weil die datei mit dem gleichen namen bereits existiert, du musst also vorher prüfen obs die datei schon gibt, wenn ja => fragst den user ob er die datei umbenennen will

"Round Round Robin"

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo violeta,

der fehler kommt weil die datei mit dem gleichen namen bereits existiert

nein, das ist nicht der Grund. Der Grund war, dass die Datei schon geöffnet war. Und solange die Datei geöffnet ist, könnte sie auch gar nicht umbenannt werden.

herbivore

v
24 Beiträge seit 2006
vor 17 Jahren

muss ich jetzt die datei vorher schließen oder was?

"Round Round Robin"

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo violeta,

ja, wobei die Datei eben auch durch ein Image.FromFile geöffnet wird und bis zum Image.Dispose geöffnet bleibt. Aber das ist ja gerade das Thema des Threads. Am besten nochmal lesen.

herbivore

v
24 Beiträge seit 2006
vor 17 Jahren

hi, okay das mit dem speichern funktioniert jetzt einwandfrei, danke!!!

so jetzt hab ich mir gedacht ich bau einen savefiledialog ein, ich hab hier ein neues projekt gemacht, da mein eigentliches schon viel zu groß und unübersichtlich ist:


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace SaveTest
{
    public partial class Form1 : Form
    {
        FileInfo fi;

        public Form1()
        {
            InitializeComponent();
        }

        //neues bild auswählen-button
        private void button1_Click(object sender, EventArgs e)
        {
            this.openFileDialog1.ShowDialog();
        }

        private void openFileDialog1_FileOk(object sender, CancelEventArgs e)
        {
            fi = new FileInfo(openFileDialog1.FileName);
            this.pictureBox1.Image=Image.FromFile(fi.Name);
        }

        //rotiere button
        private void button3_Click(object sender, EventArgs e)
        {
            Image img = this.pictureBox1.Image;
            img.RotateFlip(RotateFlipType.Rotate90FlipNone);
            this.pictureBox1.Image = img;  
        }

        //save button
        private void button2_Click(object sender, EventArgs e)
        {
            this.saveFileDialog1.ShowDialog();
            this.saveFileDialog1.FileName = fi.Name;
        }

        private void saveFileDialog1_FileOk(object sender, CancelEventArgs e)
        {
            this.pictureBox1.Image.Save(this.saveFileDialog1.FileName);
        }
    }
}

Aber ich komm nicht drauf wie ich den Namen und den Typ der Datei im SaveFileDialog festlegen kann, ich hab jetzt glaub ich jede methode des savefiledialogs durchkämmt und komm nicht drauf.

"Round Round Robin"

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo violeta,

FileDialog.FileName und FileDialog.Filter. Codebeispiele in der SDK-Doku.

herbivore

v
24 Beiträge seit 2006
vor 17 Jahren

hi,
also das mit FileName hatte ich eh schon probiert, siehst eh im code, aber die textbox im saveFileDialog bleibt trozdem leer 🙁

http://forum.fachinformatiker.de/archive/index.php/t-86285.html

dem nach kann man es nicht ändern

"Round Round Robin"

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo violeta,

in dem Codebeispiel in der SDK-Doku auf der Seite 'FileDialog.FileName Property' wird FileDialog.FileName auf 'myText' gesetzt und diese auch in dem erscheinenden Dialog angezeigt.

herbivore

v
24 Beiträge seit 2006
vor 17 Jahren

"Round Round Robin"

v
24 Beiträge seit 2006
vor 17 Jahren

oh jetzt hab ich meinen fehler gefunden! 8o

ich hab immer das showDialog vorher gemacht:


this.saveFileDialog1.ShowDialog();
saveFileDialog1.FileName = "myText";
saveFileDialog1.DefaultExt = "txt";
saveFileDialog1.Filter = "Text files (*.txt)|*.txt";
saveFileDialog1.InitialDirectory = "c:\\";

richtig gehörts so dann:


saveFileDialog1.FileName = "myText";
saveFileDialog1.DefaultExt = "txt";
saveFileDialog1.Filter = "Text files (*.txt)|*.txt";
saveFileDialog1.InitialDirectory = "c:\\";
this.saveFileDialog1.ShowDialog();

wiederum danke herbivore!

"Round Round Robin"

v
24 Beiträge seit 2006
vor 17 Jahren
weitere fehlermeldung....

hi

Bwa, jetzt hab ich schon wieder so einen Error!
Also wenn ich ein Bild verändere und überschreiben will, dann kommt diese Exception:

ArgumentException
Parameter is not valid.

bei: i.Save(fileInfoName,imgf);

ich hab schon vieles probiert, ich hab mir dacht es hilft vielleicht wenn ich das file ganz lösche aber trozdem funkts nicht!

Ihr könnt es ja mal sehen:


private void saveFileDialog1_FileOk(object sender, CancelEventArgs e)
        {
            try
            {
                this.pictureBox1.Image.Save(this.saveFileDialog1.FileName);
            }
            catch (Exception)   //Abfangen wenn name bereits vorhanden
            {
                Image i = this.pictureBox1.Image;
                imgf = i.RawFormat;
                this.pictureBox1.Image.Dispose();
                fileInfoName = fi.Name;                  //fi => FileInfo (Instanzvariable)
                fi.Delete();
                i.Save(fileInfoName,imgf);
                this.pictureBox1.Image = i;
            }
        }

Warum darf ich nicht das Bild speichern?

"Round Round Robin"

4.221 Beiträge seit 2005
vor 17 Jahren

Statt this.pictureBox1.Image.Dispose(); machst Du nur this.pictureBox1.Image=null;.... denn sonst ist das Image tot und es kracht.

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

v
24 Beiträge seit 2006
vor 17 Jahren

dann hab ich wieder das problem, dass das image von einem andere prozess verwendet wird und mich wirfts dann bei fi.delete();

"Round Round Robin"

v
24 Beiträge seit 2006
vor 17 Jahren
  1. ich glaub jetzt gehts 8) danke für die hilfe, obwohl ich mir nicht sicher bin warum es geht 👍

namespace SaveTest
{
    public partial class Form1 : Form
    {
        FileInfo fi;
        string fileInfoPath;

        public Form1()
        {
            InitializeComponent();
        }

        //neues bild auswählen-button
        private void button1_Click(object sender, EventArgs e)
        {
            this.openFileDialog1.ShowDialog();
        }

        private void openFileDialog1_FileOk(object sender, CancelEventArgs e)
        {
            fi = new FileInfo(openFileDialog1.FileName);
            this.pictureBox1.Image=Image.FromFile(fi.Name);
            Image img = this.pictureBox1.Image;
        }

        //rotiere button
        private void button3_Click(object sender, EventArgs e)
        {

            Image img = this.pictureBox1.Image;
            img.RotateFlip(RotateFlipType.Rotate90FlipNone);
            this.pictureBox1.Image = img;  
        }

        //save button
        private void button2_Click(object sender, EventArgs e)
        {    
            saveFileDialog1.FileName = fi.Name;
            saveFileDialog1.DefaultExt = fi.Extension;
            this.saveFileDialog1.ShowDialog();
            
        }

        private void saveFileDialog1_FileOk(object sender, CancelEventArgs e)
        {
            try
            {
                Image i = this.pictureBox1.Image;    //das musste ich ändern
                i.Save(this.saveFileDialog1.FileName);
            }
            catch (Exception)
            {
                Image i = this.pictureBox1.Image;
                this.pictureBox1.Image.Dispose();
                //this.pictureBox1.Image = null;  geht auch
                fileInfoPath = fi.Name;
                fi.Delete();
                i.Save(fileInfoPath);
                this.pictureBox1.Image = i;
            }
        }
    }
}

**
try
{
Image i = this.pictureBox1.Image; //das musste ich ändern
i.Save(this.saveFileDialog1.FileName);
}

habs einfach ausprobiert und siehe da, es funkt!**

"Round Round Robin"

s
11 Beiträge seit 2006
vor 17 Jahren

Ich habe ein recht ähnliches Problem, finde hier aber nicht die Lösung...

Ich habe auch eine picturebox, die ein bild beinhaltet. Das bild wird bearbeitet. Beim click auf den save-button krieg ich dann in einem Dialog sfd den Ziel-Filename, der eben auch exakt das Ursprungsbild sein kann. das Problem ist wiederum die Picturebox.

Nach dem Speichern soll das Bild in der immer noch veränderten Form da sein. Aber bei allem was ich probiert habe kriege ich immer noch die GDI+ Exception beim Save.

Bei einem anderen Teil des programms, wo mehrere bilder bearbeitet und gespeichert werden, aber auch ein Bild in der Picturebox ist, werden alle bearbeitet ausser das aus der picturebox. Wenn ich interessanterweise das bild vor der massenbearbeitung sinnlos um 180° drehe und wieder zurück (oder ähnliche nichtsmachende bearbeitungen), dann geht es interessanterweise.

Aber auch nur bei der massenbearbeitung, derselbe hilfscode bei der einzelnen save funktion bringt absolut nichts.

Hilfe X(

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo sekaichizu zouka,

die Lösung wurde schon genannt: Fehler beim Speichern eines Bildes nach Rotieren .

herbivore

s
11 Beiträge seit 2006
vor 17 Jahren

Eben nicht. Ich habe leider etwas falsch geschrieben.

Ich meinte, dass ich eine exception kriege wenn ich das unveränderte Bild der Picturebox drüberspeichere. Denn darin liegt das Problem. Nach einem rotate oder sowas scheint die verbindung zur file nicht mehr da zu sein. Hier ist es aber auf jeden Fall so.

Klar, ich könnte es umgehen indem ich einfach gar nicht speichere, weil die datei eh nicht verändert wird (was wiederum hässlich ist). Aber mich würde interessieren wie es rein theoretisch ginge, ein unverändertes Bild über seine basis zu schreiben, wobei das bild in einer picturebox steht.

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo sekaichizu zouka,

auch diese Lösung wurde schon genannt: Fehler beim Speichern eines Bildes nach Rotieren .

herbivore