public override BitmapBase Apply(RenderTask renderTask, BitmapBase layer) { Tank tank = renderTask.Tank; layer.ScaleOpacity(Opacity, Style); return(layer); }
public override BitmapBase Apply(RenderTask renderTask, BitmapBase layer) { Tank tank = renderTask.Tank; using (var image = layer.ToMagickImage()) { image.BackgroundColor = MagickColors.Transparent; var channels = Channels.None; if (ChannelA) { channels = channels | Channels.Alpha; } if (ChannelR) { channels = channels | Channels.Red; } if (ChannelG) { channels = channels | Channels.Green; } if (ChannelB) { channels = channels | Channels.Blue; } image.FilterType = FilterType.Lanczos; image.SelectiveBlur(Radius, Sigma, Threshold, channels); layer.CopyPixelsFrom(image.ToBitmapSource()); return(layer); } }
public override BitmapBase Apply(Tank tank, BitmapBase layer) { if (FlipHorz) layer.FlipHorz(); if (FlipVert) layer.FlipVert(); return layer; }
public override BitmapBase Apply(Tank tank, BitmapBase layer) { if (ShiftX == 0 && ShiftY == 0) return layer; var result = new BitmapRam(layer.Width, layer.Height); result.DrawImage(layer, ShiftX, ShiftY); return result; }
public override BitmapBase Apply(RenderTask renderTask, BitmapBase layer) { Tank tank = renderTask.Tank; var color = ColorHSV.FromColor(Color.GetColorWpf(tank)); layer.Colorize(color.Hue, color.Saturation / 100.0, color.Value / 100.0 - 0.5, color.Alpha / 255.0); return(layer); }
public override BitmapBase Apply(Tank tank, BitmapBase layer) { if (_blur == null || _blur.Radius != Radius) lock (this) if (_blur == null || _blur.Radius != Radius) _blur = new GaussianBlur(Radius); layer.Blur(_blur, Edge); return layer; }
public override BitmapBase Apply(RenderTask renderTask, BitmapBase layer) { Tank tank = renderTask.Tank; if (ShiftX == 0 && ShiftY == 0) { return(layer); } var result = new BitmapRam(Math.Max(1, layer.Width + ShiftX), Math.Max(1, layer.Height + ShiftY)); result.DrawImage(layer, ShiftX, ShiftY); return(result); }
public override BitmapBase Apply(RenderTask renderTask, BitmapBase layer) { Tank tank = renderTask.Tank; if (Strength == 0) { return(layer); } int totalAlpha = 0; long totalBrightness = 0; using (layer.UseRead()) unsafe { for (int y = 0; y < layer.Height; y++) { byte *linePtr = layer.Data + y * layer.Stride; byte *lineEndPtr = linePtr + layer.Width * 4; while (linePtr < lineEndPtr) { int brightness = *(linePtr) * 722 + *(linePtr + 1) * 7152 + *(linePtr + 2) * 2126; totalBrightness += brightness * *(linePtr + 3); totalAlpha += *(linePtr + 3); linePtr += 4; } } } if (totalAlpha == 0) { return(layer); } using (var image = layer.ToMagickImage()) { var averageBrightness = (double)totalBrightness * 100.0 / (double)totalAlpha / 255.0 / 10000.0; image.BackgroundColor = MagickColors.Transparent; double strength = Strength / 100; double scaleValue = 1 + (Brightness / averageBrightness - 1) * strength; double scaleSaturation = Saturation == SaturationMode.Zero ? 0 : 1; if (Saturation == SaturationMode.Reduce && scaleValue < 1) { scaleSaturation = 1 - (1 - scaleValue * scaleValue) * strength; } image.Modulate(new Percentage(100 * scaleValue), new Percentage(100 * scaleSaturation), new Percentage(100)); layer.CopyPixelsFrom(image.ToBitmapSource()); return(layer); } }
public override BitmapBase Apply(RenderTask renderTask, BitmapBase layer) { Tank tank = renderTask.Tank; using (var image = layer.ToMagickImage()) { image.BackgroundColor = MagickColors.Transparent; image.FilterType = FilterType.Lanczos; image.AdaptiveBlur(Radius, Sigma); layer.CopyPixelsFrom(image.ToBitmapSource()); return(layer); } }
public override BitmapBase Apply(RenderTask renderTask, BitmapBase layer) { Tank tank = renderTask.Tank; if (FlipHorz) { layer.FlipHorz(); } if (FlipVert) { layer.FlipVert(); } return(layer); }
public override BitmapBase Apply(RenderTask renderTask, BitmapBase layer) { Tank tank = renderTask.Tank; if (_blur == null || _blur.Radius != Radius) { lock (this) if (_blur == null || _blur.Radius != Radius) { _blur = new GaussianBlur(Radius); } } layer.Blur(_blur, Edge); return(layer); }
public override BitmapBase Apply(RenderTask renderTask, BitmapBase layer) { Tank tank = renderTask.Tank; var outline = new BitmapRam(layer.Width, layer.Height); layer.GetOutline(outline, Color.GetColorWpf(tank), Threshold, Inside); if (KeepImage) { layer.DrawImage(outline); return(layer); } else { return(outline); } }
public unsafe override BitmapBase Apply(RenderTask renderTask, BitmapBase layer) { Tank tank = renderTask.Tank; var bounds = Mode == ClipMode.ByPixels ? layer.PreciseSize(PixelAlphaThreshold) : Mode == ClipMode.ByLayerBounds ? PixelRect.FromMixed(0, 0, layer.Width, layer.Height) : PixelRect.FromMixed(0, 0, Layer.ParentStyle.IconWidth, Layer.ParentStyle.IconHeight); using (layer.UseWrite()) { int count; byte *ptr; // Clip Top for (int y = 0; y < bounds.Top + ClipTop && y < layer.Height; y++) { Ut.MemSet(layer.Data + y * layer.Stride, 0, layer.Width * 4); } // Clip Bottom for (int y = layer.Height - 1; y > bounds.Bottom - ClipBottom && y >= 0; y--) { Ut.MemSet(layer.Data + y * layer.Stride, 0, layer.Width * 4); } // Clip Left count = Math.Min(bounds.Left + ClipLeft, layer.Width) * 4; ptr = layer.Data; if (count > 0) { for (int y = 0; y < layer.Height; y++, ptr += layer.Stride) { Ut.MemSet(ptr, 0, count); } } // Clip Right count = Math.Min(layer.Width - 1 - bounds.Right + ClipRight, layer.Width) * 4; ptr = layer.Data + layer.Width * 4 - count; if (count > 0) { for (int y = 0; y < layer.Height; y++, ptr += layer.Stride) { Ut.MemSet(ptr, 0, count); } } } return(layer); }
public override BitmapBase Apply(RenderTask renderTask, BitmapBase layer) { Tank tank = renderTask.Tank; if (Angle == 0) { return(layer); } using (var image = layer.ToMagickImage()) { image.BackgroundColor = MagickColors.Transparent; image.Distort(DistortMethod.ScaleRotateTranslate, new double[] { RotateX, RotateY, Angle }); layer.CopyPixelsFrom(image.ToBitmapSource()); return(layer); } }
public override BitmapBase Apply(RenderTask renderTask, BitmapBase layer) { Tank tank = renderTask.Tank; if (Hue == 0 && Saturation == 100 && Lightness == 100) { return(layer); } using (var image = layer.ToMagickImage()) { image.BackgroundColor = MagickColors.Transparent; image.Modulate(new Percentage(Lightness), new Percentage(Saturation), new Percentage(Hue * 100.0 / 180.0 + 100)); layer.CopyPixelsFrom(image.ToBitmapSource()); return(layer); } }
public override BitmapBase Apply(RenderTask renderTask, BitmapBase layer) { Tank tank = renderTask.Tank; if (Amplitude == 0) { return(layer); } using (var image = layer.ToMagickImage()) { image.BackgroundColor = MagickColors.Transparent; image.Wave(PixelInterpolateMethod.Bilinear, Amplitude, Length); layer.CopyPixelsFrom(image.ToBitmapSource()); return(layer); } }
public override BitmapBase Apply(RenderTask renderTask, BitmapBase layer) { Tank tank = renderTask.Tank; if (GammaRed == 1 && GammaGreen == 1 && GammaBlue == 1) { return(layer); } using (var image = layer.ToMagickImage()) { image.BackgroundColor = MagickColors.Transparent; image.GammaCorrect(GammaRed, Channels.Red); image.GammaCorrect(GammaGreen, Channels.Green); image.GammaCorrect(GammaBlue, Channels.Blue); //image.GammaCorrect(GammaRed, GammaGreen, GammaBlue); layer.CopyPixelsFrom(image.ToBitmapSource()); return(layer); } }
public override BitmapBase Apply(RenderTask renderTask, BitmapBase layer) { Tank tank = renderTask.Tank; if (Angle == 0) { return(layer); } var channels = Channels.None; if (ChannelA) { channels = channels | Channels.Alpha; } if (ChannelR) { channels = channels | Channels.Red; } if (ChannelG) { channels = channels | Channels.Green; } if (ChannelB) { channels = channels | Channels.Blue; } using (var image = layer.ToMagickImage()) { image.BackgroundColor = MagickColors.Transparent; image.FilterType = FilterType.Lanczos; image.RotationalBlur(Angle, channels); layer.CopyPixelsFrom(image.ToBitmapSource()); return(layer); } }
public override BitmapBase Apply(RenderTask renderTask, BitmapBase layer) { Tank tank = renderTask.Tank; if (_blur == null || _blur.Radius != Radius) { lock (this) if (_blur == null || _blur.Radius != Radius) { _blur = new GaussianBlur(Radius); } } BitmapBase shadow = layer.ToBitmapRam(); var color = Color.GetColorWpf(tank); shadow.ReplaceColor(color); shadow.Blur(_blur, BlurEdgeMode.Transparent); shadow.ScaleOpacity(Spread, OpacityStyle.Additive); shadow.Transparentize(color.A); layer.DrawImage(shadow, below: true); return(layer); }
public override BitmapBase Apply(RenderTask renderTask, BitmapBase layer) { Tank tank = renderTask.Tank; if (!(ChannelA || ChannelR || ChannelG || ChannelB)) { return(layer); } using (var image = layer.ToMagickImage()) { image.BackgroundColor = MagickColors.Transparent; var channels = Channels.None; if (ChannelA) { channels = channels | Channels.Alpha; } if (ChannelR) { channels = channels | Channels.Red; } if (ChannelG) { channels = channels | Channels.Green; } if (ChannelB) { channels = channels | Channels.Blue; } image.Negate(channels); layer.CopyPixelsFrom(image.ToBitmapSource()); return(layer); } }
public override BitmapBase Apply(RenderTask renderTask, BitmapBase layer) { Tank tank = renderTask.Tank; if (!(ChannelA || ChannelR || ChannelG || ChannelB) || (_Brightness == 0 && _Contrast == 0)) { return(layer); } using (var image = layer.ToMagickImage()) { image.BackgroundColor = MagickColors.Transparent; var channels = Channels.None; if (ChannelA) { channels = channels | Channels.Alpha; } if (ChannelR) { channels = channels | Channels.Red; } if (ChannelG) { channels = channels | Channels.Green; } if (ChannelB) { channels = channels | Channels.Blue; } image.BrightnessContrast(new Percentage(Brightness), new Percentage(Contrast), channels); layer.CopyPixelsFrom(image.ToBitmapSource()); return(layer); } }
public override BitmapBase Apply(RenderTask renderTask, BitmapBase layer) { Tank tank = renderTask.Tank; if (!(ChannelA || ChannelR || ChannelG || ChannelB) || (BlackPoint == 0 && WhitePoint == 255 && MidPoint == 1)) { return(layer); } using (var image = layer.ToMagickImage()) { image.BackgroundColor = MagickColors.Transparent; var channels = Channels.None; if (ChannelA) { channels = channels | Channels.Alpha; } if (ChannelR) { channels = channels | Channels.Red; } if (ChannelG) { channels = channels | Channels.Green; } if (ChannelB) { channels = channels | Channels.Blue; } image.Level(new Percentage(BlackPoint), new Percentage(WhitePoint), MidPoint, channels); layer.CopyPixelsFrom(image.ToBitmapSource()); return(layer); } }
public unsafe override BitmapBase Apply(RenderTask renderTask, BitmapBase layer) { Tank tank = renderTask.Tank; LayerBase maskLayer; if (string.IsNullOrEmpty(MaskLayerId)) { return(layer); } maskLayer = renderTask.Style.Layers.FirstOrDefault(x => x.Id == MaskLayerId); if (maskLayer == null) { throw new StyleUserError(App.Translation.EffectMaskLayer.ErrorInvalidId.Fmt(MaskLayerId)); } if (renderTask.IsLayerAlreadyReferenced(maskLayer)) { throw new StyleUserError(App.Translation.EffectMaskLayer.ErrorRecursiveLayerReference.Fmt(MaskLayerId)); } var maskImg = renderTask.RenderLayer(maskLayer); using (layer.UseWrite()) { using (maskImg.UseRead()) { for (int i = 0; i < layer.Width; ++i) { for (int j = 0; j < layer.Height; ++j) { decimal alpha = 0; if (i < maskImg.Width && j < maskImg.Height) { switch (MaskMode) { case Effects.MaskMode.Opacity: alpha = maskImg.Data[i * 4 + maskImg.Stride * j + 3]; break; case Effects.MaskMode.Grayscale: alpha = (maskImg.Data[i * 4 + maskImg.Stride * j] + maskImg.Data[i * 4 + maskImg.Stride * j + 1] + maskImg.Data[i * 4 + maskImg.Stride * j + 2] ) / 3; break; case Effects.MaskMode.Combined: alpha = (maskImg.Data[i * 4 + maskImg.Stride * j] + maskImg.Data[i * 4 + maskImg.Stride * j + 1] + maskImg.Data[i * 4 + maskImg.Stride * j + 2] ) / 3 * maskImg.Data[i * 4 + maskImg.Stride * j + 3] / 255m; break; } } if (Invert) { alpha = 255m - alpha; } var opacity = layer.Data[i * 4 + layer.Stride * j + 3] * (alpha / 255m); layer.Data[i * 4 + layer.Stride * j + 3] = (byte)opacity; } } } } return(layer); }
public override BitmapBase Apply(Tank tank, BitmapBase layer) { var color = ColorHSV.FromColor(Color.GetColorWpf(tank)); layer.Colorize(color.Hue, color.Saturation / 100.0, color.Value / 100.0 - 0.5, color.Alpha / 255.0); return layer; }
public override BitmapBase Apply(RenderTask renderTask, BitmapBase layer) { var calculator = new SizeCalculator(renderTask, layer); Func <string, string> describe = property => "*{0}:* {1}\n".Fmt(EggsML.Escape(App.Translation.Calculator.ErrLabel_Layer), EggsML.Escape((string.IsNullOrEmpty(Layer.Name) ? "" : (Layer.Name + " – ")) + Layer.TypeName)) + "*{0}:* {1}\n".Fmt(EggsML.Escape(App.Translation.Calculator.ErrLabel_Effect), EggsML.Escape((string.IsNullOrEmpty(Name) ? "" : (Name + " – ")) + TypeName)) + "*{0}:* {1}".Fmt(EggsML.Escape(App.Translation.Calculator.ErrLabel_Property), EggsML.Escape(property)); double ParsedWidth = Math.Max(0, calculator.Parse(Width, describe(WidthTr(App.Translation).DisplayName))), ParsedHeight = Math.Max(0, calculator.Parse(Height, describe(HeightTr(App.Translation).DisplayName))), ParsedX = calculator.Parse(X, describe(XTr(App.Translation).DisplayName)), ParsedY = calculator.Parse(Y, describe(YTr(App.Translation).DisplayName)); Tank tank = renderTask.Tank; var pixels = PixelRect.FromMixed(0, 0, layer.Width, layer.Height); if (ShowPixelBorders || PositionByPixels || (SizeByPixels && SizeMode2 != SizeMode2.NoChange && SizeMode2 != SizeMode2.ByPercentage)) { pixels = layer.PreciseSize(PixelAlphaThreshold); } bool emptyPixels = pixels.Width <= 0 || pixels.Height <= 0; if (emptyPixels) { pixels = PixelRect.FromMixed(0, 0, layer.Width, layer.Height); } double scaleWidth, scaleHeight; int sourceWidth = SizeByPixels ? pixels.Width : layer.Width; int sourceHeight = SizeByPixels ? pixels.Height : layer.Height; switch (SizeMode2) { case SizeMode2.NoChange: scaleWidth = scaleHeight = 1; break; case SizeMode2.ByPercentage: scaleWidth = scaleHeight = Percentage / 100.0; break; case SizeMode2.BySizeWidthOnly: scaleWidth = scaleHeight = ParsedWidth / (double)sourceWidth; break; case SizeMode2.BySizeHeightOnly: scaleWidth = scaleHeight = ParsedHeight / (double)sourceHeight; break; case SizeMode2.BySizeFit: scaleWidth = scaleHeight = Math.Min(ParsedWidth / (double)sourceWidth, ParsedHeight / (double)sourceHeight); break; case SizeMode2.BySizeStretch: scaleWidth = ParsedWidth / (double)sourceWidth; scaleHeight = ParsedHeight / (double)sourceHeight; break; default: throw new Exception("7924688"); } if (GrowShrinkMode == GrowShrinkMode.GrowOnly) { scaleWidth = Math.Max(1.0, scaleWidth); scaleHeight = Math.Max(1.0, scaleHeight); } else if (GrowShrinkMode == GrowShrinkMode.ShrinkOnly) { scaleWidth = Math.Min(1.0, scaleWidth); scaleHeight = Math.Min(1.0, scaleHeight); } var anchor = (AnchorRaw)Anchor; int anchorWidth = (int)Math.Ceiling((PositionByPixels ? pixels.Width : layer.Width) * scaleWidth); int anchorHeight = (int)Math.Ceiling((PositionByPixels ? pixels.Height : layer.Height) * scaleHeight); // Location of the top left corner of the anchored rectangle int tgtX = (int)ParsedX - (anchor.HasFlag(AnchorRaw.Right) ? anchorWidth - 1 : anchor.HasFlag(AnchorRaw.Center) ? (anchorWidth - 1) / 2 : 0); int tgtY = (int)ParsedY - (anchor.HasFlag(AnchorRaw.Bottom) ? anchorHeight - 1 : anchor.HasFlag(AnchorRaw.Mid) ? (anchorHeight - 1) / 2 : 0); // Location of the top left corner of the whole scaled layer image double x = tgtX - (PositionByPixels ? pixels.Left * scaleWidth : 0); double y = tgtY - (PositionByPixels ? pixels.Top * scaleHeight : 0); int offsetX = (PositionByPixels ? pixels.Left : 0); int offsetY = (PositionByPixels ? pixels.Top : 0); if (ShowLayerBorders || ShowPixelBorders) { using (var image = layer.ToMagickImage()) { image.Settings.StrokeWidth = 1; if (ShowLayerBorders) { image.Settings.FillColor = ImageMagick.MagickColors.Transparent; image.Settings.StrokeColor = new ImageMagick.MagickColor("aqua"); image.Draw(new ImageMagick.DrawableRectangle(0, 0, layer.Width - 1, layer.Height - 1)); } if (ShowPixelBorders && !emptyPixels) { image.Settings.FillColor = ImageMagick.MagickColors.Transparent; image.Settings.StrokeColor = new ImageMagick.MagickColor("red"); image.Draw(new ImageMagick.DrawableRectangle(pixels.Left, pixels.Top, pixels.Right, pixels.Bottom)); } layer.CopyPixelsFrom(image.ToBitmapSource()); } } BitmapResampler.Filter filter; switch (Filter) { case Filter.Auto: filter = null; break; case Filter.Mitchell: filter = new BitmapResampler.MitchellFilter(); break; case Filter.Bicubic: filter = new BitmapResampler.CatmullRomFilter(); break; case Filter.Lanczos: filter = new BitmapResampler.LanczosFilter(); break; case Filter.Sinc256: filter = new BitmapResampler.LanczosFilter(8); break; case Filter.Sinc1024: filter = new BitmapResampler.LanczosFilter(16); break; default: throw new Exception("SizePosEffect.Filter 4107"); } layer = BitmapResampler.SizePos(layer, scaleWidth, scaleHeight, offsetX, offsetY, tgtX, tgtY, Math.Max(layer.Width, Layer.ParentStyle.IconWidth), Math.Max(layer.Height, Layer.ParentStyle.IconHeight), filter); if (ShowAnchor) { using (var image = layer.ToMagickImage()) { image.Settings.StrokeWidth = 1; image.Settings.StrokeColor = new ImageMagick.MagickColor(255, 255, 0, 120); image.Draw(new ImageMagick.DrawableLine((int)ParsedX - 1, (int)ParsedY, (int)ParsedX + 1, (int)ParsedY)); image.Draw(new ImageMagick.DrawableLine((int)ParsedX, (int)ParsedY - 1, (int)ParsedX, (int)ParsedY + 1)); layer.CopyPixelsFrom(image.ToBitmapSource()); } } return(layer); }
public SizeCalculator(RenderTask renderTask, BitmapBase layer) : base() { _renderTask = renderTask; _layer = layer; }
public unsafe override BitmapBase Apply(Tank tank, BitmapBase layer) { var bounds = Mode == ClipMode.ByPixels ? layer.PreciseSize(PixelAlphaThreshold) : Mode == ClipMode.ByLayerBounds ? PixelRect.FromMixed(0, 0, layer.Width, layer.Height) : PixelRect.FromMixed(0, 0, Layer.ParentStyle.IconWidth, Layer.ParentStyle.IconHeight); using (layer.UseWrite()) { int count; byte* ptr; // Clip Top for (int y = 0; y < bounds.Top + ClipTop && y < layer.Height; y++) Ut.MemSet(layer.Data + y * layer.Stride, 0, layer.Width * 4); // Clip Bottom for (int y = layer.Height - 1; y > bounds.Bottom - ClipBottom && y >= 0; y--) Ut.MemSet(layer.Data + y * layer.Stride, 0, layer.Width * 4); // Clip Left count = Math.Min(bounds.Left + ClipLeft, layer.Width) * 4; ptr = layer.Data; if (count > 0) for (int y = 0; y < layer.Height; y++, ptr += layer.Stride) Ut.MemSet(ptr, 0, count); // Clip Right count = Math.Min(layer.Width - 1 - bounds.Right + ClipRight, layer.Width) * 4; ptr = layer.Data + layer.Width * 4 - count; if (count > 0) for (int y = 0; y < layer.Height; y++, ptr += layer.Stride) Ut.MemSet(ptr, 0, count); } return layer; }
public override BitmapBase Apply(Tank tank, BitmapBase layer) { layer.ScaleOpacity(Opacity, Style); return layer; }
public override BitmapBase Apply(Tank tank, BitmapBase layer) { var outline = new BitmapRam(layer.Width, layer.Height); layer.GetOutline(outline, Color.GetColorWpf(tank), Threshold, Inside); if (KeepImage) { layer.DrawImage(outline); return layer; } else return outline; }
public override BitmapBase Apply(Tank tank, BitmapBase layer) { if (_blur == null || _blur.Radius != Radius) lock (this) if (_blur == null || _blur.Radius != Radius) _blur = new GaussianBlur(Radius); BitmapBase shadow = layer.ToBitmapRam(); var color = Color.GetColorWpf(tank); shadow.ReplaceColor(color); shadow.Blur(_blur, BlurEdgeMode.Transparent); shadow.ScaleOpacity(Spread, OpacityStyle.Additive); shadow.Transparentize(color.A); layer.DrawImage(shadow, below: true); return layer; }
public override BitmapBase Apply(Tank tank, BitmapBase layer) { var pixels = PixelRect.FromMixed(0, 0, layer.Width, layer.Height); if (ShowPixelBorders || PositionByPixels || (SizeByPixels && SizeMode2 != SizeMode2.NoChange && SizeMode2 != SizeMode2.ByPercentage)) pixels = layer.PreciseSize(PixelAlphaThreshold); bool emptyPixels = pixels.Width <= 0 || pixels.Height <= 0; if (emptyPixels) pixels = PixelRect.FromMixed(0, 0, layer.Width, layer.Height); double scaleWidth, scaleHeight; int sourceWidth = SizeByPixels ? pixels.Width : layer.Width; int sourceHeight = SizeByPixels ? pixels.Height : layer.Height; switch (SizeMode2) { case SizeMode2.NoChange: scaleWidth = scaleHeight = 1; break; case SizeMode2.ByPercentage: scaleWidth = scaleHeight = Percentage / 100.0; break; case SizeMode2.BySizeWidthOnly: scaleWidth = scaleHeight = Width / (double) sourceWidth; break; case SizeMode2.BySizeHeightOnly: scaleWidth = scaleHeight = Height / (double) sourceHeight; break; case SizeMode2.BySizeFit: scaleWidth = scaleHeight = Math.Min(Width / (double) sourceWidth, Height / (double) sourceHeight); break; case SizeMode2.BySizeStretch: scaleWidth = Width / (double) sourceWidth; scaleHeight = Height / (double) sourceHeight; break; default: throw new Exception("7924688"); } if (GrowShrinkMode == GrowShrinkMode.GrowOnly) { scaleWidth = Math.Max(1.0, scaleWidth); scaleHeight = Math.Max(1.0, scaleHeight); } else if (GrowShrinkMode == GrowShrinkMode.ShrinkOnly) { scaleWidth = Math.Min(1.0, scaleWidth); scaleHeight = Math.Min(1.0, scaleHeight); } var anchor = (AnchorRaw) Anchor; int anchorWidth = (int) Math.Ceiling((PositionByPixels ? pixels.Width : layer.Width) * scaleWidth); int anchorHeight = (int) Math.Ceiling((PositionByPixels ? pixels.Height : layer.Height) * scaleHeight); // Location of the top left corner of the anchored rectangle int tgtX = X - (anchor.HasFlag(AnchorRaw.Right) ? anchorWidth - 1 : anchor.HasFlag(AnchorRaw.Center) ? (anchorWidth - 1) / 2 : 0); int tgtY = Y - (anchor.HasFlag(AnchorRaw.Bottom) ? anchorHeight - 1 : anchor.HasFlag(AnchorRaw.Mid) ? (anchorHeight - 1) / 2 : 0); // Location of the top left corner of the whole scaled layer image double x = tgtX - (PositionByPixels ? pixels.Left * scaleWidth : 0); double y = tgtY - (PositionByPixels ? pixels.Top * scaleHeight : 0); var src = layer.ToBitmapGdi(); if (ShowLayerBorders || ShowPixelBorders) using (var dc = System.Drawing.Graphics.FromImage(src.Bitmap)) { if (ShowLayerBorders) dc.DrawRectangle(System.Drawing.Pens.Aqua, 0, 0, layer.Width - 1, layer.Height - 1); if (ShowPixelBorders && !emptyPixels) dc.DrawRectangle(System.Drawing.Pens.Red, pixels.Left, pixels.Top, pixels.Width - 1, pixels.Height - 1); } #if true // Using GDI: sharp-ish downscaling, but imprecise boundaries var result = new BitmapGdi(Math.Max(layer.Width, Layer.ParentStyle.IconWidth), Math.Max(layer.Height, Layer.ParentStyle.IconHeight)); using (var dc = Graphics.FromImage(result.Bitmap)) { dc.InterpolationMode = InterpolationMode.HighQualityBicubic; dc.DrawImage(src.Bitmap, (float) x, (float) y, (float) (src.Width * scaleWidth), (float) (src.Height * scaleHeight)); if (ShowAnchor) using (var pen = new Pen(Color.FromArgb(120, Color.Yellow), 0)) { dc.DrawLine(pen, X - 1, Y, X + 1, Y); dc.DrawLine(pen, X, Y - 1, X, Y + 1); } } #else // Using WPF: precise boundaries but rather blurry downscaling var result = Ut.NewBitmapWpf(dc => { var img = src.ToBitmapWpf().UnderlyingImage; var group = new System.Windows.Media.DrawingGroup(); System.Windows.Media.RenderOptions.SetBitmapScalingMode(group, System.Windows.Media.BitmapScalingMode.Fant); group.Children.Add(new System.Windows.Media.ImageDrawing(img, new System.Windows.Rect(x, y, src.Width * scaleWidth, src.Height * scaleHeight))); dc.DrawDrawing(group); if (ShowTargetPosition) { var pen = new System.Windows.Media.Pen(new System.Windows.Media.SolidColorBrush(System.Windows.Media.Color.FromArgb(200, 255, 255, 0)), 1); dc.DrawLine(pen, new System.Windows.Point(X - 1 + 0.5, Y + 0.5), new System.Windows.Point(X + 1 + 0.5, Y + 0.5)); dc.DrawLine(pen, new System.Windows.Point(X + 0.5, Y - 1 + 0.5), new System.Windows.Point(X + 0.5, Y + 1 + 0.5)); } }, Math.Max(layer.Width, Layer.Style.IconWidth), Math.Max(layer.Height, Layer.Style.IconHeight)); #endif GC.KeepAlive(src); return result.ToBitmapRam(); }
public unsafe override BitmapBase Apply(Tank tank, BitmapBase layer) { using (layer.UseWrite()) { // Just scale the brightness and alpha channels so as to normalize the maximum value. // This is crude but gives good results; a better algorithm would try to fit the histogram // to a predefined standard by scaling non-linearly. double maxBrightness = -1; double maxAlpha = -1; for (int y = 0; y < layer.Height; y++) { byte* ptr = layer.Data + y * layer.Stride; byte* end = ptr + layer.Width * 4; while (ptr < end) { byte alpha = *(ptr + 3); if (alpha > 0) // there are a lot of non-black pixels in the fully-transparent regions { if (NormalizeBrightness) { double brightness = *(ptr + 0) * 0.0722 + *(ptr + 1) * 0.7152 + *(ptr + 2) * 0.2126; if (brightness > maxBrightness) maxBrightness = brightness; } if (NormalizeAlpha) { if (alpha > maxAlpha) maxAlpha = alpha; } } ptr += 4; } } double scaleBrightness = (double) MaxBrightness / maxBrightness; double scaleAlpha = (double) MaxAlpha / maxAlpha; for (int y = 0; y < layer.Height; y++) { byte* ptr = layer.Data + y * layer.Stride; byte* end = ptr + layer.Width * 4; while (ptr < end) { byte alpha = *(ptr + 3); if (alpha > 0) { if (NormalizeBrightness) { if (Grayscale) { double brightness = *(ptr + 0) * 0.0722 + *(ptr + 1) * 0.7152 + *(ptr + 2) * 0.2126; *(ptr + 0) = *(ptr + 1) = *(ptr + 2) = (byte) (brightness * scaleBrightness).ClipMax(255); } else { // TODO: the clipping here alters the hue. Ideally the color should be clipped without altering hue, by increasing brightness until white. *(ptr + 0) = (byte) (*(ptr + 0) * scaleBrightness).ClipMax(255); *(ptr + 1) = (byte) (*(ptr + 1) * scaleBrightness).ClipMax(255); *(ptr + 2) = (byte) (*(ptr + 2) * scaleBrightness).ClipMax(255); } } else if (Grayscale) { double brightness = *(ptr + 0) * 0.0722 + *(ptr + 1) * 0.7152 + *(ptr + 2) * 0.2126; *(ptr + 0) = *(ptr + 1) = *(ptr + 2) = (byte) brightness; } if (NormalizeAlpha) { *(ptr + 3) = (byte) (alpha * scaleAlpha); } } ptr += 4; } } } return layer; }
public unsafe override BitmapBase Apply(RenderTask renderTask, BitmapBase layer) { Tank tank = renderTask.Tank; using (layer.UseWrite()) { // Just scale the brightness and alpha channels so as to normalize the maximum value. // This is crude but gives good results; a better algorithm would try to fit the histogram // to a predefined standard by scaling non-linearly. double maxBrightness = -1; double maxAlpha = -1; for (int y = 0; y < layer.Height; y++) { byte *ptr = layer.Data + y * layer.Stride; byte *end = ptr + layer.Width * 4; while (ptr < end) { byte alpha = *(ptr + 3); if (alpha > 0) // there are a lot of non-black pixels in the fully-transparent regions { if (NormalizeBrightness) { double brightness = *(ptr + 0) * 0.0722 + *(ptr + 1) * 0.7152 + *(ptr + 2) * 0.2126; if (brightness > maxBrightness) { maxBrightness = brightness; } } if (NormalizeAlpha) { if (alpha > maxAlpha) { maxAlpha = alpha; } } } ptr += 4; } } double scaleBrightness = (double)MaxBrightness / maxBrightness; double scaleAlpha = (double)MaxAlpha / maxAlpha; for (int y = 0; y < layer.Height; y++) { byte *ptr = layer.Data + y * layer.Stride; byte *end = ptr + layer.Width * 4; while (ptr < end) { byte alpha = *(ptr + 3); if (alpha > 0) { if (NormalizeBrightness) { if (Grayscale) { double brightness = *(ptr + 0) * 0.0722 + *(ptr + 1) * 0.7152 + *(ptr + 2) * 0.2126; *(ptr + 0) = *(ptr + 1) = *(ptr + 2) = (byte)(brightness * scaleBrightness).ClipMax(255); } else { // TODO: the clipping here alters the hue. Ideally the color should be clipped without altering hue, by increasing brightness until white. *(ptr + 0) = (byte)(*(ptr + 0) * scaleBrightness).ClipMax(255); *(ptr + 1) = (byte)(*(ptr + 1) * scaleBrightness).ClipMax(255); *(ptr + 2) = (byte)(*(ptr + 2) * scaleBrightness).ClipMax(255); } } else if (Grayscale) { double brightness = *(ptr + 0) * 0.0722 + *(ptr + 1) * 0.7152 + *(ptr + 2) * 0.2126; *(ptr + 0) = *(ptr + 1) = *(ptr + 2) = (byte)brightness; } if (NormalizeAlpha) { *(ptr + 3) = (byte)(alpha * scaleAlpha); } } ptr += 4; } } } return(layer); }