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...
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.
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
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...
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
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...
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
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...
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
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...
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...
funktioniert nicht. bringt mich wieder an meinen anfangspunkt...
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...
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...
Mach mal ein leeres Projekt
Einen Button... Code reinpasten ... Testen !
Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...
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!
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...
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
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...
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...
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.
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"
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
muss ich jetzt die datei vorher schließen oder was?
"Round Round Robin"
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
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"
Hallo violeta,
FileDialog.FileName und FileDialog.Filter. Codebeispiele in der SDK-Doku.
herbivore
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"
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
okay schau mal deren code durch
hier der link wenns wer braucht:
http://msdn.microsoft.com/library/deu/default.asp?url=/library/DEU/cpref/html/frlrfsystemwindowsformssavefiledialogclassoverwriteprompttopic.asp
"Round Round Robin"
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"
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"
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...
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"
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"
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(
Hallo sekaichizu zouka,
die Lösung wurde schon genannt: Fehler beim Speichern eines Bildes nach Rotieren .
herbivore
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.
Hallo sekaichizu zouka,
auch diese Lösung wurde schon genannt: Fehler beim Speichern eines Bildes nach Rotieren .
herbivore