Texture2D в XNA может содержать только так много. В зависимости от того, какой профиль я использую, этот предел составляет 2048 или 4096 пикселей в ширину. Насколько я могу судить по моим исследованиям (кто-то поправит меня, если я ошибаюсь) GDI-изображения не имеют никаких ограничений, кроме того, что они не превышают память пользователя.
Я ищу наиболее эффективный способ взять изображение GDI и исходный прямоугольник (в пределах ограничений размера XNA) и создать новый Texture2D из этих данных во время выполнения. Процесс также должен учитывать предварительно умноженную альфа в XNA 4.0!
ИЛИ...
Способ взять Texture2D.FromStream и адаптировать его так, чтобы он тоже занимал исходный прямоугольник, так как это было бы еще лучше для моих нужд.
Требования следующие:
- Нет конвейера контента, мне нужно иметь возможность загружать их во время выполнения.
- Если возможно, используйте только профиль Reach!
- Заботьтесь только о Windows. Не беспокойтесь о портативности.
TL; DR:
Мне нужен такой метод, как:
Texture2D Texture2DHelper.FromStream(GraphicsDevice, Stream, SourceRectangle);
Или
Texture2D Texture2DHelper.FromImage(Image, SourceRectangle)
Желательно первое.
Большая фотография:
На мгновение игнорируя исходный прямоугольник (чтобы упростить визуализацию), я попытался загрузить целую текстуру в GDI и передать данные в Texture2D, используя полностью грубый метод:
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);
}
И результат был действительно медленным. Это заняло много много раз дольше, чем просто:
Texture2D.FromStream(GraphicsDevice, new FileStream(path, FileMode.Open));
Я также думал об использовании Bitmap.LockBits и Block Copy, но при этом исключалась бы предварительно умноженная альфа-коррекция, и я не знаю, как применить ее после копирования.
Я испытываю желание думать, что лучшим решением было бы работать непосредственно с Texture2D.FromStream ... Я не слишком знаком с тем, как работает Stream, но я видел некоторые методы в .NET, которые принимают Stream и Rectangle. Как бы я достиг чего-то подобного? Либо совершенно новый метод FromStream, либо обертка вокруг любого потока, который обеспечивает функциональность «Прямоугольник».