private static Texture DecodeMultiframe(ImagingFactory imagingFactory, WicFlags flags, TextureDescription description, BitmapDecoder decoder) { var texture = new Texture(description); Guid dstFormat = ToWic(description.Format, false); for (int index = 0; index < description.ArraySize; ++index) { var image = texture.Images[index]; using (var frame = decoder.GetFrame(index)) { var pfGuid = frame.PixelFormat; var size = frame.Size; if (size.Width == description.Width && size.Height == description.Height) { // This frame does not need resized if (pfGuid == dstFormat) { frame.CopyPixels(image.Data, image.RowPitch); } else { using (var converter = new FormatConverter(imagingFactory)) { converter.Initialize(frame, dstFormat, GetWicDither(flags), null, 0, BitmapPaletteType.Custom); converter.CopyPixels(image.Data, image.RowPitch); } } } else { // This frame needs resizing using (var scaler = new BitmapScaler(imagingFactory)) { scaler.Initialize(frame, description.Width, description.Height, GetWicInterp(flags)); Guid pfScaler = scaler.PixelFormat; if (pfScaler == dstFormat) { scaler.CopyPixels(image.Data, image.RowPitch); } else { // The WIC bitmap scaler is free to return a different pixel format than the source image, so here we // convert it to our desired format using (var converter = new FormatConverter(imagingFactory)) { converter.Initialize(scaler, dstFormat, GetWicDither(flags), null, 0, BitmapPaletteType.Custom); converter.CopyPixels(image.Data, image.RowPitch); } } } } } } return texture; }
public D2D1.Bitmap LoadImage(Stream stream) { using (var converter = new WIC.FormatConverter(_renderBase.WicFactory)) using (var scaler = new WIC.BitmapScaler(_renderBase.WicFactory)) using (var rotater = new WIC.BitmapFlipRotator(_renderBase.WicFactory)) using (var bmd = new WIC.BitmapDecoder(_renderBase.WicFactory, stream, WIC.DecodeOptions.CacheOnDemand)) using (var frame = bmd.GetFrame(0)) { /* * var rotation = GetExifRotation(frame); * var size = frame.Size; * scaler.Initialize(frame, (int) (size.Width + 0.5), (int) (size.Height + 0.5), WIC.BitmapInterpolationMode.HighQualityCubic); * converter.Initialize(scaler, WIC.PixelFormat.Format32bppPRGBA); * return ( * D2D1.Bitmap.FromWicBitmap(Target, converter), * GetMatrix(frame, rotation), * GetSize(frame, rotation) * ); */ var size = frame.Size; scaler.Initialize(frame, (int)size.Width, (int)size.Height, WIC.BitmapInterpolationMode.Linear); converter.Initialize(scaler, WIC.PixelFormat.Format32bppPBGRA); rotater.Initialize(converter, GetExifRotation(frame)); return(D2D1.Bitmap.FromWicBitmap(Target, rotater)); } }
public D3D11Renderer(ObservableVideoTrack videoTrack, RendererOptions options) : base(videoTrack, options) { // _factoryDWrite = new DWrite.Factory(DWrite.FactoryType.Shared); var device2D = new D2D1.Device(DeviceDXGI, new D2D1.CreationProperties { DebugLevel = D2D1.DebugLevel.Warning, ThreadingMode = D2D1.ThreadingMode.MultiThreaded, Options = D2D1.DeviceContextOptions.None }); _context2D = new D2D1.DeviceContext(device2D, D2D1.DeviceContextOptions.None); // Load the background image using (var factoryWic = new WIC.ImagingFactory2()) using (var decoder = new WIC.JpegBitmapDecoder(factoryWic)) using (var inputStream = new WIC.WICStream(factoryWic, "background-small.jpg", NativeFileAccess.Read)) using (var formatConverter = new WIC.FormatConverter(factoryWic)) using (var bitmapScaler = new WIC.BitmapScaler(factoryWic)) { decoder.Initialize(inputStream, WIC.DecodeOptions.CacheOnLoad); formatConverter.Initialize(decoder.GetFrame(0), WIC.PixelFormat.Format32bppPBGRA); bitmapScaler.Initialize(formatConverter, VideoFrameWidth, VideoFrameHeight, WIC.BitmapInterpolationMode.Fant); _backgroundBitmap = D2D1.Bitmap1.FromWicBitmap(_context2D, bitmapScaler); } // Create render target _ballEllipse = new D2D1.Ellipse { RadiusX = VideoFrameWidth / 20f, RadiusY = VideoFrameWidth / 20f }; _ballBrush = new D2D1.SolidColorBrush(_context2D, new RawColor4(1f, 1f, 0f, 1f)); }
public D2D1.Bitmap LoadImage(Stream stream) { using (var converter = new WIC.FormatConverter(_renderBase.WicFactory)) using (var scaler = new WIC.BitmapScaler(_renderBase.WicFactory)) using (var bmd = new WIC.BitmapDecoder(_renderBase.WicFactory, stream, WIC.DecodeOptions.CacheOnLoad)) using (var frame = bmd.GetFrame(0)) { var size = frame.Size; scaler.Initialize(frame, (int)(size.Width + 0.5), (int)(size.Height + 0.5), WIC.BitmapInterpolationMode.HighQualityCubic); converter.Initialize(scaler, WIC.PixelFormat.Format32bppPRGBA); return(D2D1.Bitmap.FromWicBitmap(Target, converter)); } }
/// <summary> /// Function to clip or scale the bitmap up or down to the size of the buffer. /// </summary> /// <param name="bitmap">Bitmap to scale.</param> /// <param name="filter">Filtering to apply to the scaled bitmap.</param> /// <param name="buffer">Buffer to receive the scaled bitmap.</param> /// <param name="clip">TRUE to clip, FALSE to scale.</param> /// <returns>TRUE if clipping/scaling was performed, FALSE if not.</returns> private bool ResizeBitmap(WIC.BitmapSource bitmap, WIC.BitmapInterpolationMode filter, GorgonImageBuffer buffer, bool clip) { if (!clip) { using (var scaler = new WIC.BitmapScaler(Factory)) { scaler.Initialize(bitmap, buffer.Width, buffer.Height, filter); scaler.CopyPixels(buffer.PitchInformation.RowPitch, buffer.Data.BasePointer, buffer.PitchInformation.SlicePitch); } return(true); } if ((buffer.Width >= bitmap.Size.Width) && (buffer.Height >= bitmap.Size.Height)) { return(false); } ClipBitmap(bitmap, buffer); return(true); }
//------------------------------------------------------------------------------------- // Decodes an image array, resizing/format converting as needed //------------------------------------------------------------------------------------- private static Image DecodeMultiframe(WICFlags flags, ImageDescription metadata, WIC.BitmapDecoder decoder) { var image = Image.New(metadata); Guid sourceGuid; if (!ToWIC(metadata.Format, out sourceGuid)) { return(null); } for (int index = 0; index < metadata.ArraySize; ++index) { var pixelBuffer = image.PixelBuffer[index, 0]; using (var frame = decoder.GetFrame(index)) { var pfGuid = frame.PixelFormat; var size = frame.Size; if (pfGuid == sourceGuid) { if (size.Width == metadata.Width && size.Height == metadata.Height) { // This frame does not need resized or format converted, just copy... frame.CopyPixels(pixelBuffer.RowStride, pixelBuffer.DataPointer, pixelBuffer.BufferStride); } else { // This frame needs resizing, but not format converted using (var scaler = new WIC.BitmapScaler(Factory)) { scaler.Initialize(frame, metadata.Width, metadata.Height, GetWICInterp(flags)); scaler.CopyPixels(pixelBuffer.RowStride, pixelBuffer.DataPointer, pixelBuffer.BufferStride); } } } else { // This frame required format conversion using (var converter = new WIC.FormatConverter(Factory)) { converter.Initialize(frame, pfGuid, GetWICDither(flags), null, 0, WIC.BitmapPaletteType.Custom); if (size.Width == metadata.Width && size.Height == metadata.Height) { converter.CopyPixels(pixelBuffer.RowStride, pixelBuffer.DataPointer, pixelBuffer.BufferStride); } else { // This frame needs resizing, but not format converted using (var scaler = new WIC.BitmapScaler(Factory)) { scaler.Initialize(frame, metadata.Width, metadata.Height, GetWICInterp(flags)); scaler.CopyPixels(pixelBuffer.RowStride, pixelBuffer.DataPointer, pixelBuffer.BufferStride); } } } } } } return(image); }
public bool GetThumbnail(Stream stream, int width, int height, bool cachedOnly, out byte[] imageData, out ImageType imageType) { imageData = null; imageType = ImageType.Unknown; // No support for cache if (cachedOnly) return false; try { if (stream.CanSeek) stream.Seek(0, SeekOrigin.Begin); // open the image file for reading using (var factory = new ImagingFactory2()) using (var inputStream = new WICStream(factory, stream)) using (var decoder = new BitmapDecoder(factory, inputStream, DecodeOptions.CacheOnLoad)) using (var scaler = new BitmapScaler(factory)) using (var output = new MemoryStream()) using (var encoder = new BitmapEncoder(factory, ContainerFormatGuids.Jpeg)) { // decode the loaded image to a format that can be consumed by D2D BitmapSource source = decoder.GetFrame(0); // Scale down larger images int sourceWidth = source.Size.Width; int sourceHeight = source.Size.Height; if (width > 0 && height > 0 && (sourceWidth > width || sourceHeight > height)) { if (sourceWidth <= height) width = sourceWidth; int newHeight = sourceHeight * height / sourceWidth; if (newHeight > height) { // Resize with height instead width = sourceWidth * height / sourceHeight; newHeight = height; } scaler.Initialize(source, width, newHeight, BitmapInterpolationMode.Fant); source = scaler; } encoder.Initialize(output); using (var bitmapFrameEncode = new BitmapFrameEncode(encoder)) { // Create image encoder var wicPixelFormat = PixelFormat.FormatDontCare; bitmapFrameEncode.Initialize(); bitmapFrameEncode.SetSize(source.Size.Width, source.Size.Height); bitmapFrameEncode.SetPixelFormat(ref wicPixelFormat); bitmapFrameEncode.WriteSource(source); bitmapFrameEncode.Commit(); encoder.Commit(); } imageData = output.ToArray(); imageType = ImageType.Jpeg; return true; } } catch (Exception e) { // ServiceRegistration.Get<ILogger>().Warn("WICThumbnailProvider: Error loading bitmapSource from file data stream", e); return false; } }
//------------------------------------------------------------------------------------- // Decodes an image array, resizing/format converting as needed //------------------------------------------------------------------------------------- private static Image DecodeMultiframe(WICFlags flags, ImageDescription metadata, BitmapDecoder decoder) { var image = Image.New(metadata); Guid sourceGuid; if (!ToWIC(metadata.Format, out sourceGuid)) return null; for (int index = 0; index < metadata.ArraySize; ++index) { var pixelBuffer = image.PixelBuffer[index, 0]; using (var frame = decoder.GetFrame(index)) { var pfGuid = frame.PixelFormat; var size = frame.Size; if (pfGuid == sourceGuid) { if (size.Width == metadata.Width && size.Height == metadata.Height) { // This frame does not need resized or format converted, just copy... frame.CopyPixels(pixelBuffer.RowStride, pixelBuffer.DataPointer, pixelBuffer.BufferStride); } else { // This frame needs resizing, but not format converted using (var scaler = new BitmapScaler(Factory)) { scaler.Initialize(frame, metadata.Width, metadata.Height, GetWICInterp(flags)); scaler.CopyPixels(pixelBuffer.RowStride, pixelBuffer.DataPointer, pixelBuffer.BufferStride); } } } else { // This frame required format conversion using (var converter = new FormatConverter(Factory)) { converter.Initialize(frame, pfGuid, GetWICDither(flags), null, 0, BitmapPaletteType.Custom); if (size.Width == metadata.Width && size.Height == metadata.Height) { converter.CopyPixels(pixelBuffer.RowStride, pixelBuffer.DataPointer, pixelBuffer.BufferStride); } else { // This frame needs resizing, but not format converted using (var scaler = new BitmapScaler(Factory)) { scaler.Initialize(frame, metadata.Width, metadata.Height, GetWICInterp(flags)); scaler.CopyPixels(pixelBuffer.RowStride, pixelBuffer.DataPointer, pixelBuffer.BufferStride); } } } } } } return image; }
/// <summary> /// Function to perform conversion/transformation of a bitmap. /// </summary> /// <param name="sourceData">WIC bitmap to transform.</param> /// <param name="destData">Destination data buffer.</param> /// <param name="rowPitch">Number of bytes per row in the image.</param> /// <param name="slicePitch">Number of bytes in total for the image.</param> /// <param name="destFormat">Destination format for transformation.</param> /// <param name="isSourcesRGB">TRUE if the source format is sRGB.</param> /// <param name="isDestsRGB">TRUE if the destination format is sRGB.</param> /// <param name="dither">Dithering to apply to images that get converted to a lower bit depth.</param> /// <param name="destRect">Rectangle containing the area to scale or clip</param> /// <param name="clip">TRUE to perform clipping instead of scaling.</param> /// <param name="scaleFilter">Filter to apply to scaled data.</param> public void TransformImageData(WIC.BitmapSource sourceData, IntPtr destData, int rowPitch, int slicePitch, Guid destFormat, bool isSourcesRGB, bool isDestsRGB, ImageDithering dither, Rectangle destRect, bool clip, ImageFilter scaleFilter) { WIC.BitmapSource source = sourceData; WIC.FormatConverter converter = null; WIC.BitmapClipper clipper = null; WIC.BitmapScaler scaler = null; WIC.ColorContext sourceContext = null; WIC.ColorContext destContext = null; WIC.ColorTransform sRGBTransform = null; try { if (destFormat != Guid.Empty) { if (sourceData.PixelFormat != destFormat) { converter = new WIC.FormatConverter(Factory); if (!converter.CanConvert(sourceData.PixelFormat, destFormat)) { throw new GorgonException(GorgonResult.FormatNotSupported, string.Format(Resources.GORGFX_FORMAT_NOT_SUPPORTED, destFormat)); } converter.Initialize(source, destFormat, (WIC.BitmapDitherType)dither, null, 0, WIC.BitmapPaletteType.Custom); source = converter; } if ((isDestsRGB) || (isSourcesRGB)) { sRGBTransform = new WIC.ColorTransform(Factory); sourceContext = new WIC.ColorContext(Factory); destContext = new WIC.ColorContext(Factory); sourceContext.InitializeFromExifColorSpace(isSourcesRGB ? 1 : 2); destContext.InitializeFromExifColorSpace(isDestsRGB ? 1 : 2); sRGBTransform.Initialize(source, sourceContext, destContext, destFormat); source = sRGBTransform; } } if (destRect.IsEmpty) { source.CopyPixels(rowPitch, destData, slicePitch); return; } Guid pixelFormat = source.PixelFormat; if (!clip) { scaler = new WIC.BitmapScaler(Factory); scaler.Initialize(source, destRect.Width, destRect.Height, (WIC.BitmapInterpolationMode)scaleFilter); source = scaler; } else { destRect.Width = destRect.Width.Min(source.Size.Width); destRect.Height = destRect.Height.Min(source.Size.Height); if ((destRect.Width < source.Size.Width) || (destRect.Height < source.Size.Height)) { clipper = new WIC.BitmapClipper(Factory); clipper.Initialize(source, new DX.Rectangle(destRect.X, destRect.Y, destRect.Width, destRect.Height)); source = clipper; destRect.X = 0; destRect.Y = 0; } } // We have a change of format (probably due to the filter when scaling)... so we need to convert. if (source.PixelFormat != pixelFormat) { converter = new WIC.FormatConverter(Factory); if (!converter.CanConvert(source.PixelFormat, pixelFormat)) { throw new GorgonException(GorgonResult.FormatNotSupported, string.Format(Resources.GORGFX_FORMAT_NOT_SUPPORTED, pixelFormat)); } converter.Initialize(source, pixelFormat, WIC.BitmapDitherType.None, null, 0, WIC.BitmapPaletteType.Custom); source = converter; } source.CopyPixels(rowPitch, destData, slicePitch); } finally { if (converter != null) { converter.Dispose(); } if (sourceContext != null) { sourceContext.Dispose(); } if (destContext != null) { destContext.Dispose(); } if (sRGBTransform != null) { sRGBTransform.Dispose(); } if (scaler != null) { scaler.Dispose(); } if (clipper != null) { clipper.Dispose(); } } }
/// <summary> /// Function to convert the format of a bitmap into the format of the buffer. /// </summary> /// <param name="sourceFormat">Format to convert from.</param> /// <param name="destFormat">Format to convert into.</param> /// <param name="dithering">Dithering to apply.</param> /// <param name="filter">Filtering to apply to scaled bitmaps.</param> /// <param name="bitmap">Bitmap to convert.</param> /// <param name="bitmapPalette">Palette for the bitmap.</param> /// <param name="alphaValue">Value of pixel to consider transparent.</param> /// <param name="buffer">Buffer holding the converted data.</param> /// <param name="scale">TRUE to scale when converting, FALSE to keep at original size.</param> /// <param name="clip">TRUE to perform clipping, FALSE to keep at original size.</param> private void ConvertFormat(Guid sourceFormat, Guid destFormat, WIC.BitmapDitherType dithering, WIC.BitmapInterpolationMode filter, WIC.BitmapSource bitmap, WIC.Palette bitmapPalette, int alphaValue, GorgonImageBuffer buffer, bool scale, bool clip) { WIC.BitmapSource source = bitmap; double alphaPercent = alphaValue / 255.0; var paletteType = WIC.BitmapPaletteType.Custom; // If we have a palette, then confirm that the dithering method is valid. if (bitmapPalette != null) { // Do not apply dithering if we're using // a custom palette and request ordered dithering. switch (dithering) { case WIC.BitmapDitherType.Ordered4x4: case WIC.BitmapDitherType.Ordered8x8: case WIC.BitmapDitherType.Ordered16x16: if (bitmapPalette.TypeInfo == WIC.BitmapPaletteType.Custom) { dithering = WIC.BitmapDitherType.None; } break; } paletteType = bitmapPalette.TypeInfo; } try { // Create a scaler if need one. if ((scale) && (!clip)) { var scaler = new WIC.BitmapScaler(Factory); scaler.Initialize(bitmap, buffer.Width, buffer.Height, filter); source = scaler; } // Create a clipper if we want to clip and the image needs resizing. if ((clip) && (scale) && ((buffer.Width < bitmap.Size.Width) || (buffer.Height < bitmap.Size.Height))) { var clipper = new WIC.BitmapClipper(Factory); clipper.Initialize(bitmap, new DX.Rectangle(0, 0, buffer.Width < bitmap.Size.Width ? buffer.Width : bitmap.Size.Width, buffer.Height < bitmap.Size.Height ? buffer.Height : bitmap.Size.Height)); source = clipper; } using (var converter = new WIC.FormatConverter(Factory)) { if (!converter.CanConvert(sourceFormat, destFormat)) { throw new GorgonException(GorgonResult.FormatNotSupported, string.Format(Resources.GORGFX_FORMAT_NOT_SUPPORTED, buffer.Format)); } converter.Initialize(source, destFormat, dithering, bitmapPalette, alphaPercent, paletteType); if (!scale) { int rowPitch = (GetBitsPerPixel(destFormat) * bitmap.Size.Width + 7) / 8; int slicePitch = rowPitch * bitmap.Size.Height; if ((rowPitch != buffer.PitchInformation.RowPitch) || (slicePitch != buffer.PitchInformation.SlicePitch)) { throw new GorgonException(GorgonResult.CannotWrite, Resources.GORGFX_IMAGE_PITCH_TOO_SMALL); } } converter.CopyPixels(buffer.PitchInformation.RowPitch, buffer.Data.BasePointer, buffer.PitchInformation.SlicePitch); } } finally { if (source != bitmap) { source.Dispose(); } } }