Um Texture2D no XNA pode suportar tanto. Dependendo de qual perfil eu uso, esse limite tem 2048 ou 4096 pixels de largura. Tanto quanto pude perceber na minha pesquisa (alguém me corrija se eu estiver errado), as Imagens GDI não têm outra limitação além de não exceder a memória do usuário.
Estou procurando a maneira mais eficiente de obter uma imagem GDI e um retângulo de origem (dentro das limitações de tamanho do XNA) e criar um novo Texture2D a partir desses dados em tempo de execução. O processo também deve levar em conta o alfa pré-multiplicado do XNA 4.0!
OU...
Uma maneira de pegar o Texture2D.FromStream e adaptá-lo para que ele também use um retângulo de origem, pois isso seria ainda melhor para minhas necessidades.
Os requisitos são:
- Sem pipeline de conteúdo, preciso poder carregá-los em tempo de execução.
- Utilizando apenas o perfil Reach, se possível!
- Se preocupe apenas com o Windows. Não se preocupe com portabilidade.
TL; DR:
Eu preciso de um método como:
Texture2D Texture2DHelper.FromStream(GraphicsDevice, Stream, SourceRectangle);
Ou
Texture2D Texture2DHelper.FromImage(Image, SourceRectangle)
De preferência o primeiro.
Quadro geral:
Ignorando o retângulo de origem por um momento (para facilitar a visualização), tentei carregar uma textura inteira no GDI e passar os dados para um Texture2D usando uma abordagem de força bruta:
using (System.Drawing.Image image = System.Drawing.Image.FromFile(path))
{
int w = image.Width;
int h = image.Height;
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(image);
uint[] data = new uint[w * h];
for (int i=0; i!=bitmap.Width; ++i)
{
for (int j=0; j!=bitmap.Height; ++j)
{
System.Drawing.Color pixel = bitmap.GetPixel(i, j);
Microsoft.Xna.Framework.Color color = Color.FromNonPremultiplied(pixel.R, pixel.G, pixel.B, pixel.A);
data[i + j * w] = color.PackedValue;
}
}
_texture = new Texture2D(device, w, h);
_texture.SetData(data);
}
E o resultado foi muito lento. Demorou muitas vezes mais do que simplesmente fazer:
Texture2D.FromStream(GraphicsDevice, new FileStream(path, FileMode.Open));
Também pensei em usar o Bitmap.LockBits e uma cópia de bloco, mas isso deixaria de fora a correção alfa pré-multiplicada e não sei como aplicá-la após a cópia.
Estou tentado a pensar que uma solução melhor seria contornar o Texture2D.FromStream diretamente ... Não estou muito familiarizado com o funcionamento do Stream, mas vi alguns métodos no .NET que usam um Stream e um Retângulo. Como eu conseguiria algo assim? Um método FromStream inteiramente novo ou um invólucro em torno de qualquer Stream que forneça a funcionalidade "Retângulo".