//------------------------------------------------------------------------------------- // 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 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> /// SharpDX WIC sample. Encode to JPG and decode. /// </summary> static void Main() { const int width = 512; const int height = 512; const string filename = "output.jpg"; var factory = new ImagingFactory(); WICStream stream = null; // ------------------------------------------------------ // Encode a JPG image // ------------------------------------------------------ // Create a WIC outputstream if (File.Exists(filename)) { File.Delete(filename); } stream = new WICStream(factory, filename, NativeFileAccess.Write); // Initialize a Jpeg encoder with this stream var encoder = new JpegBitmapEncoder(factory); encoder.Initialize(stream); // Create a Frame encoder var bitmapFrameEncode = new BitmapFrameEncode(encoder); bitmapFrameEncode.Options.ImageQuality = 0.8f; bitmapFrameEncode.Initialize(); bitmapFrameEncode.SetSize(width, height); var guid = PixelFormat.Format24bppBGR; bitmapFrameEncode.SetPixelFormat(ref guid); // Write a pseudo-plasma to a buffer int stride = PixelFormat.GetStride(PixelFormat.Format24bppBGR, width); var bufferSize = height * stride; var buffer = new DataStream(bufferSize, true, true); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { buffer.WriteByte((byte)(x / 2.0 + 20.0 * Math.Sin(y / 40.0))); buffer.WriteByte((byte)(y / 2.0 + 30.0 * Math.Sin(x / 80.0))); buffer.WriteByte((byte)(x / 2.0)); } } // Copy the pixels from the buffer to the Wic Bitmap Frame encoder bitmapFrameEncode.WritePixels(512, new DataRectangle(buffer.DataPointer, stride)); // Commit changes bitmapFrameEncode.Commit(); encoder.Commit(); bitmapFrameEncode.Dispose(); encoder.Dispose(); stream.Dispose(); // ------------------------------------------------------ // Decode the previous JPG image // ------------------------------------------------------ // Read input stream = new WICStream(factory, filename, NativeFileAccess.Read); var decoder = new JpegBitmapDecoder(factory); decoder.Initialize(stream, DecodeOptions.CacheOnDemand); var bitmapFrameDecode = decoder.GetFrame(0); var queryReader = bitmapFrameDecode.MetadataQueryReader; // Dump MetadataQueryreader queryReader.Dump(Console.Out); queryReader.Dispose(); bitmapFrameDecode.Dispose(); decoder.Dispose(); stream.Dispose(); // Dispose factory.Dispose(); System.Diagnostics.Process.Start(Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, filename))); }
/// <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); }
/// <summary> /// SharpDX WIC sample. Encode to JPG and decode. /// </summary> static void Main() { const int width = 512; const int height = 512; const string filename = "output.jpg"; var factory = new ImagingFactory(); WICStream stream = null; // ------------------------------------------------------ // Encode a JPG image // ------------------------------------------------------ // Create a WIC outputstream if (File.Exists(filename)) File.Delete(filename); stream = new WICStream(factory, filename, NativeFileAccess.Write); // Initialize a Jpeg encoder with this stream var encoder = new JpegBitmapEncoder(factory); encoder.Initialize(stream); // Create a Frame encoder var bitmapFrameEncode = new BitmapFrameEncode(encoder); bitmapFrameEncode.Options.ImageQuality = 0.8f; bitmapFrameEncode.Initialize(); bitmapFrameEncode.SetSize(width, height); var guid = PixelFormat.Format24bppBGR; bitmapFrameEncode.SetPixelFormat(ref guid); // Write a pseudo-plasma to a buffer int stride = PixelFormat.GetStride(PixelFormat.Format24bppBGR, width); var bufferSize = height * stride; var buffer = new DataStream(bufferSize, true, true); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { buffer.WriteByte((byte)(x / 2.0 + 20.0 * Math.Sin(y / 40.0))); buffer.WriteByte((byte)(y / 2.0 + 30.0 * Math.Sin(x / 80.0))); buffer.WriteByte((byte)(x / 2.0)); } } // Copy the pixels from the buffer to the Wic Bitmap Frame encoder bitmapFrameEncode.WritePixels(512, new DataRectangle(buffer.DataPointer, stride)); // Commit changes bitmapFrameEncode.Commit(); encoder.Commit(); bitmapFrameEncode.Dispose(); encoder.Dispose(); stream.Dispose(); // ------------------------------------------------------ // Decode the previous JPG image // ------------------------------------------------------ // Read input stream = new WICStream(factory, filename, NativeFileAccess.Read); var decoder = new JpegBitmapDecoder(factory); decoder.Initialize(stream, DecodeOptions.CacheOnDemand); var bitmapFrameDecode = decoder.GetFrame(0); var queryReader = bitmapFrameDecode.MetadataQueryReader; // Dump MetadataQueryreader queryReader.Dump(Console.Out); queryReader.Dispose(); bitmapFrameDecode.Dispose(); decoder.Dispose(); stream.Dispose(); // Dispose factory.Dispose(); System.Diagnostics.Process.Start(Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, filename))); }