2015-03-20 13 views
5

In teoria, dovrebbe essere 65.535 x 65.535 dato che hai abbastanza memoria, circa 17 GB.Qual è la risoluzione massima di Bitmap C# .NET?

Tuttavia, creando un'applicazione di console .NET 4.5 per testarlo, lancia System.ArgumentException: il parametro non è valido.

L'applicazione è progettata per la piattaforma 64 bit. Funzionante su piattaforma 64 bit con 32 GB di memoria. La risoluzione massima che sono riuscito a ottenere è 22.000 x 22.000 pixel.

Non ho trovato alcuna documentazione su questo.

E il comportamento strano è che anche a 22.000 x 22.000 pixel, non sempre funziona. A volte funziona e a volte genera un'eccezione. Questo mi fa pensare che sia legato ad un'allocazione di memoria contigua, ma ci sono circa 30 GB di memoria libera.

Qualcuno ha qualche esperienza con questo? E se volessi lavorare con, ad esempio, un'immagine di 100.000 x 100.000 pixel e più grande, quale sarebbe il modo migliore per implementare la mia bitmap?

MODIFICA: il problema non è .NET Dimensione massima dell'oggetto. Ciò può essere risolto mediante il targeting per piattaforme a 64 bit e l'impostazione del flag gcAllowVeryLargeObjects nella configurazione dell'applicazione. In questo modo, posso ottenere l'applicazione per consumare oltre 15 GB di memoria con un singolo array di numeri interi. Finora, la risposta sembra trovarsi nella sottostante implementazione del GDI +, ma come faccio a evitarlo?

+0

Bitmap .NET utilizza GDI +, vedere questa domanda per la discussione sulle limitazioni http://stackoverflow.com/questions/2932436/net-gdi-image-size-file-codec-limitations –

+0

Ho disassemblato il costruttore per Bitmap (int , int) e chiama GdipCreateBitmapFromScan0, che deve restituire un codice di errore. Il costruttore Bitmap mappa i codici di errore in varie eccezioni .NET. –

+1

Per interessi, perché dici 65.535 x 65.535? Per ['Immagine'] (http://msdn.microsoft.com/en-us/library/system.drawing.image) (che [' BitMap'] (https://msdn.microsoft.com/en-us /library/system.drawing.bitmap) è una sottoclasse di), il ['Width'] (http://msdn.microsoft.com/en-us/library/system.drawing.image.width) e [' Height Le proprietà '] (http://msdn.microsoft.com/en-us/library/system.drawing.image.height) sono tipi' int', mentre la tua domanda implica che sono 'ushort'. –

risposta

13

Questo è un GDI + limitazione imposta da Windows . GDI + crea una vista file mappata in memoria per i dati pixel della bitmap. Ciò lo rende molto efficiente, le bitmap tendono ad essere grandi e l'MMF aiuta a mantenere i dati dei pixel fuori dal file di paging. Le pagine RAM possono essere semplicemente scartate e rilette dal file. Inoltre, un po 'famigerato, molti programmatori hanno visto fallire la loro chiamata a Save() con una falsa eccezione quando si sono dimenticati di disporre della vecchia bitmap.

di Windows limita quanto grande la vista su un MMF può essere, in altre parole, la quantità di dati nel file che può essere affrontato direttamente, come documentato in this MSDN article:

La dimensione di un oggetto di file di mapping che è supportato da un file con nome è limitato dallo spazio su disco. La dimensione di una vista file è limitata al più grande blocco contiguo disponibile di memoria virtuale non prenotata. Questo è al massimo 2 GB meno la memoria virtuale già riservata dal processo.

"Il blocco continuo più grande disponibile" è la restrizione in un processo a 32 bit, tende a oscillare attorno a ~ 600 MB, dare o prendere. Il limite di 2 GB inizia con un processo a 64 bit. Tecnicamente GDI + potrebbe aggirare questo limite rimappando la vista. Ma non è così, il metodo LockBits() (anche pesantemente utilizzato internamente) sarebbe inefficiente e molto scomodo da usare.

Per utilizzare bitmap di dimensioni maggiori è necessario passare al modello successivo di GDI +, WIC (Windows Imaging Component). Esposto in .NET tramite lo spazio dei nomi System.Windows.Media.Imaging.

5

Si sta eseguendo la dimensione massima dell'oggetto consentita all'interno di .net. Che è coperto qui: Very large collection in .Net causes out-of-memory exception

Modifica: Sembra che si stiano verificando una limitazione di GDI Plus. Hans 'answer può fornire un'alternativa. Se riesci a vivere entro i limiti, la mia risposta può fornire una guida.

Sapendo che è possibile calcolare la bitmap più grande che è possibile creare.

  • La massima è formato oggetto è 2GB: bitmap 2,147,483,648
  • default è 32bpp (4 byte), la più grande area che possiamo avere è da 2 GB/4 = 536.870.912
  • Se vogliamo una piazza, la più grande noi può ottenere è sqrt (2GB/4) = 23.170

Così il seguente codice funziona bene:

Bitmap b = new Bitmap(23170,23170); 

Ma il seguente fa ils:

Bitmap b = new Bitmap(23171,23170); 

Se si desidera memorizzare un'immagine con dimensioni maggiori, si dovrebbe cambiare il formato di pixel su un numero inferiore di BPP:

Bitmap b = new Bitmap(65535,65535, PixelFormat.Format4bppIndexed); 
+0

Does not bpp di solito significa * bit * per pixel, non byte? – harold

+0

@harold Sì, quello era un errore di battitura. –

+0

La tua teoria non è corretta, le classi Image e Bitmap memorizzano solo un * handle *, non i dati dei pixel. –

Problemi correlati