public static Surface CreateThumbnail(Surface sourceSurface, PdnGraphicsPath maskPath, Rectangle bounds, int thumbSideLength) { Size thumbSize = Utility.ComputeThumbnailSize(bounds.Size, thumbSideLength); Surface thumb = new Surface(Math.Max(5, thumbSize.Width + 4), Math.Max(5, thumbSize.Height + 4)); thumb.Clear(ColorBgra.Transparent); thumb.Clear(new Rectangle(1, 1, thumb.Width - 2, thumb.Height - 2), ColorBgra.Black); Rectangle insetRect = new Rectangle(2, 2, thumb.Width - 4, thumb.Height - 4); Surface thumbInset = thumb.CreateWindow(insetRect); thumbInset.Clear(ColorBgra.Transparent); float scaleX = (float)thumbInset.Width / (float)bounds.Width; float scaleY = (float)thumbInset.Height / (float)bounds.Height; Matrix scaleMatrix = new Matrix(); scaleMatrix.Translate(-bounds.X, -bounds.Y, System.Drawing.Drawing2D.MatrixOrder.Append); scaleMatrix.Scale(scaleX, scaleY, System.Drawing.Drawing2D.MatrixOrder.Append); thumbInset.SuperSamplingFitSurface(sourceSurface); Surface maskInset = new Surface(thumbInset.Size); maskInset.Clear(ColorBgra.Black); using (RenderArgs maskInsetRA = new RenderArgs(maskInset)) { maskInsetRA.Graphics.SmoothingMode = SmoothingMode.AntiAlias; maskInsetRA.Graphics.Transform = scaleMatrix; maskInsetRA.Graphics.FillPath(Brushes.White, maskPath); maskInsetRA.Graphics.DrawPath(Pens.White, maskPath); } scaleMatrix.Dispose(); scaleMatrix = null; IntensityMaskOp maskOp = new IntensityMaskOp(); maskOp.Apply(maskInset, thumbInset, maskInset); UserBlendOps.NormalBlendOp normalOp = new UserBlendOps.NormalBlendOp(); thumbInset.ClearWithCheckboardPattern(); normalOp.Apply(thumbInset, thumbInset, maskInset); maskInset.Dispose(); maskInset = null; thumbInset.Dispose(); thumbInset = null; using (RenderArgs thumbRA = new RenderArgs(thumb)) { Utility.DrawDropShadow1px(thumbRA.Graphics, thumb.Bounds); } return(thumb); }
public GradientRenderer CreateGradientRenderer() { UserBlendOps.NormalBlendOp normalBlendOp = new UserBlendOps.NormalBlendOp(); switch (this.gradientType) { case GradientType.LinearClamped: return(new GradientRenderers.LinearClamped(this.alphaOnly, normalBlendOp)); case GradientType.LinearReflected: return(new GradientRenderers.LinearReflected(this.alphaOnly, normalBlendOp)); case GradientType.LinearDiamond: return(new GradientRenderers.LinearDiamond(this.alphaOnly, normalBlendOp)); case GradientType.Radial: return(new GradientRenderers.Radial(this.alphaOnly, normalBlendOp)); case GradientType.Conical: return(new GradientRenderers.Conical(this.alphaOnly, normalBlendOp)); default: throw new InvalidEnumArgumentException(); } }
private GradientRenderer CreateGradientRenderer() { var normalBlendOp = new UserBlendOps.NormalBlendOp(); bool alpha_only = SelectedGradientColorMode == GradientColorMode.Transparency; switch (SelectedGradientType) { case GradientType.Linear: return(new GradientRenderers.LinearClamped(alpha_only, normalBlendOp)); case GradientType.LinearReflected: return(new GradientRenderers.LinearReflected(alpha_only, normalBlendOp)); case GradientType.Radial: return(new GradientRenderers.Radial(alpha_only, normalBlendOp)); case GradientType.Diamond: return(new GradientRenderers.LinearDiamond(alpha_only, normalBlendOp)); case GradientType.Conical: return(new GradientRenderers.Conical(alpha_only, normalBlendOp)); } throw new ArgumentOutOfRangeException("Unknown gradient type."); }
private SavableBitDepths GetBitDepth(Surface scratchSurface, Rectangle bounds) { bool allOpaque; bool all0or255Alpha; int uniqueColorCount; Analyze(scratchSurface, bounds, out allOpaque, out all0or255Alpha, out uniqueColorCount); SavableBitDepths bitDepth = SavableBitDepths.Rgba32; if (allOpaque) { bitDepth = SavableBitDepths.Rgb24; if (uniqueColorCount <= 256) { bitDepth = SavableBitDepths.Rgb8; } } else if (all0or255Alpha && uniqueColorCount < 256) { bitDepth = SavableBitDepths.Rgba8; } // if bit depth is 24 or 8, then we have to do away with the alpha channel // for 8-bit, we must have pixels that have either 0 or 255 alpha if (bitDepth == SavableBitDepths.Rgb8 || bitDepth == SavableBitDepths.Rgba8 || bitDepth == SavableBitDepths.Rgb24) { UserBlendOps.NormalBlendOp blendOp = new UserBlendOps.NormalBlendOp(); unsafe { for (int y = bounds.Top; y < bounds.Bottom; ++y) { ColorBgra *srcPtr = scratchSurface.GetPointAddressUnchecked(bounds.Left, y); ColorBgra *endPtr = srcPtr + bounds.Width; while (srcPtr < endPtr) { if (srcPtr->A < 128 && bitDepth == SavableBitDepths.Rgba8) { *srcPtr = ColorBgra.FromBgra(0, 0, 0, 0); } else { *srcPtr = blendOp.Apply(ColorBgra.White, *srcPtr); } srcPtr++; } } } } return(bitDepth); }
private GradientRenderer CreateGradientRenderer() { var op = new UserBlendOps.NormalBlendOp(); return(SelectedGradientType switch { GradientType.Linear => new GradientRenderers.LinearClamped(false, op), GradientType.LinearReflected => new GradientRenderers.LinearReflected(false, op), GradientType.Radial => new GradientRenderers.Radial(false, op), GradientType.Diamond => new GradientRenderers.LinearDiamond(false, op), GradientType.Conical => new GradientRenderers.Conical(false, op), _ => throw new ArgumentOutOfRangeException("Unknown gradient type."), });
public override Surface RenderThumbnail(int maxEdgeLength) { Size thumbSize = Utility.ComputeThumbnailSize(this.Size, maxEdgeLength); Surface thumb = new Surface(thumbSize); thumb.SuperSamplingFitSurface(this.surface); Surface thumb2 = new Surface(thumbSize); thumb2.ClearWithCheckboardPattern(); UserBlendOps.NormalBlendOp nbop = new UserBlendOps.NormalBlendOp(); nbop.Apply(thumb2, thumb); thumb.Dispose(); thumb = null; return(thumb2); }
protected override void InitDialogFromToken(EffectConfigToken effectToken) { base.InitDialogFromToken(effectToken); UserBlendOp setOp = ((CloudsEffectConfigToken)effectToken).BlendOp; if (setOp == null) { setOp = new UserBlendOps.NormalBlendOp(); } foreach (object op in this.comboBlendModes.Items) { if (0 == string.Compare(op.ToString(), setOp.ToString(), StringComparison.CurrentCultureIgnoreCase)) { this.comboBlendModes.SelectedItem = op; break; } } }
private unsafe Bitmap reduceToPalette(Surface surface, byte ditheringLevel, byte threshold, ProgressEventHandler progressCallback) { BinaryPixelOp blendOp = new UserBlendOps.NormalBlendOp(); for (int y = 0; y < surface.Height; y++) { ColorBgra *ptr = surface.GetRowAddressUnchecked(y); for (int x = 0; x < surface.Width; x++) { if (ptr->A < threshold) { ptr->Bgra = 0x00000000; } else { ptr->Bgra = blendOp.Apply(ColorBgra.White, *ptr).Bgra; } ptr++; } } int ColorCount = 256; //Search for transparent pixel and add it (do this because if there is no transparent pixel, quantize with -1 color) for (int x = 0; x < surface.Width; x++) { for (int y = 0; y < surface.Height; y++) { Color color = surface.GetPoint(x, y); if (color.A == 0) { goto TransparentColorFound; } } } ColorCount = 255; TransparentColorFound: return(Quantize(surface, ditheringLevel, ColorCount, true, progressCallback)); }
public static Surface CreateThumbnail(Surface sourceSurface, PdnGraphicsPath maskPath, Rectangle bounds, int thumbSideLength) { Size thumbSize = Utility.ComputeThumbnailSize(bounds.Size, thumbSideLength); Surface thumb = new Surface(Math.Max(5, thumbSize.Width + 4), Math.Max(5, thumbSize.Height + 4)); thumb.Clear(ColorBgra.Transparent); thumb.Clear(new Rectangle(1, 1, thumb.Width - 2, thumb.Height - 2), ColorBgra.Black); Rectangle insetRect = new Rectangle(2, 2, thumb.Width - 4, thumb.Height - 4); Surface thumbInset = thumb.CreateWindow(insetRect); thumbInset.Clear(ColorBgra.Transparent); float scaleX = (float)thumbInset.Width / (float)bounds.Width; float scaleY = (float)thumbInset.Height / (float)bounds.Height; Matrix scaleMatrix = new Matrix(); scaleMatrix.Translate(-bounds.X, -bounds.Y, System.Drawing.Drawing2D.MatrixOrder.Append); scaleMatrix.Scale(scaleX, scaleY, System.Drawing.Drawing2D.MatrixOrder.Append); thumbInset.SuperSamplingFitSurface(sourceSurface); Surface maskInset = new Surface(thumbInset.Size); maskInset.Clear(ColorBgra.Black); using (RenderArgs maskInsetRA = new RenderArgs(maskInset)) { maskInsetRA.Graphics.SmoothingMode = SmoothingMode.AntiAlias; maskInsetRA.Graphics.Transform = scaleMatrix; maskInsetRA.Graphics.FillPath(Brushes.White, maskPath); maskInsetRA.Graphics.DrawPath(Pens.White, maskPath); } scaleMatrix.Dispose(); scaleMatrix = null; IntensityMaskOp maskOp = new IntensityMaskOp(); maskOp.Apply(maskInset, thumbInset, maskInset); UserBlendOps.NormalBlendOp normalOp = new UserBlendOps.NormalBlendOp(); thumbInset.ClearWithCheckboardPattern(); normalOp.Apply(thumbInset, thumbInset, maskInset); maskInset.Dispose(); maskInset = null; thumbInset.Dispose(); thumbInset = null; using (RenderArgs thumbRA = new RenderArgs(thumb)) { Utility.DrawDropShadow1px(thumbRA.Graphics, thumb.Bounds); } return thumb; }
protected unsafe override sealed void OnSaveT( Document input, Stream output, PropertyBasedSaveConfigToken token, Surface scratchSurface, ProgressEventHandler progressCallback) { // flatten the document -- render w/ transparent background scratchSurface.Clear(ColorBgra.Transparent); using (RenderArgs ra = new RenderArgs(scratchSurface)) { input.Render(ra, false); } // load properties from token int thresholdFromToken = GetThresholdFromToken(token); int ditherLevel = GetDitherLevelFromToken(token); Set <SavableBitDepths> allowedBitDepths = CreateAllowedBitDepthListFromToken(token); if (allowedBitDepths.Count == 0) { throw new ArgumentException("there must be at least 1 element returned from CreateAllowedBitDepthListFromToken()"); } // allowedBitDepths.Count >= 1 // set to 1 unless allowedBitDepths contains only Rgb8 and Rgba8 int threshold; if (allowedBitDepths.IsSubsetOf(Set.Create(SavableBitDepths.Rgb8, SavableBitDepths.Rgba8))) { threshold = thresholdFromToken; } else { threshold = 1; } // Analyze image, try to detect what bit-depth or whatever to use, based on allowedBitDepths bool allOpaque; bool all0or255Alpha; int uniqueColorCount; Analyze(scratchSurface, out allOpaque, out all0or255Alpha, out uniqueColorCount); Set <SavableBitDepths> losslessBitDepths = new Set <SavableBitDepths>(); losslessBitDepths.Add(SavableBitDepths.Rgba32); if (allOpaque) { losslessBitDepths.Add(SavableBitDepths.Rgb24); if (uniqueColorCount <= 256) { losslessBitDepths.Add(SavableBitDepths.Rgb8); } } else if (all0or255Alpha && uniqueColorCount < 256) { losslessBitDepths.Add(SavableBitDepths.Rgba8); } SavableBitDepths bitDepth = ChooseBitDepth(allowedBitDepths, losslessBitDepths, allOpaque, all0or255Alpha, uniqueColorCount); if (bitDepth == SavableBitDepths.Rgba8 && threshold == 0 && allowedBitDepths.Contains(SavableBitDepths.Rgba8) && allowedBitDepths.Contains(SavableBitDepths.Rgb8)) { // threshold of 0 should effectively force full 256 color palette, instead of 255+1 transparent bitDepth = SavableBitDepths.Rgb8; } // if bit depth is 24 or 8, then we have to do away with the alpha channel // for 8-bit, we must have pixels that have either 0 or 255 alpha if (bitDepth == SavableBitDepths.Rgb8 || bitDepth == SavableBitDepths.Rgba8 || bitDepth == SavableBitDepths.Rgb24) { UserBlendOps.NormalBlendOp blendOp = new UserBlendOps.NormalBlendOp(); for (int y = 0; y < scratchSurface.Height; ++y) { for (int x = 0; x < scratchSurface.Width; ++x) { ColorBgra p = scratchSurface[x, y]; if (p.A < threshold && bitDepth == SavableBitDepths.Rgba8) { p = ColorBgra.FromBgra(0, 0, 0, 0); } else { p = blendOp.Apply(ColorBgra.White, p); } scratchSurface[x, y] = p; } } } Tracing.Ping("Chose " + bitDepth + ", ditherLevel=" + ditherLevel + ", threshold=" + threshold); // finally, do the save. FinalSave(input, output, scratchSurface, ditherLevel, bitDepth, token, progressCallback); }