Qual è la risoluzione massima di Bitmap C # .NET?

In teoria, dovrebbe essere 65.535 x 65.535 dato che hai abbastanza memoria, circa 17 GB.

Tuttavia, creando un’applicazione di console .NET 4.5 per testarlo, lancia System.ArgumentException: Parameter non è valido.

L’applicazione è costruita 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 sono riuscito a trovare 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?

EDIT: il problema non è .NET Dimensione massima dell’object. Ciò può essere risolto mediante il targeting per piattaforms 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?

Questa è una limitazione GDI + 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.

Windows limita la dimensione della vista su un MMF, in altre parole la quantità di dati nel file che può essere direttamente indirizzata, come documentato in questo articolo MSDN :

Le dimensioni di un object di mapping file supportato da un file con nome sono limitate 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 avere. 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 più grandi è necessario passare al successore di GDI +, WIC ( Windows Imaging Component ). Esposto in .NET tramite lo spazio dei nomi System.Windows.Media.Imaging.

Stai eseguendo la dimensione massima dell’object consentita all’interno di .net. Questo è coperto qui: Raccolta molto grande in. Net causa un’eccezione fuori memoria

Modifica: sembra che ci si stia imbattendo in una limitazione di GDI Plus. La risposta di Hans può fornirti un’alternativa. Se riesci a vivere entro i limiti, la mia risposta può fornire una guida.

Sapendo che puoi calcolare la più grande bitmap che puoi creare.

  • La dimensione massima dell’object è 2 GB: 2.147.483.648
  • La bitmap predefinita è 32bpp (4 byte), l’area più grande che possiamo avere è 2GB / 4 = 536,870,912
  • Se vogliamo un quadrato, il più grande che possiamo ottenere è sqrt (2GB / 4) = 23.170

Quindi il seguente codice funziona bene:

 Bitmap b = new Bitmap(23170,23170); 

Ma il seguente non riesce:

 Bitmap b = new Bitmap(23171,23170); 

Se si desidera memorizzare un’immagine con dimensioni maggiori, è necessario modificare il formato del pixel in un numero inferiore di bpp:

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