Un Texture2D in XNA può contenere solo così tanto. A seconda del profilo che uso quel limite è largo 2048 o 4096 pixel. Per quanto ne so dalla mia ricerca (qualcuno mi corregga se sbaglio) Le immagini GDI non hanno limiti se non quello di non superare la memoria dell'utente.
Sto cercando il modo più efficiente per acquisire un'immagine GDI e un rettangolo di origine (entro i limiti delle dimensioni di XNA) e creare un nuovo Texture2D da quei dati in fase di esecuzione. Il processo deve anche tenere conto dell'alfa pre-moltiplicata di XNA 4.0!
O...
Un modo per prendere Texture2D.FromStream e adattarlo in modo che prenda anche un rettangolo di origine, poiché sarebbe ancora meglio per le mie esigenze.
I requisiti sono:
- Nessuna pipeline di contenuti, devo essere in grado di caricarli in fase di esecuzione.
- Utilizzando solo il profilo Reach, se possibile!
- Cura solo Windows. Non preoccuparti della portabilità.
TL; DR:
Ho bisogno di un metodo come:
Texture2D Texture2DHelper.FromStream(GraphicsDevice, Stream, SourceRectangle);
O
Texture2D Texture2DHelper.FromImage(Image, SourceRectangle)
Preferibilmente il primo.
Quadro generale:
Ignorando per un momento il rettangolo di origine (per rendere le cose più facili da visualizzare), ho provato a caricare un'intera trama in GDI e passare i dati a Texture2D usando un approccio completamente a forza 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 il risultato è stato davvero lento. Ci è voluto molto più tempo del semplice fare:
Texture2D.FromStream(GraphicsDevice, new FileStream(path, FileMode.Open));
Ho anche pensato di usare Bitmap.LockBits e una copia di blocco, ma farlo escluderebbe la correzione alfa pre-moltiplicata e non so come applicarla dopo la copia.
Sono tentato di pensare che una soluzione migliore sarebbe quella di aggirare direttamente Texture2D.FromStream ... Non ho troppa familiarità con il funzionamento di Stream ma ho visto alcuni metodi in .NET che utilizzano Stream e Rectangle. Come potrei ottenere qualcosa del genere? Un metodo FromStream completamente nuovo o un wrapper attorno a qualsiasi Stream che fornisce funzionalità "Rectangle".