//------------------------------------------------------------------------------------- // Encodes a single frame //------------------------------------------------------------------------------------- private static void EncodeImage(PixelBuffer image, WICFlags flags, BitmapFrameEncode frame) { Guid pfGuid; if (!ToWIC(image.Format, out pfGuid)) { throw new NotSupportedException("Format not supported"); } frame.Initialize(); frame.SetSize(image.Width, image.Height); frame.SetResolution(72, 72); Guid targetGuid = pfGuid; frame.SetPixelFormat(ref targetGuid); if (targetGuid != pfGuid) { using (var source = new Bitmap(Factory, image.Width, image.Height, pfGuid, new DataRectangle(image.DataPointer, image.RowStride), image.BufferStride)) { using (var converter = new FormatConverter(Factory)) { using (var palette = new Palette(Factory)) { palette.Initialize(source, 256, true); converter.Initialize(source, targetGuid, GetWICDither(flags), palette, 0, BitmapPaletteType.Custom); int bpp = GetBitsPerPixel(targetGuid); if (bpp == 0) { throw new NotSupportedException("Unable to determine the Bpp for the target format"); } int rowPitch = (image.Width * bpp + 7) / 8; int slicePitch = rowPitch * image.Height; var temp = Utilities.AllocateMemory(slicePitch); try { converter.CopyPixels(rowPitch, temp, slicePitch); frame.Palette = palette; frame.WritePixels(image.Height, temp, rowPitch, slicePitch); } finally { Utilities.FreeMemory(temp); } } } } } else { // No conversion required frame.WritePixels(image.Height, image.DataPointer, image.RowStride, image.BufferStride); } frame.Commit(); }
private static void EncodeImage(ImagingFactory imagingFactory, Image image, WicFlags flags, Guid containerFormat, BitmapFrameEncode frame) { Guid pfGuid = ToWic(image.Format, false); frame.Initialize(); frame.SetSize(image.Width, image.Height); frame.SetResolution(72, 72); Guid targetGuid = pfGuid; frame.SetPixelFormat(ref targetGuid); EncodeMetadata(frame, containerFormat, image.Format); if (targetGuid != pfGuid) { // Conversion required to write. GCHandle handle = GCHandle.Alloc(image.Data, GCHandleType.Pinned); using (var source = new Bitmap(imagingFactory, image.Width, image.Height, pfGuid, new DataRectangle(handle.AddrOfPinnedObject(), image.RowPitch), image.Data.Length)) { using (var converter = new FormatConverter(imagingFactory)) { if (!converter.CanConvert(pfGuid, targetGuid)) { throw new NotSupportedException("Format conversion is not supported."); } converter.Initialize(source, targetGuid, GetWicDither(flags), null, 0, BitmapPaletteType.Custom); frame.WriteSource(converter, new Rectangle(0, 0, image.Width, image.Height)); } } handle.Free(); } else { // No conversion required. frame.WritePixels(image.Height, image.RowPitch, image.Data); } frame.Commit(); }
//------------------------------------------------------------------------------------- // Encodes a single frame //------------------------------------------------------------------------------------- private static void EncodeImage( PixelBuffer image, WICFlags flags, BitmapFrameEncode frame) { Guid pfGuid; if (! ToWIC(image.Format, out pfGuid)) throw new NotSupportedException("Format not supported"); frame.Initialize(); frame.SetSize(image.Width, image.Height); frame.SetResolution(72, 72); Guid targetGuid = pfGuid; frame.SetPixelFormat(ref targetGuid); if (targetGuid != pfGuid) { using (var source = new Bitmap(Factory, image.Width, image.Height, pfGuid, new DataRectangle(image.DataPointer, image.RowStride), image.BufferStride)) { using (var converter = new FormatConverter(Factory)) { using (var palette = new Palette(Factory)) { palette.Initialize(source, 256, true); converter.Initialize(source, targetGuid, GetWICDither(flags), palette, 0, BitmapPaletteType.Custom); int bpp = GetBitsPerPixel(targetGuid); if (bpp == 0) throw new NotSupportedException("Unable to determine the Bpp for the target format"); int rowPitch = (image.Width * bpp + 7) / 8; int slicePitch = rowPitch * image.Height; var temp = Utilities.AllocateMemory(slicePitch); try { converter.CopyPixels(rowPitch, temp, slicePitch); frame.Palette = palette; frame.WritePixels(image.Height, temp, rowPitch, slicePitch); } finally { Utilities.FreeMemory(temp); } } } } } else { // No conversion required frame.WritePixels(image.Height, image.DataPointer, image.RowStride, image.BufferStride); } frame.Commit(); }
private static bool CopyTextureToWICStream(IDeviceResources deviceResource, Texture2D staging, WICStream stream, Guid pfGuid, Guid containerFormat) { using (var encoder = new BitmapEncoder(deviceResource.WICImgFactory, containerFormat)) { var desc = staging.Description; encoder.Initialize(stream); var targetGuid = Guid.Empty; using (var frame = new BitmapFrameEncode(encoder)) { frame.Initialize(); frame.SetSize(desc.Width, desc.Height); frame.SetResolution(72, 72); switch (desc.Format) { case global::SharpDX.DXGI.Format.R32G32B32A32_Float: case global::SharpDX.DXGI.Format.R16G16B16A16_Float: targetGuid = PixelFormat.Format96bppRGBFloat; break; case global::SharpDX.DXGI.Format.R16G16B16A16_UNorm: targetGuid = PixelFormat.Format48bppBGR; break; case global::SharpDX.DXGI.Format.R32_Float: case global::SharpDX.DXGI.Format.R16_Float: case global::SharpDX.DXGI.Format.R16_UNorm: case global::SharpDX.DXGI.Format.R8_UNorm: case global::SharpDX.DXGI.Format.A8_UNorm: targetGuid = PixelFormat.Format48bppBGR; break; default: targetGuid = PixelFormat.Format24bppBGR; break; } frame.SetPixelFormat(ref targetGuid); var databox = deviceResource.Device.ImmediateContext.MapSubresource(staging, 0, MapMode.Read, MapFlags.None); try { if (targetGuid != pfGuid) { using (var bitmap = new Bitmap(deviceResource.WICImgFactory, desc.Width, desc.Height, pfGuid, new global::SharpDX.DataRectangle(databox.DataPointer, databox.RowPitch))) { using (var converter = new FormatConverter(deviceResource.WICImgFactory)) { if (converter.CanConvert(pfGuid, targetGuid)) { converter.Initialize(bitmap, targetGuid, BitmapDitherType.None, null, 0, BitmapPaletteType.MedianCut); frame.WriteSource(converter); } else { Debug.WriteLine("Cannot convert"); } } } } else { frame.WritePixels(desc.Height, new global::SharpDX.DataRectangle(databox.DataPointer, databox.RowPitch), databox.RowPitch * desc.Height); } } finally { deviceResource.Device.ImmediateContext.UnmapSubresource(staging, 0); } frame.Commit(); encoder.Commit(); return(true); } } }
private static void EncodeImage(ImagingFactory imagingFactory, Image image, WicFlags flags, Guid containerFormat, BitmapFrameEncode frame) { Guid pfGuid = ToWic(image.Format, false); frame.Initialize(); frame.SetSize(image.Width, image.Height); frame.SetResolution(72, 72); Guid targetGuid = pfGuid; frame.SetPixelFormat(ref targetGuid); EncodeMetadata(frame, containerFormat, image.Format); if (targetGuid != pfGuid) { // Conversion required to write. GCHandle handle = GCHandle.Alloc(image.Data, GCHandleType.Pinned); using (var source = new Bitmap(imagingFactory, image.Width, image.Height, pfGuid, new DataRectangle(handle.AddrOfPinnedObject(), image.RowPitch), image.Data.Length)) { using (var converter = new FormatConverter(imagingFactory)) { if (!converter.CanConvert(pfGuid, targetGuid)) throw new NotSupportedException("Format conversion is not supported."); converter.Initialize(source, targetGuid, GetWicDither(flags), null, 0, BitmapPaletteType.Custom); frame.WriteSource(converter, new Rectangle(0, 0, image.Width, image.Height)); } } handle.Free(); } else { // No conversion required. frame.WritePixels(image.Height, image.RowPitch, image.Data); } frame.Commit(); }
private static void FlushCurrentFrame(GifBitmapEncoder encoder, ImagingFactory factory, BitmapFrame bitmap) { // nothing to flush. if (bitmap == null) { return; } using (var frameEncoder = new BitmapFrameEncode(encoder)) { frameEncoder.Initialize(); frameEncoder.SetSize(bitmap.Data.Width, bitmap.Data.Height); frameEncoder.SetResolution(bitmap.Data.HorizontalResolution, bitmap.Data.VerticalResolution); // embed frame metadata. var metadataWriter = frameEncoder.MetadataQueryWriter; metadataWriter.SetMetadataByName("/grctlext/Delay", Convert.ToUInt16(bitmap.Delay/100)); metadataWriter.SetMetadataByName("/imgdesc/Left", Convert.ToUInt16(bitmap.XPos)); metadataWriter.SetMetadataByName("/imgdesc/Top", Convert.ToUInt16(bitmap.YPos)); metadataWriter.SetMetadataByName("/imgdesc/Width", Convert.ToUInt16(bitmap.Data.Width)); metadataWriter.SetMetadataByName("/imgdesc/Height", Convert.ToUInt16(bitmap.Data.Height)); using (var bitmapSource = new WicBitmap( factory, bitmap.Data, BitmapAlphaChannelOption.UsePremultipliedAlpha)) { var converter = new FormatConverter(factory); converter.Initialize(bitmapSource, PixelFormat.Format8bppIndexed, BitmapDitherType.Solid, null, 0.8, BitmapPaletteType.MedianCut); frameEncoder.WriteSource(converter); frameEncoder.Commit(); } } }
/// <summary> /// Saves a texture to a stream as an image. /// </summary> /// <param name="texture">The texture to save.</param> /// <param name="imageFormat">The image format of the saved image.</param> /// <param name="imageResolutionInDpi">The image resolution in dpi.</param> /// <param name="toStream">The stream to save the texture to.</param> public static void SaveToStream(this Texture2D texture, System.Drawing.Imaging.ImageFormat imageFormat, double imageResolutionInDpi, System.IO.Stream toStream) { Texture2D textureCopy = null; ImagingFactory imagingFactory = null; Bitmap bitmap = null; BitmapEncoder bitmapEncoder = null; try { textureCopy = new Texture2D(texture.Device, new Texture2DDescription { Width = texture.Description.Width, Height = 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 }); texture.Device.CopyResource(texture, textureCopy); DataRectangle dataRectangle = textureCopy.Map(0, MapMode.Read, SharpDX.Direct3D10.MapFlags.None); imagingFactory = new ImagingFactory(); bitmap = new Bitmap( imagingFactory, textureCopy.Description.Width, textureCopy.Description.Height, PixelFormat.Format32bppBGRA, dataRectangle); toStream.Position = 0; if (imageFormat == System.Drawing.Imaging.ImageFormat.Png) { bitmapEncoder = new PngBitmapEncoder(imagingFactory, toStream); } else if (imageFormat == System.Drawing.Imaging.ImageFormat.Bmp) { bitmapEncoder = new BmpBitmapEncoder(imagingFactory, toStream); } else if (imageFormat == System.Drawing.Imaging.ImageFormat.Gif) { bitmapEncoder = new GifBitmapEncoder(imagingFactory, toStream); } else if (imageFormat == System.Drawing.Imaging.ImageFormat.Jpeg) { bitmapEncoder = new JpegBitmapEncoder(imagingFactory, toStream); } else if (imageFormat == System.Drawing.Imaging.ImageFormat.Tiff) { bitmapEncoder = new TiffBitmapEncoder(imagingFactory, toStream); } else { bitmapEncoder = new PngBitmapEncoder(imagingFactory, toStream); } 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.SetResolution(imageResolutionInDpi, imageResolutionInDpi); bitmapFrameEncode.WriteSource(bitmap); bitmapFrameEncode.Commit(); bitmapEncoder.Commit(); } } finally { bitmapEncoder?.Dispose(); textureCopy?.Unmap(0); textureCopy?.Dispose(); bitmap?.Dispose(); imagingFactory?.Dispose(); } }
/// <summary> /// Saves a texture to a stream as an image. /// </summary> /// <param name="texture">The texture to save.</param> /// <param name="imageFormat">The image format of the saved image.</param> /// <param name="imageResolutionInDpi">The image resolution in dpi.</param> /// <param name="toStream">The stream to save the texture to.</param> public static void SaveToStream(this Texture2D texture, System.Drawing.Imaging.ImageFormat imageFormat, double imageResolutionInDpi, System.IO.Stream toStream) { Texture2D textureCopy = null; ImagingFactory imagingFactory = null; Bitmap bitmap = null; BitmapEncoder bitmapEncoder = null; try { textureCopy = new Texture2D(texture.Device, 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 }); texture.Device.CopyResource(texture, textureCopy); DataRectangle dataRectangle = textureCopy.Map(0, MapMode.Read, SharpDX.Direct3D10.MapFlags.None); imagingFactory = new ImagingFactory(); bitmap = new Bitmap( imagingFactory, textureCopy.Description.Width, textureCopy.Description.Height, PixelFormat.Format32bppBGRA, dataRectangle); toStream.Position = 0; if (imageFormat == System.Drawing.Imaging.ImageFormat.Png) bitmapEncoder = new PngBitmapEncoder(imagingFactory, toStream); else if (imageFormat == System.Drawing.Imaging.ImageFormat.Bmp) bitmapEncoder = new BmpBitmapEncoder(imagingFactory, toStream); else if (imageFormat == System.Drawing.Imaging.ImageFormat.Gif) bitmapEncoder = new GifBitmapEncoder(imagingFactory, toStream); else if (imageFormat == System.Drawing.Imaging.ImageFormat.Jpeg) bitmapEncoder = new JpegBitmapEncoder(imagingFactory, toStream); else if (imageFormat == System.Drawing.Imaging.ImageFormat.Tiff) bitmapEncoder = new TiffBitmapEncoder(imagingFactory, toStream); else bitmapEncoder = new PngBitmapEncoder(imagingFactory, toStream); 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.SetResolution(imageResolutionInDpi, imageResolutionInDpi); bitmapFrameEncode.WriteSource(bitmap); bitmapFrameEncode.Commit(); bitmapEncoder.Commit(); } } finally { bitmapEncoder?.Dispose(); textureCopy?.Unmap(0); textureCopy?.Dispose(); bitmap?.Dispose(); imagingFactory?.Dispose(); } }
private Result SaveWicTextureToFileFix( DeviceContext context, Texture2D source, ref Guid guidContainerFormat, string fileName) { if (fileName == null) { return(Result.InvalidArg); } var res = CaptureTextureFix(context, source, out var desc, out var staging); if (res.Failure) { return(res); } Guid pfGuid; //bool sRGB = false; Guid targetGuid; switch (desc.Format) { case Format.R32G32B32A32_Float: pfGuid = PixelFormat.Format128bppRGBAFloat; break; case Format.R16G16B16A16_Float: pfGuid = PixelFormat.Format64bppRGBAHalf; break; case Format.R16G16B16A16_UNorm: pfGuid = PixelFormat.Format64bppRGBA; break; case Format.R10G10B10_Xr_Bias_A2_UNorm: pfGuid = PixelFormat.Format32bppRGBA1010102XR; break; // DXGI 1.1 case Format.R10G10B10A2_UNorm: pfGuid = PixelFormat.Format32bppRGBA1010102; break; case Format.B5G5R5A1_UNorm: pfGuid = PixelFormat.Format16bppBGRA5551; break; case Format.B5G6R5_UNorm: pfGuid = PixelFormat.Format16bppBGR565; break; case Format.R32_Float: pfGuid = PixelFormat.Format32bppGrayFloat; break; case Format.R16_Float: pfGuid = PixelFormat.Format16bppGrayHalf; break; case Format.R16_UNorm: pfGuid = PixelFormat.Format16bppGray; break; case Format.R8_UNorm: pfGuid = PixelFormat.Format8bppGray; break; case Format.A8_UNorm: pfGuid = PixelFormat.Format8bppAlpha; break; case Format.R8G8B8A8_UNorm: pfGuid = PixelFormat.Format32bppRGBA; break; case Format.R8G8B8A8_UNorm_SRgb: pfGuid = PixelFormat.Format32bppRGBA; //sRGB = true; break; case Format.B8G8R8A8_UNorm: // DXGI 1.1 pfGuid = PixelFormat.Format32bppBGRA; break; case Format.B8G8R8A8_UNorm_SRgb: // DXGI 1.1 pfGuid = PixelFormat.Format32bppBGRA; //sRGB = true; break; case Format.B8G8R8X8_UNorm: // DXGI 1.1 pfGuid = PixelFormat.Format32bppBGR; break; case Format.B8G8R8X8_UNorm_SRgb: // DXGI 1.1 pfGuid = PixelFormat.Format32bppBGR; //sRGB = true; break; default: return(Result.GetResultFromWin32Error(unchecked ((int)0x80070032))); } // Create file var fs = new FileStream(fileName, FileMode.Create); var encoder = new BitmapEncoder(Direct2D.ImageFactory, guidContainerFormat); encoder.Initialize(fs); var frameEncode = new BitmapFrameEncode(encoder); frameEncode.Initialize(); frameEncode.SetSize(desc.Width, desc.Height); frameEncode.SetResolution(72.0, 72.0); switch (desc.Format) { case Format.R32G32B32A32_Float: case Format.R16G16B16A16_Float: targetGuid = PixelFormat.Format24bppBGR; break; case Format.R16G16B16A16_UNorm: targetGuid = PixelFormat.Format48bppBGR; break; case Format.B5G5R5A1_UNorm: targetGuid = PixelFormat.Format16bppBGR555; break; case Format.B5G6R5_UNorm: targetGuid = PixelFormat.Format16bppBGR565; break; case Format.R32_Float: case Format.R16_Float: case Format.R16_UNorm: case Format.R8_UNorm: case Format.A8_UNorm: targetGuid = PixelFormat.Format8bppGray; break; default: targetGuid = PixelFormat.Format24bppBGR; break; } frameEncode.SetPixelFormat(ref targetGuid); #region Write var db = context.MapSubresource(staging, 0, MapMode.Read, MapFlags.None, out _); if (pfGuid != targetGuid) { var formatConverter = new FormatConverter(Direct2D.ImageFactory); if (formatConverter.CanConvert(pfGuid, targetGuid)) { var src = new Bitmap(Direct2D.ImageFactory, desc.Width, desc.Height, pfGuid, new DataRectangle(db.DataPointer, db.RowPitch)); formatConverter.Initialize(src, targetGuid, BitmapDitherType.None, null, 0, BitmapPaletteType.Custom); frameEncode.WriteSource(formatConverter, new Rectangle(0, 0, desc.Width, desc.Height)); } } else { frameEncode.WritePixels(desc.Height, new DataRectangle(db.DataPointer, db.RowPitch)); } context.UnmapSubresource(staging, 0); frameEncode.Commit(); encoder.Commit(); #endregion frameEncode.Dispose(); encoder.Dispose(); fs.Close(); return(Result.Ok); }
/// <summary> /// Function to persist image data to a stream. /// </summary> /// <param name="imageData"><see cref="GorgonLibrary.Graphics.GorgonImageData">Gorgon image data</see> to persist.</param> /// <param name="stream">Stream that will contain the data.</param> protected internal override void SaveToStream(GorgonImageData imageData, Stream stream) { int frameCount = 1; // Wrap the stream so WIC doesn't mess up the position. using (var wrapperStream = new GorgonStreamWrapper(stream)) { using (var wic = new GorgonWICImage()) { // Find a compatible format. Guid targetFormat = wic.GetGUID(imageData.Settings.Format); if (targetFormat == Guid.Empty) { throw new IOException(string.Format(Resources.GORGFX_FORMAT_NOT_SUPPORTED, imageData.Settings.Format)); } Guid actualFormat = targetFormat; using (var encoder = new BitmapEncoder(wic.Factory, SupportedFormat)) { try { encoder.Initialize(wrapperStream); AddCustomMetaData(encoder, null, 0, imageData.Settings, null); } catch (SharpDXException) { // Repackage this exception to keep in line with our API. throw new IOException(string.Format(Resources.GORGFX_IMAGE_FILE_INCORRECT_ENCODER, Codec)); } using (var encoderInfo = encoder.EncoderInfo) { if ((imageData.Settings.ArrayCount > 1) && (CodecUseAllFrames) && (encoderInfo.IsMultiframeSupported)) { frameCount = imageData.Settings.ArrayCount; } for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) { using (var frame = new BitmapFrameEncode(encoder)) { var buffer = imageData.Buffers[0, frameIndex]; frame.Initialize(); frame.SetSize(buffer.Width, buffer.Height); frame.SetResolution(72, 72); frame.SetPixelFormat(ref actualFormat); SetFrameOptions(frame); // If the image encoder doesn't like the format we've chosen, then we'll need to convert to // the best format for the codec. if (targetFormat != actualFormat) { var rect = new DataRectangle(buffer.Data.BasePointer, buffer.PitchInformation.RowPitch); using (var bitmap = new Bitmap(wic.Factory, buffer.Width, buffer.Height, targetFormat, rect)) { // If we're using a codec that supports 8 bit indexed data, then get the palette info. var paletteInfo = GetPaletteInfo(wic, bitmap); if (paletteInfo == null) { throw new IOException(string.Format(Resources.GORGFX_IMAGE_FILE_INCORRECT_ENCODER, Codec)); } try { using (var converter = new FormatConverter(wic.Factory)) { converter.Initialize(bitmap, actualFormat, (BitmapDitherType)Dithering, paletteInfo.Item1, paletteInfo.Item2, paletteInfo.Item3); if (paletteInfo.Item1 != null) { frame.Palette = paletteInfo.Item1; } AddCustomMetaData(encoder, frame, frameIndex, imageData.Settings, (paletteInfo.Item1 != null) ? paletteInfo.Item1.Colors : null); frame.WriteSource(converter); } } finally { if (paletteInfo.Item1 != null) { paletteInfo.Item1.Dispose(); } } } } else { // No conversion was needed, just dump as-is. AddCustomMetaData(encoder, frame, frameIndex, imageData.Settings, null); frame.WritePixels(buffer.Height, buffer.Data.BasePointer, buffer.PitchInformation.RowPitch, buffer.PitchInformation.SlicePitch); } frame.Commit(); } } } encoder.Commit(); } } } }
public static Result SaveTextureToStream(Device d3dDevice, Resource source, Stream stream, Guid containerFormat, Guid targetFormatGuid) { Result result = Result.Fail; if (source == null || d3dDevice == null || stream == null) { return(Result.InvalidArg); } result = CreateStagingTexture(d3dDevice.ImmediateContext, source, out Texture2DDescription desc, out Texture2D staging); if (!result.Success) { return(result); } Guid sourceFormat = desc.Format.ConvertDXGIToWICFormat(); if (sourceFormat == Guid.Empty) { return(Result.InvalidArg); } if (ImagingFactory == null) { return(Result.NoInterface); } Guid targetFormat = targetFormatGuid; if (targetFormat == Guid.Empty) { switch (desc.Format) { case DXGI.Format.R32G32B32A32_Float: case DXGI.Format.R16G16B16A16_Float: if (WIC2) { targetFormat = PixelFormat.Format96bppRGBFloat; } else { targetFormat = PixelFormat.Format24bppBGR; } break; case DXGI.Format.R16G16B16A16_UNorm: targetFormat = PixelFormat.Format48bppBGR; break; case DXGI.Format.B5G5R5A1_UNorm: targetFormat = PixelFormat.Format16bppBGR555; break; case DXGI.Format.B5G6R5_UNorm: targetFormat = PixelFormat.Format16bppBGR565; break; case DXGI.Format.R32_Float: case DXGI.Format.R16_Float: case DXGI.Format.R16_UNorm: case DXGI.Format.R8_UNorm: case DXGI.Format.A8_UNorm: targetFormat = PixelFormat.Format8bppGray; break; default: targetFormat = PixelFormat.Format24bppBGR; break; } } if (targetFormatGuid != Guid.Empty && targetFormatGuid != targetFormat) { return(result); } try { // Create a new file if (stream.CanWrite) { using (BitmapEncoder encoder = new BitmapEncoder(ImagingFactory, containerFormat)) { encoder.Initialize(stream); using (BitmapFrameEncode frameEncode = new BitmapFrameEncode(encoder)) { frameEncode.Initialize(); frameEncode.SetSize(desc.Width, desc.Height); frameEncode.SetResolution(72.0, 72.0); frameEncode.SetPixelFormat(ref targetFormat); if (targetFormatGuid == Guid.Empty || targetFormat == targetFormatGuid) { int subresource = 0; // 讓CPU存取顯存貼圖 // MapSubresource 在 deferred context 下不支援 MapMode.Read DataBox db = d3dDevice.ImmediateContext.MapSubresource(staging, subresource, MapMode.Read, MapFlags.None, out var dataStream); if (sourceFormat != targetFormat) { // BGRA格式轉換 using (FormatConverter formatCoverter = new FormatConverter(ImagingFactory)) { if (formatCoverter.CanConvert(sourceFormat, targetFormat)) { Bitmap src = new Bitmap(ImagingFactory, desc.Width, desc.Height, sourceFormat, new DataRectangle(db.DataPointer, db.RowPitch)); formatCoverter.Initialize(src, targetFormat, BitmapDitherType.None, null, 0, BitmapPaletteType.Custom); frameEncode.WriteSource(formatCoverter, new Rectangle(0, 0, desc.Width, desc.Height)); } } } else { frameEncode.WritePixels(desc.Height, new DataRectangle(db.DataPointer, db.RowPitch)); } // 控制權歸還 d3dDevice.ImmediateContext.UnmapSubresource(staging, subresource); frameEncode.Commit(); encoder.Commit(); result = Result.Ok; } } } } } catch (Exception e) { System.Diagnostics.Debug.WriteLine(e.ToString()); result = Result.Fail; } Utilities.Dispose(ref staging); return(result); }