Come trovare il motivo dell’errore GDI + generico durante il salvataggio di un’immagine?

Avendo un codice che funziona da anni durante il caricamento e la memorizzazione delle immagini, ho scoperto che ho una singola immagine che spezza questo codice:

const string i1Path = @"c:\my\i1.jpg"; const string i2Path = @"c:\my\i2.jpg"; var i = Image.FromFile(i1Path); i.Save(i2Path, ImageFormat.Jpeg); 

L’eccezione è:

Si è verificato System.Runtime.InteropServices.ExternalException

Si è verificato un errore generico in GDI +.

a System.Drawing.Image.Save (nome file String, codificatore ImageCodecInfo, encoder EncoderParametersParams)
a System.Drawing.Image.Save (nome file String, formato ImageFormat)
a …

Per quanto posso vedere, non c’è niente di speciale nell’immagine. Ha una dimensione di circa 250 pixel e può essere aperto, ad esempio, in Image Imageer o in Paint.NET:

inserisci la descrizione dell'immagine qui

(Poiché l’immagine sopra, dopo essere stata caricata su Stack Overflow, non produce più l’errore, ho messo qui l’immagine originale )

Quello che ho scoperto è che, richiamando il metodo Save , il file immagine di destinazione viene creato con zero byte.

Sono davvero all’oscuro di ciò che causa l’errore.

Le mie domande:

  • Riesci a pensare a qualcosa di speciale che potrebbe impedire a .NET di salvare l’immagine?
  • Esiste un modo (a parte la panificazione) per limitare questo tipo di errori?

Mentre ancora non ho trovato il motivo per cui ciò che ha causato esattamente l’errore durante il salvataggio dell’immagine, ho trovato una soluzione alternativa da applicare:

 const string i1Path = @"c:\my\i1.jpg"; const string i2Path = @"c:\my\i2.jpg"; var i = Image.FromFile(i1Path); var i2 = new Bitmap(i); i2.Save(i2Path, ImageFormat.Jpeg); 

Cioè copiando l’immagine internamente in un’istanza Bitmap e salvando questa immagine invece dell’immagine originale, l’errore è scomparso.

Presumo che copiandolo, le parti errate che hanno causato il fallimento della chiamata di Save originale vengano rimosse e / o normalizzate, consentendo in questo modo l’operazione di salvataggio.

immagine salvata i2.jpg

È interessante notare che l’immagine così archiviata ha un file più piccolo su disco (16 kB) rispetto alla sua fonte originale (26 kB).

Prima di tutto assicurati che la cartella desiderata abbia i permessi di lettura / scrittura. Cambiare le autorizzazioni ha risolto questo problema per me.

La soluzione è qui, è necessario disporre l’object immagine per rilasciare la memoria sul server. Prova a usare l’istruzione. Assicurarsi che anche la directory di destinazione sul server sia presente.

la mia soluzione era creare, scrivere contenuto temporaneo (File.WriteAllText) appena prima di salvare il file

Ecco il codice:

 var i = Image.FromFile(i1Path); File.WriteAllText(i2Path, "empty"); // <---- magic goes here i.Save(i2Path, ImageFormat.Jpeg); 

Per favore prova e fammi sapere

Il motivo potrebbe essere che l’immagine viene caricata pigramente e il processo di caricamento non è ancora terminato quando si tenta di salvarlo.

A seguito di ciò che viene detto in questo post del blog (supponendo che tu sia tedesco per l’immagine che hai collegato nella tua domanda) fornisce una ansible soluzione. Anche la risposta accettata di questa domanda SO indica che ciò è dovuto al fatto che il file di immagine che stai cercando di salvare è bloccato.

MODIFICARE
Per Ulysses Alves, dal post di blog collegato: Se carichi un’immagine usando Image.FromFile() rimane bloccata finché non viene eliminata. Ciò impedisce chiamate a Save() .

 pictureBox1.Image = Image.FromFile("C:\\test\\test1.jpg"); pictureBox1.Image.Save("C:\\test\\test2.jpg"); 

Il codice sopra riportato genera un errore.

Per farlo funzionare, è necessario copiare l’immagine. Il seguente codice funziona:

 pictureBox1.Image = Image.FromFile("C:\\test\\test1.jpg"); Image copy = pictureBox1.Image; copy.Save("C:\\test\\test2.jpg") 

Apri nel programma

 const string i1Path = @"c:\my\i1.jpg"; const string i2Path = @"c:\my\i2.jpg"; var i = Image.FromFile(i1Path); i.Save(i2Path, ImageFormat.Jpeg); i.Dispose();