2010-08-02 8 views
7

Come eseguire questa operazione in C#?Caricamento di un file in una bitmap ma lasciando intatto il file originale

Se utilizzo Bitmap.FromFile(), il file originale è bloccato.

Se utilizzo Bitmap.FromStream(), il file originale non è bloccato, ma la documentazione dice "È necessario mantenere il flusso aperto per tutta la durata dell'immagine". Questo probabilmente significa che il file è ancora collegato all'oggetto immagine, (ad esempio, forse se il file cambia così fa l'oggetto o viceversa).

quello che voglio fare è solo leggere il bitmap e salvarlo in un oggetto e dopo che non v'è alcun legame di sorta tra il file e l'oggetto Immagine

risposta

25

Alcune informazioni di base su questo comportamento: Bitmap utilizza un file mappato in memoria per accedere ai pixel nella bitmap. Questa è una funzionalità molto semplice nell'API di Windows, consente una mappatura della memoria molto efficiente ai dati dei file. I dati vengono letti dal file solo quando il programma legge la memoria, le pagine di memoria virtuale non occupano spazio nel file di paging di Windows.

Lo stesso meccanismo viene utilizzato per caricare gli assembly .NET. È la mappatura della memoria che mette un blocco sul file. Il che è fondamentalmente il motivo per cui gli assembly vengono bloccati quando vengono utilizzati in un programma .NET. Il metodo Image.Dispose() rilascia il blocco. Combattere il lucchetto spesso indica che ti stai dimenticando di disporre le tue bitmap. Molto importante, dimenticarsi di chiamare Dispose() non causa spesso problemi per le classi .NET, tranne Bitmap, dal momento che può richiedere così tanta memoria (non gestita).

Sì, FromStream() impedisce alla classe di eseguire questa ottimizzazione. Il costo è significativo, è necessario raddoppiare la memoria quando viene caricata la bitmap. Questo sarà un problema quando la bitmap è grande, stai passando OOM quando il programma è in esecuzione da un po '(frammentando lo spazio degli indirizzi) e non è in esecuzione su un sistema operativo a 64 bit. Evita decisamente questo se la larghezza della bitmap x Altezza x 4> = 45 MB, dare o avere.

del codice, non si deve saltare attraverso il cerchio CopyStream:

public static Image LoadImageNoLock(string path) { 
     var ms = new MemoryStream(File.ReadAllBytes(path)); // Don't use using!! 
     return Image.FromStream(ms); 
    } 

Nota che non si vuole eliminare il MemoryStream, si otterrà un difficile da diagnosticare "errore generico" quando la bitmap viene usata se lo fai. Causato dalla classe Image che legge il flusso in modo lazy.

+0

Anche questo è necessario per ottenere la bitmap. Bitmap bitmap = new Bitmap (LoadImageNoLock (path)); – Harris

+2

MemoryStream è Usa e getta, chi si occuperà di eliminarlo in questa soluzione? – kwesolowski

4

leggere il file nella memoria copiandolo da una FileStream in un MemoryStream. (Cerca CopyStream in Stack Overflow per trovare un sacco di esempi su come farlo in modo sicuro. Fondamentalmente loop durante la lettura, scrivendo ogni pezzo nel flusso di memoria, fino a quando non ci sono più dati da leggere.) Quindi riavvolgere il MemoryStream (set Position = 0) e quindi passare a Bitmap.FromStream.

4

Per creare un'immagine senza bloccare il file, è necessario creare una copia di FileStream dell'immagine. Controllare questa pagina Best way to copy between two Stream instances - C# per come copiare lo stream.

Successivamente, crea l'immagine dallo stream copiato e sei pronto per partire.

+0

+1 per fare la ricerca per noi che Jon ha suggerito di fare ... Hai trovato un ottimo post per questo. – awe

0

Ho usato questa tecnica di copia su MemoryStream e poi l'alimentazione di MemoryStream a Bitmap.FromStream un sacco di volte. Tuttavia, c'è anche un trucco con questa tecnica.

Se si prevede di utilizzare uno dei metodi Bitmap.Save in seguito sull'immagine caricata, sarà necessario mantenere attivo lo stream (ad es., non disporlo dopo che l'immagine è stata caricata), altrimenti otterrai la temuta eccezione "Si è verificato un errore generico GDI +"!

Problemi correlati