¿Cuál es la resolución máxima de C # .NET Bitmap?

Teóricamente, debería ser 65.535 x 65.535 dado que tienes suficiente memoria, alrededor de 17 GB.

Sin embargo, al crear una aplicación de consola .NET 4.5 para probarlo, arroja System.ArgumentException: el parámetro no es válido.

La aplicación está construida para la plataforma de 64 bits. Se ejecuta en la plataforma de 64 bits con 32 GB de memoria. La resolución máxima que he podido obtener es de 22,000 x 22,000 píxeles.

No pude encontrar ninguna documentación sobre esto.

Y el comportamiento extraño es que incluso a 22,000 x 22,000 píxeles, no siempre funciona. A veces funciona, y a veces arroja la excepción. Esto me hace pensar que está relacionado con la asignación de memoria contigua, pero hay alrededor de 30 GB de memoria libre.

¿Alguien tiene alguna experiencia con esto? Y si quisiera trabajar con una imagen de 100.000 x 100,000 pixeles y más grande, ¿cuál sería la mejor manera además de implementar mi propio bitmap?

EDITAR: El problema no es .NET Maximum Object Size. Esto se puede solucionar apuntando a plataformas de 64 bits y configurando el indicador gcAllowVeryLargeObjects en la configuración de la aplicación. De esta forma, puedo hacer que la aplicación consum más de 15GB de memoria con una única matriz de enteros. Hasta ahora, la respuesta parece estar en la implementación subyacente del GDI +, pero ¿cómo puedo solucionarlo?

Esta es una limitación de GDI + impuesta por Windows. GDI + crea una vista de archivo mapeada en memoria para los datos de píxeles del bitmap. Eso lo hace muy eficiente, los mapas de bits tienden a ser grandes y el archivo MMF ayuda a mantener los datos de píxel fuera del archivo de paginación. Las páginas RAM pueden simplemente descartarse y volverse a leer desde el archivo. También bastante notorio, muchos progtwigdores han visto que su llamada a Save () falla con una excepción wonky cuando se olvidaron de deshacerse del bitmap anterior.

Windows restringe el tamaño de la vista en un archivo MMF, es decir, la cantidad de datos en el archivo que se pueden direccionar directamente, como se documenta en este artículo de MSDN :

El tamaño de un objeto de asignación de archivos respaldado por un archivo con nombre está limitado por el espacio en disco. El tamaño de una vista de archivo está limitado al bloque contiguo más grande disponible de memoria virtual no reservada. Esto es como máximo 2 GB menos la memoria virtual ya reservada por el proceso.

El “bloque continuo más grande disponible” es la restricción en un proceso de 32 bits, tiende a rondar los ~ 600 MB, más o menos. El límite de 2 GB se inicia en un proceso de 64 bits. Técnicamente, GDI + podría pasar por alto este límite al reasignar la vista. Pero no es así, el método LockBits () (también muy usado internamente) sería ineficiente y muy difícil de usar.

Para utilizar mapas de bits más grandes, debe pasar al sucesor de GDI +, WIC ( componente de imágenes de Windows ). Expuesto en .NET a través del espacio de nombres System.Windows.Media.Imaging.

Se está ejecutando en el tamaño de objeto máximo permitido dentro de .net. Esto se trata aquí: una colección muy grande en .Net causa una excepción de falta de memoria

Editar: Parece que se está ejecutando en una limitación de GDI Plus. La respuesta de Hans puede proporcionarte una alternativa. Si puede vivir dentro de las limitaciones, entonces mi respuesta puede proporcionar alguna orientación.

Sabiendo que puede calcular el bitmap más grande que puede crear.

  • El tamaño máximo de objeto es 2GB: 2,147,483,648
  • El bitmap predeterminado es 32bpp (4 bytes), el área más grande que podemos tener es 2GB / 4 = 536,870,912
  • Si queremos un cuadrado, lo más grande que podemos obtener es sqrt (2GB / 4) = 23,170

Entonces el siguiente código funciona bien:

 Bitmap b = new Bitmap(23170,23170); 

Pero el siguiente falla:

 Bitmap b = new Bitmap(23171,23170); 

Si desea almacenar una imagen con dimensiones más grandes, debe cambiar el formato de píxeles a un número menor de bpp:

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