Qual é a resolução máxima do C # .NET Bitmap?

Teoricamente, deve ser 65.535 x 65.535, dado que você tem memory suficiente, cerca de 17GB.

No entanto, criando um aplicativo de console do .NET 4.5 para testá-lo, ele lança System.ArgumentException: O parâmetro não é válido.

O aplicativo é construído para plataforma de 64 bits. Correndo em plataforma de 64 bits com 32 GB de memory. A resolução máxima que consegui foi de 22.000 x 22.000 pixels.

Não consegui encontrar nenhuma documentação sobre isso.

E o comportamento estranho é que, mesmo com 22.000 x 22.000 pixels, nem sempre funciona. Às vezes funciona e às vezes lança a exceção. Isso me faz pensar que está relacionado à alocação de memory contígua, mas há cerca de 30 GB de memory livre.

alguém tem alguma experiência com isso? E se eu quisesse trabalhar com, digamos, 100.000 x 100.000 pixels ou mais, qual seria a melhor maneira de implementar meu próprio bitmap?

EDIT: O problema não é o tamanho máximo do object .NET. Isso pode ser superado direcionando para plataformas de 64 bits e definindo o sinalizador gcAllowVeryLargeObjects na configuração do aplicativo. Dessa forma, posso fazer com que o aplicativo consuma mais de 15 GB de memory com uma única matriz de inteiros. Até agora, a resposta parece estar na implementação subjacente do GDI +, mas como posso contorná-la?

Esta é uma limitação GDI + imposta pelo Windows. GDI + cria uma exibição de arquivo mapeada em memory para os dados de pixel do bitmap. Isso torna muito eficiente, os bitmaps tendem a ser grandes e o arquivo MMF ajuda a manter os dados de pixel fora do arquivo de paginação. As páginas RAM podem simplesmente ser descartadas e relidas no arquivo. Também bastante notório, muitos programadores viram sua chamada Save () falhar com uma exceção complicada quando se esqueceram de descartar o antigo bitmap.

O Windows restringe o tamanho da exibição em um arquivo MMF, ou seja, a quantidade de dados no arquivo que pode ser endereçada diretamente, conforme documentado neste artigo do MSDN :

O tamanho de um object de mapeamento de arquivo que é feito por um arquivo nomeado é limitado pelo espaço em disco. O tamanho de uma exibição de arquivo é limitado ao maior bloco contíguo disponível de memory virtual não reservada. Isso é no máximo 2 GB menos a memory virtual já reservada pelo processo.

“Maior bloco contínuo disponível” é a restrição em um processo de 32 bits, tende a pairar em torno de ~ 600 MB, mais ou menos. O limite de 2 GB entra em ação em um processo de 64 bits. Tecnicamente GDI + poderia ignorar esse limite, remapeando a exibição. Mas isso não acontece, o método LockBits () (também muito usado internamente) seria ineficiente e muito difícil de usar.

Para usar bitmaps maiores, você precisa mover para o sucessor do GDI +, WIC ( Windows Imaging Component ). Expostos no .NET através do namespace System.Windows.Media.Imaging.

Você está correndo para o tamanho máximo permitido do object dentro de .net. Isso é coberto aqui: Uma coleção muito grande no .net causa exceção de falta de memory

Edit: Você parece estar correndo em uma limitação de GDI Plus. A resposta de Hans pode fornecer uma alternativa. Se você pode viver dentro das limitações, então minha resposta pode fornecer alguma orientação.

Sabendo que você pode calcular o maior bitmap que você pode criar.

  • O máximo é o tamanho do object é de 2 GB: 2.147.483.648
  • O bitmap padrão é 32bpp (4 bytes), a maior área que podemos ter é 2GB / 4 = 536,870,912
  • Se queremos um quadrado, o maior que conseguimos é sqrt (2GB / 4) = 23.170

Então o código a seguir funciona bem:

 Bitmap b = new Bitmap(23170,23170); 

Mas o seguinte falha:

 Bitmap b = new Bitmap(23171,23170); 

Se você quiser armazenar uma imagem com dimensões maiores, você teria que alterar o formato do pixel para um número menor de bpp:

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