Eine Texture2D in XNA kann nur so viel aufnehmen. Je nachdem, welches Profil ich verwende, ist diese Grenze entweder 2048 oder 4096 Pixel breit. Soweit ich anhand meiner Recherchen feststellen konnte (jemand korrigiert mich, wenn ich falsch liege), haben GDI-Bilder keine andere Einschränkung, als den Speicher des Benutzers nicht zu überschreiten.
Ich suche nach der effizientesten Möglichkeit, ein GDI-Image und ein Quellrechteck (innerhalb der Größenbeschränkungen von XNA) zu erstellen und zur Laufzeit aus diesen Daten eine neue Texture2D zu erstellen. Der Prozess muss auch das vormultiplizierte Alpha von XNA 4.0 berücksichtigen!
ODER...
Eine Möglichkeit, Texture2D.FromStream so anzupassen, dass auch ein Quellrechteck verwendet wird, da dies für meine Anforderungen noch besser wäre.
Die Anforderungen sind:
- Keine Inhaltspipeline, ich muss sie zur Laufzeit laden können.
- Wenn möglich nur Profil erreichen!
- Kümmere dich nur um Windows. Sorgen Sie sich nicht um die Portabilität.
TL; DR:
Ich brauche eine Methode wie:
Texture2D Texture2DHelper.FromStream(GraphicsDevice, Stream, SourceRectangle);
Oder
Texture2D Texture2DHelper.FromImage(Image, SourceRectangle)
Am liebsten der erste.
Großes Bild:
Ich habe das Quellrechteck für einen Moment ignoriert (um die Visualisierung zu vereinfachen) und versucht, eine ganze Textur in GDI zu laden und die Daten mithilfe eines Brute-Force-Ansatzes an Texture2D zu übergeben:
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);
}
Und das Ergebnis war sehr langsam. Es hat viele, viele Male länger gedauert als nur:
Texture2D.FromStream(GraphicsDevice, new FileStream(path, FileMode.Open));
Ich habe auch darüber nachgedacht, Bitmap.LockBits und eine Blockkopie zu verwenden, aber dies würde die vormultiplizierte Alphakorrektur auslassen, und ich weiß nicht, wie ich sie nach der Kopie anwenden soll.
Ich bin versucht zu glauben, dass eine bessere Lösung darin besteht, Texture2D.FromStream direkt zu umgehen ... Ich bin nicht allzu vertraut mit der Funktionsweise von Stream, aber ich habe in .NET einige Methoden gesehen, die einen Stream und ein Rechteck verwenden. Wie würde ich so etwas erreichen? Entweder eine völlig neue FromStream-Methode oder ein Wrapper um einen Stream, der "Rechteck" -Funktionalität bietet.