public unsafe void Render(Surface surface, Rectangle[] rois, int startIndex, int length) { byte startAlpha; byte endAlpha; if (this.alphaOnly) { ComputeAlphaOnlyValuesFromColors(this.startColor, this.endColor, out startAlpha, out endAlpha); } else { startAlpha = this.startColor.A; endAlpha = this.endColor.A; } for (int ri = startIndex; ri < startIndex + length; ++ri) { Rectangle rect = rois[ri]; if (this.startPoint.Equals(this.endPoint)) { // Start and End point are the same ... fill with solid color. for (int y = rect.Top; y < rect.Bottom; ++y) { ColorBgra *pixelPtr = surface.GetPointAddress(rect.Left, y); for (int x = rect.Left; x < rect.Right; ++x) { ColorBgra result; if (this.alphaOnly && this.alphaBlending) { byte resultAlpha = (byte)PixelUtils.FastDivideShortByByte((ushort)(pixelPtr->A * endAlpha), 255); result = *pixelPtr; result.A = resultAlpha; } else if (this.alphaOnly && !this.alphaBlending) { result = *pixelPtr; result.A = endAlpha; } else if (!this.alphaOnly && this.alphaBlending) { result = this.normalBlendOp.Apply(*pixelPtr, this.endColor); } else //if (!this.alphaOnly && !this.alphaBlending) { result = this.endColor; } *pixelPtr = result; ++pixelPtr; } } } else { for (int y = rect.Top; y < rect.Bottom; ++y) { ColorBgra *pixelPtr = surface.GetPointAddress(rect.Left, y); if (this.alphaOnly && this.alphaBlending) { for (int x = rect.Left; x < rect.Right; ++x) { float lerpUnbounded = ComputeUnboundedLerp(x, y); float lerpBounded = BoundLerp(lerpUnbounded); byte lerpByte = (byte)(lerpBounded * 255.0f); byte lerpAlpha = this.lerpAlphas[lerpByte]; byte resultAlpha = PixelUtils.FastScaleByteByByte(pixelPtr->A, lerpAlpha); pixelPtr->A = resultAlpha; ++pixelPtr; } } else if (this.alphaOnly && !this.alphaBlending) { for (int x = rect.Left; x < rect.Right; ++x) { float lerpUnbounded = ComputeUnboundedLerp(x, y); float lerpBounded = BoundLerp(lerpUnbounded); byte lerpByte = (byte)(lerpBounded * 255.0f); byte lerpAlpha = this.lerpAlphas[lerpByte]; pixelPtr->A = lerpAlpha; ++pixelPtr; } } else if (!this.alphaOnly && (this.alphaBlending && (startAlpha != 255 || endAlpha != 255))) { // If we're doing all color channels, and we're doing alpha blending, and if alpha blending is necessary for (int x = rect.Left; x < rect.Right; ++x) { float lerpUnbounded = ComputeUnboundedLerp(x, y); float lerpBounded = BoundLerp(lerpUnbounded); byte lerpByte = (byte)(lerpBounded * 255.0f); ColorBgra lerpColor = this.lerpColors[lerpByte]; ColorBgra result = this.normalBlendOp.Apply(*pixelPtr, lerpColor); * pixelPtr = result; ++pixelPtr; } } else //if (!this.alphaOnly && !this.alphaBlending) // or sC.A == 255 && eC.A == 255 { for (int x = rect.Left; x < rect.Right; ++x) { float lerpUnbounded = ComputeUnboundedLerp(x, y); float lerpBounded = BoundLerp(lerpUnbounded); byte lerpByte = (byte)(lerpBounded * 255.0f); ColorBgra lerpColor = this.lerpColors[lerpByte]; * pixelPtr = lerpColor; ++pixelPtr; } } } } } AfterRender(); }
private static void ComputeAlphaOnlyValuesFromColors(ColorBgra startColor, ColorBgra endColor, out byte startAlpha, out byte endAlpha) { startAlpha = startColor.A; endAlpha = (byte)(255 - endColor.A); }
public abstract ColorBgra Apply(ColorBgra color);
public void SetFromLeveledHistogram(HistogramRgb inputHistogram, UnaryPixelOps.Level upo) { if (inputHistogram == null || upo == null) { return; } Clear(); float[] before = new float[3]; float[] slopes = new float[3]; for (int c = 0; c < 3; c++) { long[] channelHistogramOutput = histogram[c]; long[] channelHistogramInput = inputHistogram.histogram[c]; for (int v = 0; v <= 255; v++) { ColorBgra after = ColorBgra.FromBgr((byte)v, (byte)v, (byte)v); upo.UnApply(after, before, slopes); if (after[c] > upo.ColorOutHigh[c] || after[c] < upo.ColorOutLow[c] || (int)Math.Floor(before[c]) < 0 || (int)Math.Ceiling(before[c]) > 255 || float.IsNaN(before[c])) { channelHistogramOutput[v] = 0; } else if (before[c] <= upo.ColorInLow[c]) { channelHistogramOutput[v] = 0; for (int i = 0; i <= upo.ColorInLow[c]; i++) { channelHistogramOutput[v] += channelHistogramInput[i]; } } else if (before[c] >= upo.ColorInHigh[c]) { channelHistogramOutput[v] = 0; for (int i = upo.ColorInHigh[c]; i < 256; i++) { channelHistogramOutput[v] += channelHistogramInput[i]; } } else { channelHistogramOutput[v] = (int)(slopes[c] * PixelUtils.Lerp( channelHistogramInput[(int)Math.Floor(before[c])], channelHistogramInput[(int)Math.Ceiling(before[c])], before[c] - Math.Floor(before[c]))); } } } OnHistogramUpdated(); }
public override ColorBgra GetPercentileColor(float fraction) { int[] perc = GetPercentile(fraction); return(ColorBgra.FromBgr((byte)(perc[0]), (byte)(perc[1]), (byte)(perc[2]))); }
public override ColorBgra GetMeanColor() { float[] mean = GetMean(); return(ColorBgra.FromBgr((byte)(mean[0] + 0.5f), (byte)(mean[1] + 0.5f), (byte)(mean[2] + 0.5f))); }