/// <inheritdoc/> protected override void OnFrameApply(ImageFrame <TPixelDst> source, Rectangle sourceRectangle, Configuration configuration) { Image <TPixelSrc> targetImage = this.Image; PixelBlender <TPixelDst> blender = this.Blender; int locationY = this.Location.Y; // Align start/end positions. Rectangle bounds = targetImage.Bounds(); int minX = Math.Max(this.Location.X, sourceRectangle.X); int maxX = Math.Min(this.Location.X + bounds.Width, sourceRectangle.Width); int targetX = minX - this.Location.X; int minY = Math.Max(this.Location.Y, sourceRectangle.Y); int maxY = Math.Min(this.Location.Y + bounds.Height, sourceRectangle.Bottom); int width = maxX - minX; var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); ParallelHelper.IterateRows( workingRect, configuration, rows => { for (int y = rows.Min; y < rows.Max; y++) { Span <TPixelDst> background = source.GetPixelRowSpan(y).Slice(minX, width); Span <TPixelSrc> foreground = targetImage.GetPixelRowSpan(y - locationY).Slice(targetX, width); blender.Blend <TPixelSrc>(configuration, background, background, foreground, this.Opacity); } }); }
/// <summary> /// Initializes a new instance of the <see cref="VignetteProcessor{TPixel}" /> class. /// </summary> /// <param name="color">The color of the vignette.</param> /// <param name="options">The options effecting blending and composition.</param> public VignetteProcessor(TPixel color, GraphicsOptions options) { this.VignetteColor = color; this.options = options; this.blender = PixelOperations <TPixel> .Instance.GetPixelBlender(this.options.BlenderMode); }
/// <inheritdoc/> protected override void OnFrameApply(ImageFrame <TPixelDst> source, Rectangle sourceRectangle, Configuration configuration) { Image <TPixelSrc> targetImage = this.Image; PixelBlender <TPixelDst> blender = this.Blender; int locationY = this.Location.Y; // Align start/end positions. Rectangle bounds = targetImage.Bounds(); int minX = Math.Max(this.Location.X, sourceRectangle.X); int maxX = Math.Min(this.Location.X + bounds.Width, sourceRectangle.Width); int targetX = minX - this.Location.X; int minY = Math.Max(this.Location.Y, sourceRectangle.Y); int maxY = Math.Min(this.Location.Y + bounds.Height, sourceRectangle.Bottom); int width = maxX - minX; MemoryAllocator memoryAllocator = this.Image.GetConfiguration().MemoryAllocator; ParallelFor.WithConfiguration( minY, maxY, configuration, y => { Span <TPixelDst> background = source.GetPixelRowSpan(y).Slice(minX, width); Span <TPixelSrc> foreground = targetImage.GetPixelRowSpan(y - locationY).Slice(targetX, width); blender.Blend <TPixelSrc>(memoryAllocator, background, background, foreground, this.Opacity); }); }
public static IPixelBlender GetBlender(PixelFormat backBuffer, Endianess backBufferEndianess, PixelFormat fronBuffer, Endianess frontBufferEndianes, PixelFormat output, Endianess outputEndianess, PixelFormat?clutForegroundFormat = null, PixelFormat?clutBackgroundFormat = null) { var blenderConfiguration = Tuple.Create(backBuffer, backBufferEndianess, fronBuffer, frontBufferEndianes, output, outputEndianess); if (!blendersCache.ContainsKey(blenderConfiguration)) { blendersCache[blenderConfiguration] = new PixelBlender(backBuffer, fronBuffer, output, GenerateBlendMethod( new BufferDescriptor { ColorFormat = backBuffer, ClutColorFormat = clutBackgroundFormat, DataEndianness = backBufferEndianess }, new BufferDescriptor { ColorFormat = fronBuffer, ClutColorFormat = clutForegroundFormat, DataEndianness = frontBufferEndianes }, new BufferDescriptor { ColorFormat = output, DataEndianness = outputEndianess })); } return(blendersCache[blenderConfiguration]); }
public void ReturnsCorrectBlender <TPixel>(TestPixel <TPixel> pixel, Type type, PixelBlenderMode mode) where TPixel : struct, IPixel <TPixel> { PixelBlender <TPixel> blender = PixelOperations <TPixel> .Instance.GetPixelBlender(mode); Assert.IsType(type, blender); }
/// <summary> /// Initializes a new instance of the <see cref="GlowProcessor{TPixel}" /> class. /// </summary> /// <param name="color">The color or the glow.</param> /// <param name="radius">The radius of the glow.</param> /// <param name="options">The options effecting blending and composition.</param> public GlowProcessor(TPixel color, ValueSize radius, GraphicsOptions options) { this.options = options; this.GlowColor = color; this.Radius = radius; this.blender = PixelOperations <TPixel> .Instance.GetPixelBlender(this.options.BlenderMode); }
public void ReturnsCorrectBlender <TPixel>(TestPixel <TPixel> pixel, Type type, PixelColorBlendingMode mode) where TPixel : unmanaged, IPixel <TPixel> { PixelBlender <TPixel> blender = PixelOperations <TPixel> .Instance.GetPixelBlender(mode, PixelAlphaCompositionMode.SrcOver); Assert.IsType(type, blender); }
/// <inheritdoc /> protected override void OnFrameApply(ImageFrame <TPixelBg> source) { SixLabors.ImageSharp.Rectangle sourceRectangle = this.SourceRectangle; Configuration configuration = this.Configuration; SixLabors.ImageSharp.Image <TPixelFg> image = this.Image; PixelBlender <TPixelBg> blender = this.Blender; int y = this.Location.Y; SixLabors.ImageSharp.Rectangle rectangle1 = image.Bounds(); int num = Math.Max(this.Location.X, sourceRectangle.X); int right = Math.Min(this.Location.X + rectangle1.Width, sourceRectangle.Right); int targetX = num - this.Location.X; int top = Math.Max(this.Location.Y, sourceRectangle.Y); int bottom = Math.Min(this.Location.Y + rectangle1.Height, sourceRectangle.Bottom); int width = right - num; SixLabors.ImageSharp.Rectangle rectangle2 = SixLabors.ImageSharp.Rectangle.FromLTRB(num, top, right, bottom); if (rectangle2.Width <= 0 || rectangle2.Height <= 0) { throw new ImageProcessingException( "Cannot draw image because the source image does not overlap the target image."); } InterpolateProcessor <TPixelBg, TPixelFg> .RowOperation operation = new InterpolateProcessor <TPixelBg, TPixelFg> .RowOperation( source, image, blender, configuration, num, width, y, targetX, InterpolationValue); ParallelRowIterator.IterateRows <InterpolateProcessor <TPixelBg, TPixelFg> .RowOperation>( configuration, rectangle2, in operation); }
public static IPixelBlender GetBlender(PixelFormat backBuffer, Endianess backBufferEndianess, PixelFormat fronBuffer, Endianess frontBufferEndianes, PixelFormat output, Endianess outputEndianess, PixelFormat? clutForegroundFormat = null, PixelFormat? clutBackgroundFormat = null) { var blenderConfiguration = Tuple.Create(backBuffer, backBufferEndianess, fronBuffer, frontBufferEndianes, output, outputEndianess); if(!blendersCache.ContainsKey(blenderConfiguration)) { blendersCache[blenderConfiguration] = new PixelBlender(backBuffer, fronBuffer, output, GenerateBlendMethod( new BufferDescriptor { ColorFormat = backBuffer, ClutColorFormat = clutBackgroundFormat, DataEndianness = backBufferEndianess }, new BufferDescriptor { ColorFormat = fronBuffer, ClutColorFormat = clutForegroundFormat, DataEndianness = frontBufferEndianes }, new BufferDescriptor { ColorFormat = output, DataEndianness = outputEndianess })); } return blendersCache[blenderConfiguration]; }
public void BlendFillColorOverBackround <TPixel>( TestImageProvider <TPixel> provider, bool triggerFillRegion, string newColorName, float alpha, PixelBlenderMode blenderMode, float blendPercentage) where TPixel : struct, IPixel <TPixel> { var vec = TestUtils.GetPixelOfNamedColor <RgbaVector>(newColorName).ToVector4(); vec.W = alpha; TPixel fillColor = default; fillColor.PackFromVector4(vec); using (Image <TPixel> image = provider.GetImage()) { TPixel bgColor = image[0, 0]; var options = new GraphicsOptions(false) { BlenderMode = blenderMode, BlendPercentage = blendPercentage }; if (triggerFillRegion) { var region = new ShapeRegion(new RectangularPolygon(0, 0, 16, 16)); image.Mutate(c => c.Fill(options, new SolidBrush <TPixel>(fillColor), region)); } else { image.Mutate(c => c.Fill(options, new SolidBrush <TPixel>(fillColor))); } var testOutputDetails = new { triggerFillRegion = triggerFillRegion, newColorName = newColorName, alpha = alpha, blenderMode = blenderMode, blendPercentage = blendPercentage }; image.DebugSave( provider, testOutputDetails, appendPixelTypeToFileName: false, appendSourceFileOrDescription: false); PixelBlender <TPixel> blender = PixelOperations <TPixel> .Instance.GetPixelBlender(blenderMode); TPixel expectedPixel = blender.Blend(bgColor, fillColor, blendPercentage); image.ComparePixelBufferTo(expectedPixel); } }
public void BlendFillColorOverBackground <TPixel>( TestImageProvider <TPixel> provider, bool triggerFillRegion, string newColorName, float alpha, PixelColorBlendingMode blenderMode, float blendPercentage) where TPixel : unmanaged, IPixel <TPixel> { Color fillColor = TestUtils.GetColorByName(newColorName).WithAlpha(alpha); using (Image <TPixel> image = provider.GetImage()) { TPixel bgColor = image[0, 0]; var options = new DrawingOptions { GraphicsOptions = new GraphicsOptions { Antialias = false, ColorBlendingMode = blenderMode, BlendPercentage = blendPercentage } }; if (triggerFillRegion) { var path = new RectangularPolygon(0, 0, 16, 16); image.Mutate(c => c.SetGraphicsOptions(options.GraphicsOptions).Fill(new SolidBrush(fillColor), path)); } else { image.Mutate(c => c.Fill(options, new SolidBrush(fillColor))); } var testOutputDetails = new { triggerFillRegion, newColorName, alpha, blenderMode, blendPercentage }; image.DebugSave( provider, testOutputDetails, appendPixelTypeToFileName: false, appendSourceFileOrDescription: false); PixelBlender <TPixel> blender = PixelOperations <TPixel> .Instance.GetPixelBlender( blenderMode, PixelAlphaCompositionMode.SrcOver); TPixel expectedPixel = blender.Blend(bgColor, fillColor.ToPixel <TPixel>(), blendPercentage); image.ComparePixelBufferTo(expectedPixel); } }
public DXT1Texture(int id, int width, int height, int levels, Endianness endianness, Stream stream) : base(id, width, height, levels, stream) { Endianness = endianness; Words = new UInt16Serializer(Endianness); Pixels = PixelOperations <RgbaVector> .Instance .GetPixelBlender(new GraphicsOptions()); }
/// <summary> /// Initializes a new instance of the <see cref="VignetteProcessor{TPixel}" /> class. /// </summary> /// <param name="color">The color of the vignette.</param> /// <param name="radiusX">The x-radius.</param> /// <param name="radiusY">The y-radius.</param> /// <param name="options">The options effecting blending and composition.</param> public VignetteProcessor(TPixel color, ValueSize radiusX, ValueSize radiusY, GraphicsOptions options) { this.VignetteColor = color; this.RadiusX = radiusX; this.RadiusY = radiusY; this.options = options; this.blender = PixelOperations <TPixel> .Instance.GetPixelBlender(this.options.BlenderMode); }
public static IPixelBlender GetBlender(PixelFormat backBuffer, Endianess backBufferEndianess, PixelFormat fronBuffer, Endianess frontBufferEndianes, PixelFormat output, Endianess outputEndianess) { var tuple = Tuple.Create(backBuffer, backBufferEndianess, fronBuffer, frontBufferEndianes, output, outputEndianess); if(!blendersCache.ContainsKey(tuple)) { blendersCache[tuple] = new PixelBlender(backBuffer, fronBuffer, output, GenerateBlendMethod(backBuffer, backBufferEndianess, fronBuffer, frontBufferEndianes, output, outputEndianess)); } return blendersCache[tuple]; }
public void TestAlphaCompositionModes(Rgba32 backdrop, Rgba32 source, float opacity, PixelAlphaCompositionMode mode, Rgba32 expectedResult) { PixelBlender <Rgba32> blender = PixelOperations <Rgba32> .Instance.GetPixelBlender(PixelColorBlendingMode.Normal, mode); Rgba32 actualResult = blender.Blend(backdrop, source, opacity); // var str = actualResult.Rgba.ToString("X8"); // used to extract expectedResults Assert.Equal(actualResult.ToVector4(), expectedResult.ToVector4()); }
public static IPixelBlender GetBlender(PixelFormat backBuffer, Endianess backBufferEndianess, PixelFormat fronBuffer, Endianess frontBufferEndianes, PixelFormat output, Endianess outputEndianess) { var tuple = Tuple.Create(backBuffer, backBufferEndianess, fronBuffer, frontBufferEndianes, output, outputEndianess); if (!blendersCache.ContainsKey(tuple)) { blendersCache[tuple] = new PixelBlender(backBuffer, fronBuffer, output, GenerateBlendMethod(backBuffer, backBufferEndianess, fronBuffer, frontBufferEndianes, output, outputEndianess)); } return(blendersCache[tuple]); }
/// <summary> /// Initializes a new instance of the <see cref="DrawImageProcessor{TPixel}"/> class. /// </summary> /// <param name="image">The image to blend with the currently processing image.</param> /// <param name="size">The size to draw the blended image.</param> /// <param name="location">The location to draw the blended image.</param> /// <param name="options">The opacity of the image to blend. Between 0 and 100.</param> public DrawImageProcessor(Image <TPixel> image, Size size, Point location, GraphicsOptions options) { Guard.MustBeBetweenOrEqualTo(options.BlendPercentage, 0, 1, nameof(options.BlendPercentage)); this.Image = image; this.Size = size; this.Alpha = options.BlendPercentage; this.blender = PixelOperations <TPixel> .Instance.GetPixelBlender(options.BlenderMode); this.Location = location; }
/// <inheritdoc/> protected override void OnFrameApply(ImageFrame <TPixel> source, Rectangle sourceRectangle, Configuration configuration) { int startY = sourceRectangle.Y; int endY = sourceRectangle.Bottom; int startX = sourceRectangle.X; int endX = sourceRectangle.Right; // Align start/end positions. int minX = Math.Max(0, startX); int maxX = Math.Min(source.Width, endX); int minY = Math.Max(0, startY); int maxY = Math.Min(source.Height, endY); // Reset offset if necessary. if (minX > 0) { startX = 0; } if (minY > 0) { startY = 0; } int width = maxX - minX; using (IBuffer <TPixel> colors = source.MemoryAllocator.Allocate <TPixel>(width)) using (IBuffer <float> amount = source.MemoryAllocator.Allocate <float>(width)) { // Be careful! Do not capture colorSpan & amountSpan in the lambda below! Span <TPixel> colorSpan = colors.GetSpan(); Span <float> amountSpan = amount.GetSpan(); // TODO: Use Span.Fill? for (int i = 0; i < width; i++) { colorSpan[i] = this.Color; amountSpan[i] = this.GraphicsOptions.BlendPercentage; } PixelBlender <TPixel> blender = PixelOperations <TPixel> .Instance.GetPixelBlender(this.GraphicsOptions.BlenderMode); Parallel.For( minY, maxY, configuration.ParallelOptions, y => { Span <TPixel> destination = source.GetPixelRowSpan(y - startY).Slice(minX - startX, width); // This switched color & destination in the 2nd and 3rd places because we are applying the target color under the current one blender.Blend(source.MemoryAllocator, destination, colors.GetSpan(), destination, amount.GetSpan()); }); } }
/// <inheritdoc/> protected override void OnApply(ImageBase <TPixel> source, Rectangle sourceRectangle) { int startY = sourceRectangle.Y; int endY = sourceRectangle.Bottom; int startX = sourceRectangle.X; int endX = sourceRectangle.Right; // Align start/end positions. int minX = Math.Max(0, startX); int maxX = Math.Min(source.Width, endX); int minY = Math.Max(0, startY); int maxY = Math.Min(source.Height, endY); // Reset offset if necessary. if (minX > 0) { startX = 0; } if (minY > 0) { startY = 0; } int width = maxX - minX; using (Buffer <TPixel> colors = new Buffer <TPixel>(width)) using (Buffer <float> amount = new Buffer <float>(width)) using (PixelAccessor <TPixel> sourcePixels = source.Lock()) { for (int i = 0; i < width; i++) { colors[i] = this.Value; amount[i] = this.options.BlendPercentage; } PixelBlender <TPixel> blender = PixelOperations <TPixel> .Instance.GetPixelBlender(this.options.BlenderMode); Parallel.For( minY, maxY, this.ParallelOptions, y => { int offsetY = y - startY; Span <TPixel> destination = sourcePixels.GetRowSpan(offsetY).Slice(minX - startX, width); // this switched color & destination in the 2nd and 3rd places because we are applying the target colour under the current one blender.Blend(destination, colors, destination, amount); }); } }
public RowIntervalOperation( ImageFrame <TPixelBg> sourceFrame, Image <TPixelFg> targetImage, PixelBlender <TPixelBg> blender, Configuration configuration, int width) { this.sourceFrame = sourceFrame; this.targetImage = targetImage; this.blender = blender; this.configuration = configuration; this.width = width; }
/// <inheritdoc/> protected override void OnFrameApply( ImageFrame <TPixelBg> source, Rectangle sourceRectangle, Configuration configuration) { Image <TPixelFg> targetImage = this.Image; PixelBlender <TPixelBg> blender = this.Blender; int locationY = this.Location.Y; // Align start/end positions. Rectangle bounds = targetImage.Bounds(); int minX = Math.Max(this.Location.X, sourceRectangle.X); int maxX = Math.Min(this.Location.X + bounds.Width, sourceRectangle.Right); int targetX = minX - this.Location.X; int minY = Math.Max(this.Location.Y, sourceRectangle.Y); int maxY = Math.Min(this.Location.Y + bounds.Height, sourceRectangle.Bottom); int width = maxX - minX; var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); // not a valid operation because rectangle does not overlap with this image. if (workingRect.Width <= 0 || workingRect.Height <= 0) { throw new ImageProcessingException( "Cannot draw image because the source image does not overlap the target image."); } ParallelHelper.IterateRows( workingRect, configuration, rows => { for (int y = rows.Min; y < rows.Max; y++) { Span <TPixelBg> background = source.GetPixelRowSpan(y).Slice(minX, width); Span <TPixelFg> foreground = targetImage.GetPixelRowSpan(y - locationY).Slice(targetX, width); blender.Blend <TPixelFg>(configuration, background, background, foreground, this.Opacity); } }); }
public RowOperation( Configuration configuration, Rectangle bounds, IMemoryOwner <TPixel> colors, PixelBlender <TPixel> blender, Vector2 center, float maxDistance, float blendPercent, ImageFrame <TPixel> source) { this.configuration = configuration; this.bounds = bounds; this.colors = colors; this.blender = blender; this.center = center; this.maxDistance = maxDistance; this.blendPercent = blendPercent; this.source = source; }
public RowOperation(ImageFrame <TPixelBg> sourceFrame, SixLabors.ImageSharp.Image <TPixelFg> targetImage, PixelBlender <TPixelBg> blender, Configuration configuration, int minX, int width, int locationY, int targetX, float interpolationValue) { this.sourceFrame = sourceFrame; this.targetImage = targetImage; this.blender = blender; this.configuration = configuration; this.minX = minX; this.width = width; this.locationY = locationY; this.targetX = targetX; this.interpolationValue = interpolationValue; }
public RowOperation( Buffer2D <TPixelBg> source, Buffer2D <TPixelFg> target, PixelBlender <TPixelBg> blender, Configuration configuration, int minX, int width, int locationY, int targetX, float opacity) { this.source = source; this.target = target; this.blender = blender; this.configuration = configuration; this.minX = minX; this.width = width; this.locationY = locationY; this.targetX = targetX; this.opacity = opacity; }
public RowOperation( ImageFrame <TPixelBg> sourceFrame, Image <TPixelFg> targetImage, PixelBlender <TPixelBg> blender, Configuration configuration, int minX, int width, int locationY, int targetX, float opacity) { this.sourceFrame = sourceFrame; this.targetImage = targetImage; this.blender = blender; this.configuration = configuration; this.minX = minX; this.width = width; this.locationY = locationY; this.targetX = targetX; this.opacity = opacity; }
/// <inheritdoc/> protected override void OnFrameApply(ImageFrame <TPixelBg> source) { Rectangle sourceRectangle = this.SourceRectangle; Configuration configuration = this.Configuration; Image <TPixelFg> targetImage = this.Image; PixelBlender <TPixelBg> blender = this.Blender; int locationY = this.Location.Y; // Align start/end positions. Rectangle bounds = targetImage.Bounds(); int minX = Math.Max(this.Location.X, sourceRectangle.X); int maxX = Math.Min(this.Location.X + bounds.Width, sourceRectangle.Right); int targetX = minX - this.Location.X; int minY = Math.Max(this.Location.Y, sourceRectangle.Y); int maxY = Math.Min(this.Location.Y + bounds.Height, sourceRectangle.Bottom); int width = maxX - minX; var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); // Not a valid operation because rectangle does not overlap with this image. if (workingRect.Width <= 0 || workingRect.Height <= 0) { throw new ImageProcessingException( "Cannot draw image because the source image does not overlap the target image."); } var operation = new RowOperation(source, targetImage, blender, configuration, minX, width, locationY, targetX, this.Opacity); ParallelRowIterator.IterateRows( configuration, workingRect, in operation); }
/// <inheritdoc/> protected override void OnApply(ImageFrame <TPixel> source, Rectangle sourceRectangle, Configuration configuration) { Image <TPixel> targetImage = this.Image; PixelBlender <TPixel> blender = this.Blender; int locationY = this.Location.Y; // Align start/end positions. Rectangle bounds = targetImage.Bounds(); int minX = Math.Max(this.Location.X, sourceRectangle.X); int maxX = Math.Min(this.Location.X + bounds.Width, sourceRectangle.Width); int targetX = minX - this.Location.X; int minY = Math.Max(this.Location.Y, sourceRectangle.Y); int maxY = Math.Min(this.Location.Y + bounds.Height, sourceRectangle.Bottom); int width = maxX - minX; using (var amount = new Buffer <float>(width)) { for (int i = 0; i < width; i++) { amount[i] = this.Opacity; } Parallel.For( minY, maxY, configuration.ParallelOptions, y => { Span <TPixel> background = source.GetPixelRowSpan(y).Slice(minX, width); Span <TPixel> foreground = targetImage.GetPixelRowSpan(y - locationY).Slice(targetX, width); blender.Blend(background, background, foreground, amount); }); } }
/// <inheritdoc/> protected override void OnFrameApply(ImageFrame <TPixel> source, Rectangle sourceRectangle, Configuration configuration) { Image <TPixel> targetImage = this.Image; PixelBlender <TPixel> blender = this.Blender; int locationY = this.Location.Y; // Align start/end positions. Rectangle bounds = targetImage.Bounds(); int minX = Math.Max(this.Location.X, sourceRectangle.X); int maxX = Math.Min(this.Location.X + bounds.Width, sourceRectangle.Width); int targetX = minX - this.Location.X; int minY = Math.Max(this.Location.Y, sourceRectangle.Y); int maxY = Math.Min(this.Location.Y + bounds.Height, sourceRectangle.Bottom); int width = maxX - minX; MemoryManager memoryManager = this.Image.GetConfiguration().MemoryManager; using (IBuffer <float> amount = memoryManager.Allocate <float>(width)) { amount.Span.Fill(this.Opacity); Parallel.For( minY, maxY, configuration.ParallelOptions, y => { Span <TPixel> background = source.GetPixelRowSpan(y).Slice(minX, width); Span <TPixel> foreground = targetImage.GetPixelRowSpan(y - locationY).Slice(targetX, width); blender.Blend(memoryManager, background, background, foreground, amount.Span); }); } }
/// <summary> /// Initializes a new instance of the <see cref="GlowProcessor{TPixel}"/> class. /// </summary> /// <param name="configuration">The configuration which allows altering default behaviour or extending the library.</param> /// <param name="definition">The <see cref="GlowProcessor"/> defining the processor parameters.</param> /// <param name="source">The source <see cref="Image{TPixel}"/> for the current processor instance.</param> /// <param name="sourceRectangle">The source area to process for the current processor instance.</param> public GlowProcessor(Configuration configuration, GlowProcessor definition, Image <TPixel> source, Rectangle sourceRectangle) : base(configuration, source, sourceRectangle) { this.definition = definition; this.blender = PixelOperations <TPixel> .Instance.GetPixelBlender(definition.GraphicsOptions); }
/// <summary> /// Initializes a new instance of the <see cref="VignetteProcessor{TPixel}"/> class. /// </summary> /// <param name="definition">The <see cref="VignetteProcessor"/> defining the processor parameters.</param> /// <param name="source">The source <see cref="Image{TPixel}"/> for the current processor instance.</param> /// <param name="sourceRectangle">The source area to process for the current processor instance.</param> public VignetteProcessor(VignetteProcessor definition, Image <TPixel> source, Rectangle sourceRectangle) : base(source, sourceRectangle) { this.definition = definition; this.blender = PixelOperations <TPixel> .Instance.GetPixelBlender(definition.GraphicsOptions); }
public GlowProcessor(GlowProcessor definition) { this.definition = definition; this.blender = PixelOperations <TPixel> .Instance.GetPixelBlender(definition.GraphicsOptions); }
/// <inheritdoc/> protected override void OnFrameApply(ImageFrame <TPixel> source) { TPixel color = this.definition.Color.ToPixel <TPixel>(); GraphicsOptions graphicsOptions = this.definition.GraphicsOptions; int startY = this.SourceRectangle.Y; int endY = this.SourceRectangle.Bottom; int startX = this.SourceRectangle.X; int endX = this.SourceRectangle.Right; // Align start/end positions. int minX = Math.Max(0, startX); int maxX = Math.Min(source.Width, endX); int minY = Math.Max(0, startY); int maxY = Math.Min(source.Height, endY); // Reset offset if necessary. if (minX > 0) { startX = 0; } if (minY > 0) { startY = 0; } int width = maxX - minX; var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); using (IMemoryOwner <TPixel> colors = source.MemoryAllocator.Allocate <TPixel>(width)) using (IMemoryOwner <float> amount = source.MemoryAllocator.Allocate <float>(width)) { // Be careful! Do not capture colorSpan & amountSpan in the lambda below! Span <TPixel> colorSpan = colors.GetSpan(); Span <float> amountSpan = amount.GetSpan(); colorSpan.Fill(color); amountSpan.Fill(graphicsOptions.BlendPercentage); PixelBlender <TPixel> blender = PixelOperations <TPixel> .Instance.GetPixelBlender(graphicsOptions); ParallelHelper.IterateRows( workingRect, this.Configuration, rows => { for (int y = rows.Min; y < rows.Max; y++) { Span <TPixel> destination = source.GetPixelRowSpan(y - startY).Slice(minX - startX, width); // This switched color & destination in the 2nd and 3rd places because we are applying the target color under the current one blender.Blend( source.Configuration, destination, colors.GetSpan(), destination, amount.GetSpan()); } }); } }