Un Texture2D dans XNA ne peut contenir qu'une telle quantité. Selon le profil que j'utilise, cette limite est de 2048 ou 4096 pixels de large. Autant que je sache d'après mes recherches (quelqu'un me corrige si je me trompe), les images GDI n'ont aucune limitation autre que de ne pas dépasser la mémoire de l'utilisateur.
Je cherche le moyen le plus efficace de prendre une image GDI et un rectangle source (dans les limites de taille de XNA) et de créer un nouveau Texture2D à partir de ces données lors de l'exécution. Le processus doit également prendre en compte l'alpha pré-multiplié de XNA 4.0!
OU...
Une façon de prendre Texture2D.FromStream et de l'adapter pour qu'il prenne aussi un rectangle source, car ce serait encore mieux pour mes besoins.
Les exigences sont les suivantes:
- Pas de pipeline de contenu, je dois pouvoir les charger lors de l'exécution.
- Utiliser uniquement le profil Reach si possible!
- Ne vous souciez que de Windows. Ne vous inquiétez pas de la portabilité.
TL; DR:
J'ai besoin d'une méthode telle que:
Texture2D Texture2DHelper.FromStream(GraphicsDevice, Stream, SourceRectangle);
Ou
Texture2D Texture2DHelper.FromImage(Image, SourceRectangle)
De préférence le premier.
Grande image:
Ignorant le rectangle source pendant un moment (pour rendre les choses plus faciles à visualiser), j'ai essayé de charger une texture entière dans GDI et de passer les données à un Texture2D en utilisant une approche complètement brute:
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);
}
Et le résultat a été vraiment lent. Cela a pris plusieurs fois plus de temps que de le faire:
Texture2D.FromStream(GraphicsDevice, new FileStream(path, FileMode.Open));
J'ai également pensé à utiliser Bitmap.LockBits et une copie de bloc, mais cela laisserait de côté la correction alpha pré-multipliée, et je ne sais pas comment l'appliquer après la copie.
Je suis tenté de penser qu'une meilleure solution serait de contourner directement Texture2D.FromStream ... Je ne suis pas trop familier avec le fonctionnement de Stream mais j'ai vu quelques méthodes dans .NET qui prennent un Stream et un Rectangle. Comment pourrais-je réaliser quelque chose comme ça? Soit une méthode FromStream entièrement nouvelle, soit un wrapper autour de n'importe quel Stream qui fournit la fonctionnalité "Rectangle".