问题
I'm trying to save a user-generated Texture2D to disk, but it looks like the standard ways of accomplishing this aren't available when targeting DirectX11.1 / Win8.1 / Metro. ToStream/FromStream are absent, and the DX11 methods for writing a texture to disk are absent as well.
Any ideas or suggestions?
回答1:
Here's the general solution I ended up with. Getting a DataStream through mapping a texture resource is what got me on the right track.
General flow is create a texture with CpuAccessFlags.Read, then CopyResource from the source texture to the new texture, then read data from the new texture into a WIC Bitmap.
public static class Texture2DExtensions
{
public static void Save(this Texture2D texture, IRandomAccessStream stream, DeviceManager deviceManager)
{
var textureCopy = new Texture2D(deviceManager.DeviceDirect3D, new Texture2DDescription
{
Width = (int)texture.Description.Width,
Height = (int)texture.Description.Height,
MipLevels = 1,
ArraySize = 1,
Format = texture.Description.Format,
Usage = ResourceUsage.Staging,
SampleDescription = new SampleDescription(1, 0),
BindFlags = BindFlags.None,
CpuAccessFlags = CpuAccessFlags.Read,
OptionFlags = ResourceOptionFlags.None
});
deviceManager.ContextDirect3D.CopyResource(texture, textureCopy);
DataStream dataStream;
var dataBox = deviceManager.ContextDirect3D.MapSubresource(
textureCopy,
0,
0,
MapMode.Read,
SharpDX.Direct3D11.MapFlags.None,
out dataStream);
var dataRectangle = new DataRectangle
{
DataPointer = dataStream.DataPointer,
Pitch = dataBox.RowPitch
};
var bitmap = new Bitmap(
deviceManager.WICFactory,
textureCopy.Description.Width,
textureCopy.Description.Height,
PixelFormat.Format32bppBGRA,
dataRectangle);
using (var s = stream.AsStream())
{
s.Position = 0;
using (var bitmapEncoder = new PngBitmapEncoder(deviceManager.WICFactory, s))
{
using (var bitmapFrameEncode = new BitmapFrameEncode(bitmapEncoder))
{
bitmapFrameEncode.Initialize();
bitmapFrameEncode.SetSize(bitmap.Size.Width, bitmap.Size.Height);
var pixelFormat = PixelFormat.FormatDontCare;
bitmapFrameEncode.SetPixelFormat(ref pixelFormat);
bitmapFrameEncode.WriteSource(bitmap);
bitmapFrameEncode.Commit();
bitmapEncoder.Commit();
}
}
}
deviceManager.ContextDirect3D.UnmapSubresource(textureCopy, 0);
textureCopy.Dispose();
bitmap.Dispose();
}
}
来源:https://stackoverflow.com/questions/21243270/saving-a-texture2d-using-sharpdx-when-targeting-win8-1-metro