private void DrawGradient(Graphics g) { g.PixelOffsetMode = PixelOffsetMode.Half; Rectangle gradientRect; float gradientAngle; switch (this.orientation) { case Orientation.Horizontal: gradientAngle = 180.0f; break; case Orientation.Vertical: gradientAngle = 90.0f; break; default: throw new InvalidEnumArgumentException(); } // draw gradient gradientRect = ClientRectangle; switch (this.orientation) { case Orientation.Horizontal: gradientRect.Inflate(-triangleHalfLength, -triangleSize + 3); break; case Orientation.Vertical: gradientRect.Inflate(-triangleSize + 3, -triangleHalfLength); break; default: throw new InvalidEnumArgumentException(); } if (this.customGradient != null && gradientRect.Width > 1 && gradientRect.Height > 1) { Surface gradientSurface = new Surface(gradientRect.Width, gradientRect.Height); using (RenderArgs ra = new RenderArgs(gradientSurface)) { Utility.DrawColorRectangle(ra.Graphics, ra.Bounds, Color.Transparent, false); if (Orientation == Orientation.Horizontal) { for (int x = 0; x < gradientSurface.Width; ++x) { // TODO: refactor, double buffer, save this computation in a bitmap somewhere double index = (double)(x * (this.customGradient.Length - 1)) / (double)(gradientSurface.Width - 1); int indexL = (int)Math.Floor(index); double t = 1.0 - (index - indexL); int indexR = (int)Math.Min(this.customGradient.Length - 1, Math.Ceiling(index)); Color colorL = this.customGradient[indexL]; Color colorR = this.customGradient[indexR]; double a1 = colorL.A / 255.0; double r1 = colorL.R / 255.0; double g1 = colorL.G / 255.0; double b1 = colorL.B / 255.0; double a2 = colorR.A / 255.0; double r2 = colorR.R / 255.0; double g2 = colorR.G / 255.0; double b2 = colorR.B / 255.0; double at = (t * a1) + ((1.0 - t) * a2); double rt; double gt; double bt; if (at == 0) { rt = 0; gt = 0; bt = 0; } else { rt = ((t * a1 * r1) + ((1.0 - t) * a2 * r2)) / at; gt = ((t * a1 * g1) + ((1.0 - t) * a2 * g2)) / at; bt = ((t * a1 * b1) + ((1.0 - t) * a2 * b2)) / at; } int ap = Utility.Clamp((int)Math.Round(at * 255.0), 0, 255); int rp = Utility.Clamp((int)Math.Round(rt * 255.0), 0, 255); int gp = Utility.Clamp((int)Math.Round(gt * 255.0), 0, 255); int bp = Utility.Clamp((int)Math.Round(bt * 255.0), 0, 255); for (int y = 0; y < gradientSurface.Height; ++y) { ColorBgra src = gradientSurface[x, y]; // we are assuming that src.A = 255 int rd = ((rp * ap) + (src.R * (255 - ap))) / 255; int gd = ((gp * ap) + (src.G * (255 - ap))) / 255; int bd = ((bp * ap) + (src.B * (255 - ap))) / 255; // TODO: proper alpha blending! gradientSurface[x, y] = ColorBgra.FromBgra((byte)bd, (byte)gd, (byte)rd, 255); } } g.DrawImage(ra.Bitmap, gradientRect, ra.Bounds, GraphicsUnit.Pixel); } else if (Orientation == Orientation.Vertical) { // TODO } else { throw new InvalidEnumArgumentException(); } } gradientSurface.Dispose(); } else { using (LinearGradientBrush lgb = new LinearGradientBrush(this.ClientRectangle, maxColor, minColor, gradientAngle, false)) { g.FillRectangle(lgb, gradientRect); } } // fill background using (Region nonGradientRegion = new Region()) { nonGradientRegion.MakeInfinite(); nonGradientRegion.Exclude(gradientRect); using (SolidBrush sb = new SolidBrush(this.BackColor)) { g.FillRegion(sb, nonGradientRegion); } } // draw value triangles for (int i = 0; i < this.vals.Length; i++) { int pos = ValueToPosition(vals[i]); Brush brush; Pen pen; if (i == highlight) { brush = Brushes.Blue; pen = (Pen)Pens.White.Clone(); } else { brush = Brushes.Black; pen = (Pen)Pens.Gray.Clone(); } g.SmoothingMode = SmoothingMode.AntiAlias; Point a1; Point b1; Point c1; Point a2; Point b2; Point c2; switch (this.orientation) { case Orientation.Horizontal: a1 = new Point(pos - triangleHalfLength, 0); b1 = new Point(pos, triangleSize - 1); c1 = new Point(pos + triangleHalfLength, 0); a2 = new Point(a1.X, Height - 1 - a1.Y); b2 = new Point(b1.X, Height - 1 - b1.Y); c2 = new Point(c1.X, Height - 1 - c1.Y); break; case Orientation.Vertical: a1 = new Point(0, pos - triangleHalfLength); b1 = new Point(triangleSize - 1, pos); c1 = new Point(0, pos + triangleHalfLength); a2 = new Point(Width - 1 - a1.X, a1.Y); b2 = new Point(Width - 1 - b1.X, b1.Y); c2 = new Point(Width - 1 - c1.X, c1.Y); break; default: throw new InvalidEnumArgumentException(); } if (this.drawNearNub) { g.FillPolygon(brush, new Point[] { a1, b1, c1, a1 }); } if (this.drawFarNub) { g.FillPolygon(brush, new Point[] { a2, b2, c2, a2 }); } if (pen != null) { if (this.drawNearNub) { g.DrawPolygon(pen, new Point[] { a1, b1, c1, a1 }); } if (this.drawFarNub) { g.DrawPolygon(pen, new Point[] { a2, b2, c2, a2 }); } pen.Dispose(); } } }
public override ColorBgra Apply(ColorBgra color) { return(ColorBgra.FromBgra(CurveB[color.B], CurveG[color.G], CurveR[color.R], color.A)); }
public override void Render(Surface src, Surface dest, Rectangle[] rois, int startIndex, int length) { unsafe { int w = dest.Width; int h = dest.Height; double invH = 1.0 / h; double invZoom = 1.0 / _zoom; double invQuality = 1.0 / _quality; double aspect = (double)h / (double)w; int count = _quality * _quality + 1; double invCount = 1.0 / (double)count; for (int ri = startIndex; ri < startIndex + length; ++ri) { Rectangle rect = rois[ri]; for (int y = rect.Top; y < rect.Bottom; y++) { ColorBgra *dstPtr = dest.GetPointAddressUnchecked(rect.Left, y); for (int x = rect.Left; x < rect.Right; x++) { int r = 0; int g = 0; int b = 0; int a = 0; for (double i = 0; i < count; i++) { double u = (2.0 * x - w + (i * invCount)) * invH; double v = (2.0 * y - h + ((i * invQuality) % 1)) * invH; double radius = Math.Sqrt((u * u) + (v * v)); double radiusP = radius; double theta = Math.Atan2(v, u); double thetaP = theta + _angleTheta; double uP = radiusP * Math.Cos(thetaP); double vP = radiusP * Math.Sin(thetaP); double jX = (uP - vP * aspect) * invZoom; double jY = (vP + uP * aspect) * invZoom; double j = Julia(jX, jY, JR, JI); double c = _factor * j; b += PixelUtils.ClampToByte(c - 768); g += PixelUtils.ClampToByte(c - 512); r += PixelUtils.ClampToByte(c - 256); a += PixelUtils.ClampToByte(c - 0); } *dstPtr = ColorBgra.FromBgra( PixelUtils.ClampToByte(b / count), PixelUtils.ClampToByte(g / count), PixelUtils.ClampToByte(r / count), PixelUtils.ClampToByte(a / count)); ++dstPtr; } } } } }
public override ColorBgra Apply(ColorBgra lhs, ColorBgra rhs) { byte intensityByte = rhs.GetIntensityByte(); return(ColorBgra.FromBgra(lhs.B, lhs.G, lhs.R, ByteUtil.FastScale(intensityByte, lhs.A))); }
public override ColorBgra Apply(ColorBgra color) { return(ColorBgra.FromBgra(color.B, color.G, color.R, Curve[color.A])); }
public override ColorBgra Apply(ColorBgra color) { return(ColorBgra.FromBgra(blueLevels[color.B], greenLevels[color.G], redLevels[color.R], color.A)); }
public unsafe override void Render(ImageSurface src, ImageSurface dest, Gdk.Rectangle[] rois) { // Glow backgound glowEffect.Data.Radius = 6; glowEffect.Data.Brightness = -(Data.Coloring - 50) * 2; glowEffect.Data.Contrast = -(Data.Coloring - 50) * 2; this.glowEffect.Render(src, dest, rois); // Create black outlines by finding the edges of objects foreach (Gdk.Rectangle roi in rois) { for (int y = roi.Top; y < roi.Bottom; ++y) { int top = y - radius; int bottom = y + radius + 1; if (top < 0) { top = 0; } if (bottom > dest.Height) { bottom = dest.Height; } ColorBgra *srcPtr = src.GetPointAddress(roi.X, y); ColorBgra *dstPtr = dest.GetPointAddress(roi.X, y); for (int x = roi.Left; x < roi.Right; ++x) { int left = x - radius; int right = x + radius + 1; if (left < 0) { left = 0; } if (right > dest.Width) { right = dest.Width; } int r = 0; int g = 0; int b = 0; int src_width = src.Width; ColorBgra *src_dataptr = (ColorBgra *)src.DataPtr; for (int v = top; v < bottom; v++) { ColorBgra *pRow = src.GetRowAddressUnchecked(src_dataptr, src_width, v); int j = v - y + radius; for (int u = left; u < right; u++) { int i1 = u - x + radius; int w = conv[j][i1]; ColorBgra *pRef = pRow + u; r += pRef->R * w; g += pRef->G * w; b += pRef->B * w; } } ColorBgra topLayer = ColorBgra.FromBgr( Utility.ClampToByte(b), Utility.ClampToByte(g), Utility.ClampToByte(r)); // Desaturate topLayer = this.desaturateOp.Apply(topLayer); // Adjust Brightness and Contrast if (topLayer.R > (Data.InkOutline * 255 / 100)) { topLayer = ColorBgra.FromBgra(255, 255, 255, topLayer.A); } else { topLayer = ColorBgra.FromBgra(0, 0, 0, topLayer.A); } // Change Blend Mode to Darken ColorBgra myPixel = this.darkenOp.Apply(topLayer, *dstPtr); * dstPtr = myPixel; ++srcPtr; ++dstPtr; } } } }
protected unsafe override void OnRender(Rectangle[] rois, int startIndex, int length) { Surface dst = DstArgs.Surface; Surface src = SrcArgs.Surface; for (int i = startIndex; i < startIndex + length; ++i) { Rectangle rect = rois[i]; // loop through each line of target rectangle for (int y = rect.Top; y < rect.Bottom; ++y) { int fyStart = 0; int fyEnd = 3; if (y == src.Bounds.Top) { fyStart = 1; } if (y == src.Bounds.Bottom - 1) { fyEnd = 2; } // loop through each point in the line ColorBgra *dstPtr = dst.GetPointAddressUnchecked(rect.Left, y); for (int x = rect.Left; x < rect.Right; ++x) { int fxStart = 0; int fxEnd = 3; if (x == src.Bounds.Left) { fxStart = 1; } if (x == src.Bounds.Right - 1) { fxEnd = 2; } // loop through each weight double sum = 0.0; for (int fy = fyStart; fy < fyEnd; ++fy) { for (int fx = fxStart; fx < fxEnd; ++fx) { double weight = this.weights[fy][fx]; ColorBgra c = src.GetPointUnchecked(x - 1 + fx, y - 1 + fy); double intensity = (double)c.GetIntensityByte(); sum += weight * intensity; } } int iSum = (int)sum + 128; if (iSum > 255) { iSum = 255; } else if (iSum < 0) { iSum = 0; } *dstPtr = ColorBgra.FromBgra((byte)iSum, (byte)iSum, (byte)iSum, 255); ++dstPtr; } } } }
unsafe public override void Render(ImageSurface src, ImageSurface dst, Gdk.Rectangle[] rois) { const double jr = 0.3125; const double ji = 0.03; int w = dst.Width; int h = dst.Height; double invH = 1.0 / h; double invZoom = 1.0 / Data.Zoom; double invQuality = 1.0 / Data.Quality; double aspect = (double)h / (double)w; int count = Data.Quality * Data.Quality + 1; double invCount = 1.0 / (double)count; double angleTheta = (Data.Angle * Math.PI * 2) / 360.0; ColorBgra *dst_dataptr = (ColorBgra *)dst.DataPtr; int dst_width = dst.Width; foreach (Gdk.Rectangle rect in rois) { for (int y = rect.Top; y <= rect.GetBottom(); y++) { ColorBgra *dstPtr = dst.GetPointAddressUnchecked(dst_dataptr, dst_width, rect.Left, y); for (int x = rect.Left; x <= rect.GetRight(); x++) { int r = 0; int g = 0; int b = 0; int a = 0; for (double i = 0; i < count; i++) { double u = (2.0 * x - w + (i * invCount)) * invH; double v = (2.0 * y - h + ((i * invQuality) % 1)) * invH; double radius = Math.Sqrt((u * u) + (v * v)); double radiusP = radius; double theta = Math.Atan2(v, u); double thetaP = theta + angleTheta; double uP = radiusP * Math.Cos(thetaP); double vP = radiusP * Math.Sin(thetaP); double jX = (uP - vP * aspect) * invZoom; double jY = (vP + uP * aspect) * invZoom; double j = Julia(jX, jY, jr, ji); double c = Data.Factor * j; b += Utility.ClampToByte(c - 768); g += Utility.ClampToByte(c - 512); r += Utility.ClampToByte(c - 256); a += Utility.ClampToByte(c - 0); } *dstPtr = ColorBgra.FromBgra(Utility.ClampToByte(b / count), Utility.ClampToByte(g / count), Utility.ClampToByte(r / count), Utility.ClampToByte(a / count)); ++dstPtr; } } } }
protected unsafe override void RenderLine(ISurface src, ISurface dst, Rectangle rect) { if (amount == 0) { // Copy src to dest return; } var src_bounds = src.Bounds; long w = dst.Width; long h = dst.Height; long fox = (long)(dst.Width * offset.X * 32768.0); long foy = (long)(dst.Height * offset.Y * 32768.0); long fcx = fox + (w << 15); long fcy = foy + (h << 15); long fz = amount; const int n = 64; for (int y = rect.Top; y <= rect.Bottom; ++y) { ColorBgra *dstPtr = dst.GetPointAddress(rect.Left, y); ColorBgra *srcPtr = src.GetPointAddress(rect.Left, y); for (int x = rect.Left; x <= rect.Right; ++x) { long fx = (x << 16) - fcx; long fy = (y << 16) - fcy; int sr = 0; int sg = 0; int sb = 0; int sa = 0; int sc = 0; sr += srcPtr->R * srcPtr->A; sg += srcPtr->G * srcPtr->A; sb += srcPtr->B * srcPtr->A; sa += srcPtr->A; ++sc; for (int i = 0; i < n; ++i) { fx -= ((fx >> 4) * fz) >> 10; fy -= ((fy >> 4) * fz) >> 10; int u = (int)(fx + fcx + 32768 >> 16); int v = (int)(fy + fcy + 32768 >> 16); if (src_bounds.Contains(u, v)) { ColorBgra *srcPtr2 = src.GetPointAddress(u, v); sr += srcPtr2->R * srcPtr2->A; sg += srcPtr2->G * srcPtr2->A; sb += srcPtr2->B * srcPtr2->A; sa += srcPtr2->A; ++sc; } } if (sa != 0) { *dstPtr = ColorBgra.FromBgra( Utility.ClampToByte(sb / sa), Utility.ClampToByte(sg / sa), Utility.ClampToByte(sr / sa), Utility.ClampToByte(sa / sc)); } else { dstPtr->Bgra = 0; } ++srcPtr; ++dstPtr; } } }
public unsafe override void Render(ImageSurface src, ImageSurface dst, Gdk.Rectangle[] rois) { if (Data.Angle == 0) { // Copy src to dest return; } int w = dst.Width; int h = dst.Height; int fcx = (w << 15) + (int)(Data.Offset.X * (w << 15)); int fcy = (h << 15) + (int)(Data.Offset.Y * (h << 15)); int n = (Data.Quality * Data.Quality) * (30 + Data.Quality * Data.Quality); int fr = (int)(Data.Angle * Math.PI * 65536.0 / 181.0); foreach (Gdk.Rectangle rect in rois) { for (int y = rect.Top; y < rect.Bottom; ++y) { ColorBgra *dstPtr = dst.GetPointAddressUnchecked(rect.Left, y); ColorBgra *srcPtr = src.GetPointAddressUnchecked(rect.Left, y); for (int x = rect.Left; x < rect.Right; ++x) { int fx = (x << 16) - fcx; int fy = (y << 16) - fcy; int fsr = fr / n; int sr = 0; int sg = 0; int sb = 0; int sa = 0; int sc = 0; sr += srcPtr->R * srcPtr->A; sg += srcPtr->G * srcPtr->A; sb += srcPtr->B * srcPtr->A; sa += srcPtr->A; ++sc; int ox1 = fx; int ox2 = fx; int oy1 = fy; int oy2 = fy; ColorBgra *src_dataptr = (ColorBgra *)src.DataPtr; int src_width = src.Width; for (int i = 0; i < n; ++i) { Rotate(ref ox1, ref oy1, fsr); Rotate(ref ox2, ref oy2, -fsr); int u1 = ox1 + fcx + 32768 >> 16; int v1 = oy1 + fcy + 32768 >> 16; if (u1 > 0 && v1 > 0 && u1 < w && v1 < h) { ColorBgra *sample = src.GetPointAddressUnchecked(src_dataptr, src_width, u1, v1); sr += sample->R * sample->A; sg += sample->G * sample->A; sb += sample->B * sample->A; sa += sample->A; ++sc; } int u2 = ox2 + fcx + 32768 >> 16; int v2 = oy2 + fcy + 32768 >> 16; if (u2 > 0 && v2 > 0 && u2 < w && v2 < h) { ColorBgra *sample = src.GetPointAddressUnchecked(src_dataptr, src_width, u2, v2); sr += sample->R * sample->A; sg += sample->G * sample->A; sb += sample->B * sample->A; sa += sample->A; ++sc; } } if (sa > 0) { *dstPtr = ColorBgra.FromBgra( Utility.ClampToByte(sb / sa), Utility.ClampToByte(sg / sa), Utility.ClampToByte(sr / sa), Utility.ClampToByte(sa / sc)); } else { dstPtr->Bgra = 0; } ++dstPtr; ++srcPtr; } } } }
public unsafe void RenderConvolutionFilter(int[][] weights, int offset, RenderArgs dstArgs, RenderArgs srcArgs, Rectangle[] rois, int startIndex, int length) { int weightsWidth = weights[0].Length; int weightsHeight = weights.Length; int fYOffset = -(weightsHeight / 2); int fXOffset = -(weightsWidth / 2); // we cache the beginning and ending horizontal indices into the weights matrix // for every source pixel X location // i.e. for src[x,y], where we're concerned with x, what weight[x,y] horizontal // extent should we worry about? // this way we end up with less branches and faster code (hopefully?!) FExtent fxExtent = GetFExtent(srcArgs.Surface.Width, weightsWidth); FExtent fyExtent = GetFExtent(srcArgs.Surface.Height, weightsHeight); for (int ri = startIndex; ri < startIndex + length; ++ri) { Rectangle roi = rois[ri]; for (int y = roi.Top; y < roi.Bottom; ++y) { ColorBgra *dstPixel = dstArgs.Surface.GetPointAddressUnchecked(roi.Left, y); int fyStart = fyExtent.fStarts[y]; int fyEnd = fyExtent.fEnds[y]; for (int x = roi.Left; x < roi.Right; ++x) { int redSum = 0; int greenSum = 0; int blueSum = 0; int alphaSum = 0; int colorFactor = 0; int alphaFactor = 0; int fxStart = fxExtent.fStarts[x]; int fxEnd = fxExtent.fEnds[x]; for (int fy = fyStart; fy < fyEnd; ++fy) { int srcY = y + fy + fYOffset; int srcX1 = x + fXOffset + fxStart; ColorBgra *srcPixel = srcArgs.Surface.GetPointAddressUnchecked(srcX1, srcY); int[] wRow = weights[fy]; for (int fx = fxStart; fx < fxEnd; ++fx) { int srcX = fx + srcX1; int weight = wRow[fx]; ColorBgra c = *srcPixel; alphaFactor += weight; weight = weight * (c.A + (c.A >> 7)); colorFactor += weight; weight >>= 8; redSum += c.R * weight; blueSum += c.B * weight; greenSum += c.G * weight; alphaSum += c.A * weight; ++srcPixel; } } colorFactor /= 256; if (colorFactor != 0) { redSum /= colorFactor; greenSum /= colorFactor; blueSum /= colorFactor; } else { redSum = 0; greenSum = 0; blueSum = 0; } if (alphaFactor != 0) { alphaSum /= alphaFactor; } else { alphaSum = 0; } redSum += offset; greenSum += offset; blueSum += offset; alphaSum += offset; #region clamp values to [0,255] if (redSum < 0) { redSum = 0; } else if (redSum > 255) { redSum = 255; } if (greenSum < 0) { greenSum = 0; } else if (greenSum > 255) { greenSum = 255; } if (blueSum < 0) { blueSum = 0; } else if (blueSum > 255) { blueSum = 255; } if (alphaSum < 0) { alphaSum = 0; } else if (alphaSum > 255) { alphaSum = 255; } #endregion *dstPixel = ColorBgra.FromBgra((byte)blueSum, (byte)greenSum, (byte)redSum, (byte)alphaSum); ++dstPixel; } } } }
public unsafe override void Render(EffectConfigToken configToken, RenderArgs dstArgs, RenderArgs srcArgs, Rectangle[] rois, int startIndex, int length) { EmbossEffectConfigToken eect = (EmbossEffectConfigToken)configToken; double[,] weights = eect.Weights; Surface dst = dstArgs.Surface; Surface src = srcArgs.Surface; for (int i = startIndex; i < startIndex + length; ++i) { Rectangle rect = rois[i]; // loop through each line of target rectangle for (int y = rect.Top; y < rect.Bottom; ++y) { int fyStart = 0; int fyEnd = 3; if (y == src.Bounds.Top) { fyStart = 1; } if (y == src.Bounds.Bottom - 1) { fyEnd = 2; } // loop through each point in the line ColorBgra *dstPtr = dst.GetPointAddress(rect.Left, y); for (int x = rect.Left; x < rect.Right; ++x) { int fxStart = 0; int fxEnd = 3; if (x == src.Bounds.Left) { fxStart = 1; } if (x == src.Bounds.Right - 1) { fxEnd = 2; } // loop through each weight double sum = 0.0; for (int fy = fyStart; fy < fyEnd; ++fy) { for (int fx = fxStart; fx < fxEnd; ++fx) { double weight = weights[fy, fx]; ColorBgra c = src.GetPointUnchecked(x - 1 + fx, y - 1 + fy); double intensity = (double)c.GetIntensityByte(); sum += weight * intensity; } } int iSum = (int)sum; iSum += 128; if (iSum > 255) { iSum = 255; } if (iSum < 0) { iSum = 0; } *dstPtr = ColorBgra.FromBgra((byte)iSum, (byte)iSum, (byte)iSum, 255); ++dstPtr; } } } }
private void SetSliderGradients() { HsvColor h = wheel.HsvColor; ColorBgra c = wheel.Color; rslider.Gradient = new ColorBgra[] { ColorBgra.FromBgr(c.B, c.G, 0), ColorBgra.FromBgr(c.B, c.G, 255) }; gslider.Gradient = new ColorBgra[] { ColorBgra.FromBgr(c.B, 0, c.R), ColorBgra.FromBgr(c.B, 255, c.R) }; bslider.Gradient = new ColorBgra[] { ColorBgra.FromBgr(0, c.G, c.R), ColorBgra.FromBgr(255, c.G, c.R) }; aslider.Gradient = new ColorBgra[] { ColorBgra.FromBgra(c.B, c.G, c.R, 0), ColorBgra.FromBgra(c.B, c.G, c.R, 255) }; sslider.Gradient = new ColorBgra[] { new HsvColor(h.Hue, 0, h.Value).ToColorBgra(), new HsvColor(h.Hue, 100, h.Value).ToColorBgra() }; vslider.Gradient = new ColorBgra[] { new HsvColor(h.Hue, h.Saturation, 0).ToColorBgra(), new HsvColor(h.Hue, h.Saturation, 100).ToColorBgra() }; if (hslider.Gradient == null) { ColorBgra[] hues = new ColorBgra[361]; for (int hue = 0; hue <= 360; ++hue) { hues[hue] = new HsvColor(hue, 100, 100).ToColorBgra(); } hslider.Gradient = hues; } }
public unsafe void Render(Surface src, Surface dst, Rectangle[] rois, int start, int len) { int width = src.Width; int height = src.Height; int arrayLens = 1 + this.coarseness; int localStoreSize = arrayLens * 5 * sizeof(int); byte *localStore = stackalloc byte[localStoreSize]; byte *p = localStore; int *intensityCount = (int *)p; p += arrayLens * sizeof(int); uint *avgRed = (uint *)p; p += arrayLens * sizeof(uint); uint *avgGreen = (uint *)p; p += arrayLens * sizeof(uint); uint *avgBlue = (uint *)p; p += arrayLens * sizeof(uint); uint *avgAlpha = (uint *)p; p += arrayLens * sizeof(uint); byte maxIntensity = this.coarseness; //TODO: review here for (int r = start; r < start + len; ++r) { Rectangle rect = rois[r]; int rectTop = rect.Top; int rectBottom = rect.Bottom; int rectLeft = rect.Left; int rectRight = rect.Right; for (int y = rectTop; y < rectBottom; ++y) { ColorBgra *dstPtr = dst.GetPointAddressUnchecked(rect.Left, y); int top = y - brushSize; int bottom = y + brushSize + 1; if (top < 0) { top = 0; } if (bottom > height) { bottom = height; } for (int x = rectLeft; x < rectRight; ++x) { PlatformMemory.SetToZero(localStore, (ulong)localStoreSize); int left = x - brushSize; int right = x + brushSize + 1; if (left < 0) { left = 0; } if (right > width) { right = width; } int numInt = 0; for (int j = top; j < bottom; ++j) { ColorBgra *srcPtr = src.GetPointAddressUnchecked(left, j); for (int i = left; i < right; ++i) { byte intensity = PixelUtils.FastScaleByteByByte(srcPtr->GetIntensityByte(), maxIntensity); ++intensityCount[intensity]; ++numInt; avgRed[intensity] += srcPtr->R; avgGreen[intensity] += srcPtr->G; avgBlue[intensity] += srcPtr->B; avgAlpha[intensity] += srcPtr->A; ++srcPtr; } } byte chosenIntensity = 0; int maxInstance = 0; for (int i = 0; i <= maxIntensity; ++i) { if (intensityCount[i] > maxInstance) { chosenIntensity = (byte)i; maxInstance = intensityCount[i]; } } // TODO: correct handling of alpha values? byte R = (byte)(avgRed[chosenIntensity] / maxInstance); byte G = (byte)(avgGreen[chosenIntensity] / maxInstance); byte B = (byte)(avgBlue[chosenIntensity] / maxInstance); byte A = (byte)(avgAlpha[chosenIntensity] / maxInstance); *dstPtr = ColorBgra.FromBgra(B, G, R, A); ++dstPtr; } } } }
unsafe public override void Render(ImageSurface src, ImageSurface dst, Gdk.Rectangle[] rois) { int width = dst.Width; int height = dst.Height; float hw = width / 2f; float hh = height / 2f; float sin = (float)Math.Sin(Data.Rotation * Math.PI / 180.0); float cos = (float)Math.Cos(Data.Rotation * Math.PI / 180.0); float scale = (float)Math.PI / Data.TileSize; float intensity = Data.Intensity; intensity = intensity * intensity / 10 * Math.Sign(intensity); int aaLevel = 4; int aaSamples = aaLevel * aaLevel + 1; PointD *aaPoints = stackalloc PointD[aaSamples]; for (int i = 0; i < aaSamples; ++i) { double x = (i * aaLevel) / (double)aaSamples; double y = i / (double)aaSamples; x -= (int)x; // RGSS + rotation to maximize AA quality aaPoints[i] = new PointD((double)(cos * x + sin * y), (double)(cos * y - sin * x)); } int src_width = src.Width; ColorBgra *src_data_ptr = (ColorBgra *)src.DataPtr; foreach (var rect in rois) { for (int y = rect.Top; y <= rect.GetBottom(); y++) { float j = y - hh; ColorBgra *dstPtr = dst.GetPointAddressUnchecked(rect.Left, y); for (int x = rect.Left; x <= rect.GetRight(); x++) { int b = 0; int g = 0; int r = 0; int a = 0; float i = x - hw; for (int p = 0; p < aaSamples; ++p) { PointD pt = aaPoints[p]; float u = i + (float)pt.X; float v = j - (float)pt.Y; float s = cos * u + sin * v; float t = -sin * u + cos * v; s += intensity * (float)Math.Tan(s * scale); t += intensity * (float)Math.Tan(t * scale); u = cos * s - sin * t; v = sin * s + cos * t; int xSample = (int)(hw + u); int ySample = (int)(hh + v); xSample = (xSample + width) % width; // This makes it a little faster if (xSample < 0) { xSample = (xSample + width) % width; } ySample = (ySample + height) % height; // This makes it a little faster if (ySample < 0) { ySample = (ySample + height) % height; } ColorBgra sample = *src.GetPointAddressUnchecked(src_data_ptr, src_width, xSample, ySample); b += sample.B; g += sample.G; r += sample.R; a += sample.A; } *(dstPtr++) = ColorBgra.FromBgra((byte)(b / aaSamples), (byte)(g / aaSamples), (byte)(r / aaSamples), (byte)(a / aaSamples)); } } } }
public unsafe override void Render(ImageSurface src, ImageSurface dest, Gdk.Rectangle[] rois) { int width = src.Width; int height = src.Height; int arrayLens = 1 + Data.Coarseness; int localStoreSize = arrayLens * 5 * sizeof(int); byte *localStore = stackalloc byte[localStoreSize]; byte *p = localStore; int *intensityCount = (int *)p; p += arrayLens * sizeof(int); uint *avgRed = (uint *)p; p += arrayLens * sizeof(uint); uint *avgGreen = (uint *)p; p += arrayLens * sizeof(uint); uint *avgBlue = (uint *)p; p += arrayLens * sizeof(uint); uint *avgAlpha = (uint *)p; p += arrayLens * sizeof(uint); byte maxIntensity = (byte)Data.Coarseness; foreach (Gdk.Rectangle rect in rois) { int rectTop = rect.Top; int rectBottom = rect.GetBottom(); int rectLeft = rect.Left; int rectRight = rect.GetRight(); ColorBgra *dst_dataptr = (ColorBgra *)dest.DataPtr; int dst_width = dest.Width; ColorBgra *src_dataptr = (ColorBgra *)src.DataPtr; int src_width = src.Width; for (int y = rectTop; y <= rectBottom; ++y) { ColorBgra *dstPtr = dest.GetPointAddressUnchecked(dst_dataptr, dst_width, rect.Left, y); int top = y - Data.BrushSize; int bottom = y + Data.BrushSize + 1; if (top < 0) { top = 0; } if (bottom > height) { bottom = height; } for (int x = rectLeft; x <= rectRight; ++x) { SetToZero(localStore, (ulong)localStoreSize); int left = x - Data.BrushSize; int right = x + Data.BrushSize + 1; if (left < 0) { left = 0; } if (right > width) { right = width; } int numInt = 0; for (int j = top; j < bottom; ++j) { ColorBgra *srcPtr = src.GetPointAddressUnchecked(src_dataptr, src_width, left, j); for (int i = left; i < right; ++i) { byte intensity = Utility.FastScaleByteByByte(srcPtr->GetIntensityByte(), maxIntensity); ++intensityCount[intensity]; ++numInt; avgRed[intensity] += srcPtr->R; avgGreen[intensity] += srcPtr->G; avgBlue[intensity] += srcPtr->B; avgAlpha[intensity] += srcPtr->A; ++srcPtr; } } byte chosenIntensity = 0; int maxInstance = 0; for (int i = 0; i <= maxIntensity; ++i) { if (intensityCount[i] > maxInstance) { chosenIntensity = (byte)i; maxInstance = intensityCount[i]; } } // TODO: correct handling of alpha values? byte R = (byte)(avgRed[chosenIntensity] / maxInstance); byte G = (byte)(avgGreen[chosenIntensity] / maxInstance); byte B = (byte)(avgBlue[chosenIntensity] / maxInstance); byte A = (byte)(avgAlpha[chosenIntensity] / maxInstance); *dstPtr = ColorBgra.FromBgra(B, G, R, A); ++dstPtr; } } } }
protected unsafe override void RenderLine(ISurface src, ISurface dst, Rectangle rect) { int width = src.Width; int height = src.Height; int r = amount; Random localRandom = this.random; int * intensityCount = stackalloc int[256]; uint *avgRed = stackalloc uint[256]; uint *avgGreen = stackalloc uint[256]; uint *avgBlue = stackalloc uint[256]; uint *avgAlpha = stackalloc uint[256]; byte *intensityChoices = stackalloc byte[(1 + (r * 2)) * (1 + (r * 2))]; int rectTop = rect.Top; int rectBottom = rect.Bottom; int rectLeft = rect.Left; int rectRight = rect.Right; for (int y = rectTop; y <= rectBottom; ++y) { ColorBgra *dstPtr = dst.GetPointAddress(rect.Left, y); int top = y - r; int bottom = y + r + 1; if (top < 0) { top = 0; } if (bottom > height) { bottom = height; } for (int x = rectLeft; x <= rectRight; ++x) { int intensityChoicesIndex = 0; for (int i = 0; i < 256; ++i) { intensityCount[i] = 0; avgRed[i] = 0; avgGreen[i] = 0; avgBlue[i] = 0; avgAlpha[i] = 0; } int left = x - r; int right = x + r + 1; if (left < 0) { left = 0; } if (right > width) { right = width; } for (int j = top; j < bottom; ++j) { if (j < 0 || j >= height) { continue; } ColorBgra *srcPtr = src.GetPointAddress(left, j); for (int i = left; i < right; ++i) { byte intensity = srcPtr->GetIntensityByte(); intensityChoices[intensityChoicesIndex] = intensity; ++intensityChoicesIndex; ++intensityCount[intensity]; avgRed[intensity] += srcPtr->R; avgGreen[intensity] += srcPtr->G; avgBlue[intensity] += srcPtr->B; avgAlpha[intensity] += srcPtr->A; ++srcPtr; } } int randNum; lock (localRandom) { randNum = localRandom.Next(intensityChoicesIndex); } byte chosenIntensity = intensityChoices[randNum]; byte R = (byte)(avgRed[chosenIntensity] / intensityCount[chosenIntensity]); byte G = (byte)(avgGreen[chosenIntensity] / intensityCount[chosenIntensity]); byte B = (byte)(avgBlue[chosenIntensity] / intensityCount[chosenIntensity]); byte A = (byte)(avgAlpha[chosenIntensity] / intensityCount[chosenIntensity]); *dstPtr = ColorBgra.FromBgra(B, G, R, A); ++dstPtr; // prepare the array for the next loop iteration for (int i = 0; i < intensityChoicesIndex; ++i) { intensityChoices[i] = 0; } } } }
public unsafe override void Render(ImageSurface src, ImageSurface dst, Gdk.Rectangle[] rois) { if (Data.Amount == 0) { // Copy src to dest return; } int src_width = src.Width; ColorBgra *src_data_ptr = (ColorBgra *)src.DataPtr; int dst_width = dst.Width; ColorBgra *dst_data_ptr = (ColorBgra *)dst.DataPtr; Gdk.Rectangle src_bounds = src.GetBounds(); long w = dst.Width; long h = dst.Height; long fox = (long)(dst.Width * Data.Offset.X * 32768.0); long foy = (long)(dst.Height * Data.Offset.Y * 32768.0); long fcx = fox + (w << 15); long fcy = foy + (h << 15); long fz = Data.Amount; const int n = 64; foreach (Gdk.Rectangle rect in rois) { for (int y = rect.Top; y <= rect.GetBottom(); ++y) { ColorBgra *dstPtr = dst.GetPointAddressUnchecked(dst_data_ptr, dst_width, rect.Left, y); ColorBgra *srcPtr = src.GetPointAddressUnchecked(src_data_ptr, src_width, rect.Left, y); for (int x = rect.Left; x <= rect.GetRight(); ++x) { long fx = (x << 16) - fcx; long fy = (y << 16) - fcy; int sr = 0; int sg = 0; int sb = 0; int sa = 0; int sc = 0; sr += srcPtr->R * srcPtr->A; sg += srcPtr->G * srcPtr->A; sb += srcPtr->B * srcPtr->A; sa += srcPtr->A; ++sc; for (int i = 0; i < n; ++i) { fx -= ((fx >> 4) * fz) >> 10; fy -= ((fy >> 4) * fz) >> 10; int u = (int)(fx + fcx + 32768 >> 16); int v = (int)(fy + fcy + 32768 >> 16); if (src_bounds.Contains(u, v)) { ColorBgra *srcPtr2 = src.GetPointAddressUnchecked(src_data_ptr, src_width, u, v); sr += srcPtr2->R * srcPtr2->A; sg += srcPtr2->G * srcPtr2->A; sb += srcPtr2->B * srcPtr2->A; sa += srcPtr2->A; ++sc; } } if (sa != 0) { *dstPtr = ColorBgra.FromBgra( Utility.ClampToByte(sb / sa), Utility.ClampToByte(sg / sa), Utility.ClampToByte(sr / sa), Utility.ClampToByte(sa / sc)); } else { dstPtr->Bgra = 0; } ++srcPtr; ++dstPtr; } } } }
private ColorBgra ReadColor(Stream input, int pixelDepth, ColorBgra[] palette) { ColorBgra color; switch (pixelDepth) { case 32: { long colorInt = Utility.ReadUInt32(input); if (colorInt == -1) { throw new EndOfStreamException(); } color = ColorBgra.FromUInt32((uint)colorInt); break; } case 24: { int colorInt = Utility.ReadUInt24(input); if (colorInt == -1) { throw new EndOfStreamException(); } color = ColorBgra.FromUInt32((uint)colorInt); color.A = 255; break; } case 15: case 16: { int colorWord = Utility.ReadUInt16(input); if (colorWord == -1) { throw new EndOfStreamException(); } color = ColorBgra.FromBgra( (byte)((colorWord >> 7) & 0xf8), (byte)((colorWord >> 2) & 0xf8), (byte)((colorWord & 0x1f) * 8), 255); break; } case 8: { int colorByte = input.ReadByte(); if (colorByte == -1) { throw new EndOfStreamException(); } if (colorByte >= palette.Length) { throw new FormatException("color index was outside the bounds of the palette"); } color = palette[colorByte]; break; } default: throw new FormatException("colorDepth was not one of {8, 15, 16, 24, 32}"); } return(color); }
public override void Render(Surface src, Surface dst, Rectangle[] rois, int startIndex, int length) { unsafe { // Glow backgound glowRenderer.Render(src, dst, rois, startIndex, length); // Create black outlines by finding the edges of objects for (int i = startIndex; i < startIndex + length; ++i) { Rectangle roi = rois[i]; for (int y = roi.Top; y < roi.Bottom; ++y) { int top = y - radius; int bottom = y + radius + 1; if (top < 0) { top = 0; } if (bottom > dst.Height) { bottom = dst.Height; } ColorBgra *srcPtr = src.GetPointAddress(roi.X, y); ColorBgra *dstPtr = src.GetPointAddress(roi.X, y); for (int x = roi.Left; x < roi.Right; ++x) { int left = x - radius; int right = x + radius + 1; if (left < 0) { left = 0; } if (right > dst.Width) { right = dst.Width; } int r = 0; int g = 0; int b = 0; for (int v = top; v < bottom; v++) { ColorBgra *pRow = src.GetRowAddress(v); int j = v - y + radius; for (int u = left; u < right; u++) { int i1 = u - x + radius; int w = conv[j][i1]; ColorBgra *pRef = pRow + u; r += pRef->R * w; g += pRef->G * w; b += pRef->B * w; } } ColorBgra topLayer = ColorBgra.FromBgr( PixelUtils.ClampToByte(b), PixelUtils.ClampToByte(g), PixelUtils.ClampToByte(r)); // Desaturate topLayer = this.desaturateOp.Apply(topLayer); // Adjust Brightness and Contrast if (topLayer.R > (this.inkOutline * 255 / 100)) { topLayer = ColorBgra.FromBgra(255, 255, 255, topLayer.A); } else { topLayer = ColorBgra.FromBgra(0, 0, 0, topLayer.A); } // Change Blend Mode to Darken ColorBgra myPixel = this.darkenOp.Apply(topLayer, *dstPtr); * dstPtr = myPixel; ++srcPtr; ++dstPtr; } } } } }
protected override unsafe void OnRender(Rectangle[] renderRects, int startIndex, int length) { int w = DstArgs.Width; int h = DstArgs.Height; double wDiv2 = (double)w / 2; double hDiv2 = (double)h / 2; double invH = 1.0 / h; double invZoom = 1.0 / this.zoom; double invQuality = 1.0 / (double)this.quality; int count = this.quality * this.quality + 1; double invCount = 1.0 / (double)count; for (int ri = startIndex; ri < startIndex + length; ++ri) { Rectangle rect = renderRects[ri]; for (int y = rect.Top; y < rect.Bottom; y++) { ColorBgra *dstPtr = DstArgs.Surface.GetPointAddressUnchecked(rect.Left, y); for (int x = rect.Left; x < rect.Right; x++) { int r = 0; int g = 0; int b = 0; int a = 0; for (double i = 0; i < count; i++) { double u = (2.0 * x - w + (i * invCount)) * invH; double v = (2.0 * y - h + ((i * invQuality) % 1)) * invH; double radius = Math.Sqrt((u * u) + (v * v)); double radiusP = radius; double theta = Math.Atan2(v, u); double thetaP = theta + this.angleTheta; double uP = radiusP * Math.Cos(thetaP); double vP = radiusP * Math.Sin(thetaP); double m = Mandelbrot( (uP * invZoom) + this.xOffset, (vP * invZoom) + this.yOffset, this.factor); double c = 64 + this.factor * m; r += Utility.ClampToByte(c - 768); g += Utility.ClampToByte(c - 512); b += Utility.ClampToByte(c - 256); a += Utility.ClampToByte(c - 0); } *dstPtr = ColorBgra.FromBgra( Utility.ClampToByte(b / count), Utility.ClampToByte(g / count), Utility.ClampToByte(r / count), Utility.ClampToByte(a / count)); ++dstPtr; } } if (this.invertColors) { for (int y = rect.Top; y < rect.Bottom; y++) { ColorBgra *dstPtr = DstArgs.Surface.GetPointAddressUnchecked(rect.Left, y); for (int x = rect.Left; x < rect.Right; ++x) { ColorBgra c = *dstPtr; c.B = (byte)(255 - c.B); c.G = (byte)(255 - c.G); c.R = (byte)(255 - c.R); *dstPtr = c; ++dstPtr; } } } } }
public unsafe void RenderColorDifferenceEffect( double[][] weights, RenderArgs dstArgs, RenderArgs srcArgs, Rectangle[] rois, int startIndex, int length) { Surface dst = dstArgs.Surface; Surface src = srcArgs.Surface; for (int i = startIndex; i < startIndex + length; ++i) { Rectangle rect = rois[i]; // loop through each line of target rectangle for (int y = rect.Top; y < rect.Bottom; ++y) { int fyStart = 0; int fyEnd = 3; if (y == src.Bounds.Top) { fyStart = 1; } if (y == src.Bounds.Bottom - 1) { fyEnd = 2; } // loop through each point in the line ColorBgra *dstPtr = dst.GetPointAddressUnchecked(rect.Left, y); for (int x = rect.Left; x < rect.Right; ++x) { int fxStart = 0; int fxEnd = 3; if (x == src.Bounds.Left) { fxStart = 1; } if (x == src.Bounds.Right - 1) { fxEnd = 2; } // loop through each weight double rSum = 0.0; double gSum = 0.0; double bSum = 0.0; for (int fy = fyStart; fy < fyEnd; ++fy) { for (int fx = fxStart; fx < fxEnd; ++fx) { double weight = weights[fy][fx]; ColorBgra c = src.GetPointUnchecked(x - 1 + fx, y - 1 + fy); rSum += weight * (double)c.R; gSum += weight * (double)c.G; bSum += weight * (double)c.B; } } int iRsum = (int)rSum; int iGsum = (int)gSum; int iBsum = (int)bSum; if (iRsum > 255) { iRsum = 255; } if (iGsum > 255) { iGsum = 255; } if (iBsum > 255) { iBsum = 255; } if (iRsum < 0) { iRsum = 0; } if (iGsum < 0) { iGsum = 0; } if (iBsum < 0) { iBsum = 0; } *dstPtr = ColorBgra.FromBgra((byte)iBsum, (byte)iGsum, (byte)iRsum, 255); ++dstPtr; } } } }
public static unsafe ColorBgra GetPercentile(int percentile, int area, int *hb, int *hg, int *hr, int *ha) { int minCount = area * percentile / 100; int b = 0; int bCount = 0; while (b < 255 && hb[b] == 0) { ++b; } while (b < 255 && bCount < minCount) { bCount += hb[b]; ++b; } int g = 0; int gCount = 0; while (g < 255 && hg[g] == 0) { ++g; } while (g < 255 && gCount < minCount) { gCount += hg[g]; ++g; } int r = 0; int rCount = 0; while (r < 255 && hr[r] == 0) { ++r; } while (r < 255 && rCount < minCount) { rCount += hr[r]; ++r; } int a = 0; int aCount = 0; while (a < 255 && ha[a] == 0) { ++a; } while (a < 255 && aCount < minCount) { aCount += ha[a]; ++a; } return(ColorBgra.FromBgra((byte)b, (byte)g, (byte)r, (byte)a)); }
public override ColorBgra Apply(ColorBgra color) { int i = 0; int h, s, v, delta; switch (InputMode) { case Channel.A: i = Curve[color.A]; break; case Channel.R: i = Curve[color.R]; break; case Channel.G: i = Curve[color.G]; break; case Channel.B: i = Curve[color.B]; break; case Channel.C: i = 255 - color.R; i -= Math.Min(Math.Min(255 - color.R, 255 - color.G), 255 - color.B); i = Curve[i]; break; case Channel.M: i = 255 - color.G; i -= Math.Min(Math.Min(255 - color.R, 255 - color.G), 255 - color.B); i = Curve[i]; break; case Channel.Y: i = 255 - color.B; i -= Math.Min(Math.Min(255 - color.R, 255 - color.G), 255 - color.B); i = Curve[i]; break; case Channel.K: i = Math.Min(Math.Min(255 - color.R, 255 - color.G), 255 - color.B); i = Curve[i]; break; case Channel.H: s = 0; v = (color.R > color.G) ? color.R : color.G; delta = 0; if (color.B > v) { v = color.B; } if (v == 0) { s = 0; } else { int min = (color.R < color.G) ? color.R : color.G; if (color.B < min) { min = color.B; } delta = v - min; if (delta > 0) { s = CommonUtil.IntDiv(255 * delta, v); } } if (s == 0) { i = 0; } else { if (color.R == v) // Between Yellow and Magenta { i = CommonUtil.IntDiv(255 * (color.G - color.B), delta); } else if (color.G == v) // Between Cyan and Yellow { i = 512 + CommonUtil.IntDiv(255 * (color.B - color.R), delta); } else // Between Magenta and Cyan { i = 1024 + CommonUtil.IntDiv(255 * (color.R - color.G), delta); } if (i < 0) { i += 1536; } i = CommonUtil.IntDiv(i, 6); } i = Curve[i]; break; case Channel.S: v = (color.R > color.G) ? color.R : color.G; if (color.B > v) { v = color.B; } if (v == 0) { i = 0; } else { int min = (color.R < color.G) ? color.R : color.G; if (color.B < min) { min = color.B; } delta = v - min; if (delta > 0) { i = CommonUtil.IntDiv(255 * delta, v); } } i = Curve[i]; break; case Channel.V: i = (color.R > color.G) ? color.R : color.G; if (color.B > i) { i = color.B; } i = Curve[i]; break; case Channel.L: i = color.GetIntensityByte(); i = Curve[i]; break; default: throw new Exception(); } switch (OutputMode) { case Channel.A: return(ColorBgra.FromBgra( color.B, color.G, color.R, (byte)i)); case Channel.R: return(ColorBgra.FromBgra( color.B, color.G, (byte)i, color.A)); case Channel.G: return(ColorBgra.FromBgra( color.B, (byte)i, color.R, color.A)); case Channel.B: return(ColorBgra.FromBgra( (byte)i, color.G, color.R, color.A)); case Channel.C: i = (byte)(i + Math.Min(Math.Min(255 - color.R, 255 - color.G), 255 - color.B)).Clamp(0, 255); return(ColorBgra.FromBgra( color.B, color.G, (byte)(255 - i), color.A)); case Channel.M: i = (byte)(i + Math.Min(Math.Min(255 - color.R, 255 - color.G), 255 - color.B)).Clamp(0, 255); return(ColorBgra.FromBgra( color.B, (byte)(255 - i), color.R, color.A)); case Channel.Y: i = (byte)(i + Math.Min(Math.Min(255 - color.R, 255 - color.G), 255 - color.B)).Clamp(0, 255); return(ColorBgra.FromBgra( (byte)(255 - i), color.G, color.R, color.A)); case Channel.K: int C = 255 - color.R; int M = 255 - color.G; int Y = 255 - color.B; int K = Math.Min(Math.Min(C, M), Y); return(ColorBgra.FromBgraClamped( 255 - (Y - K + i), 255 - (M - K + i), 255 - (C - K + i), color.A)); case Channel.H: s = 0; v = (color.R > color.G) ? color.R : color.G; delta = 0; if (color.B > v) { v = color.B; } if (v == 0) { s = 0; } else { int min = (color.R < color.G) ? color.R : color.G; if (color.B < min) { min = color.B; } delta = v - min; if (delta > 0) { s = CommonUtil.IntDiv(255 * delta, v); } } i *= 6; int fSector = (i & 0xff); int sNumber = (i >> 8); switch (sNumber) { case 0: int tmp0 = ((s * (255 - fSector)) + 128) >> 8; return(ColorBgra.FromBgra( (byte)(((v * (255 - s)) + 128) >> 8), (byte)(((v * (255 - tmp0)) + 128) >> 8), (byte)v, color.A)); case 1: int tmp1 = ((s * fSector) + 128) >> 8; return(ColorBgra.FromBgra( (byte)(((v * (255 - s)) + 128) >> 8), (byte)v, (byte)(((v * (255 - tmp1)) + 128) >> 8), color.A)); case 2: int tmp2 = ((s * (255 - fSector)) + 128) >> 8; return(ColorBgra.FromBgra( (byte)(((v * (255 - tmp2)) + 128) >> 8), (byte)v, (byte)(((v * (255 - s)) + 128) >> 8), color.A)); case 3: int tmp3 = ((s * fSector) + 128) >> 8; return(ColorBgra.FromBgra( (byte)v, (byte)(((v * (255 - tmp3)) + 128) >> 8), (byte)(((v * (255 - s)) + 128) >> 8), color.A)); case 4: int tmp4 = ((s * (255 - fSector)) + 128) >> 8; return(ColorBgra.FromBgra( (byte)v, (byte)(((v * (255 - s)) + 128) >> 8), (byte)(((v * (255 - tmp4)) + 128) >> 8), color.A)); case 5: int tmp5 = ((s * fSector) + 128) >> 8; return(ColorBgra.FromBgra( (byte)(((v * (255 - tmp5)) + 128) >> 8), (byte)(((v * (255 - s)) + 128) >> 8), (byte)v, color.A)); default: return(new ColorBgra()); } case Channel.S: s = 0; v = (color.R > color.G) ? color.R : color.G; delta = 0; if (color.B > v) { v = color.B; } if (v == 0) { s = 0; } else { int min = (color.R < color.G) ? color.R : color.G; if (color.B < min) { min = color.B; } delta = v - min; if (delta > 0) { s = CommonUtil.IntDiv(255 * delta, v); } } if (s == 0) { h = 0; } else { if (color.R == v) // Between Yellow and Magenta { h = CommonUtil.IntDiv(255 * (color.G - color.B), delta); } else if (color.G == v) // Between Cyan and Yellow { h = 512 + CommonUtil.IntDiv(255 * (color.B - color.R), delta); } else // Between Magenta and Cyan { h = 1024 + CommonUtil.IntDiv(255 * (color.R - color.G), delta); } if (h < 0) { h += 1536; } } int fs = (h & 0xff); int sn = (h >> 8); switch (sn) { case 0: int tmp0 = ((i * (255 - fs)) + 128) >> 8; return(ColorBgra.FromBgra( (byte)(((v * (255 - i)) + 128) >> 8), (byte)(((v * (255 - tmp0)) + 128) >> 8), (byte)v, color.A)); case 1: int tmp1 = ((i * fs) + 128) >> 8; return(ColorBgra.FromBgra( (byte)(((v * (255 - i)) + 128) >> 8), (byte)v, (byte)(((v * (255 - tmp1)) + 128) >> 8), color.A)); case 2: int tmp2 = ((i * (255 - fs)) + 128) >> 8; return(ColorBgra.FromBgra( (byte)(((v * (255 - tmp2)) + 128) >> 8), (byte)v, (byte)(((v * (255 - i)) + 128) >> 8), color.A)); case 3: int tmp3 = ((i * fs) + 128) >> 8; return(ColorBgra.FromBgra( (byte)v, (byte)(((v * (255 - tmp3)) + 128) >> 8), (byte)(((v * (255 - i)) + 128) >> 8), color.A)); case 4: int tmp4 = ((i * (255 - fs)) + 128) >> 8; return(ColorBgra.FromBgra( (byte)v, (byte)(((v * (255 - i)) + 128) >> 8), (byte)(((v * (255 - tmp4)) + 128) >> 8), color.A)); case 5: int tmp5 = ((i * fs) + 128) >> 8; return(ColorBgra.FromBgra( (byte)(((v * (255 - tmp5)) + 128) >> 8), (byte)(((v * (255 - i)) + 128) >> 8), (byte)v, color.A)); default: return(new ColorBgra()); } case Channel.V: int max = (color.R > color.G) ? color.R : color.G; if (color.B > max) { max = color.B; } return(ColorBgra.FromBgra( (byte)CommonUtil.IntDiv(color.B * i, max), (byte)CommonUtil.IntDiv(color.G * i, max), (byte)CommonUtil.IntDiv(color.R * i, max), color.A )); case Channel.L: return(ColorBgra.FromBgraClamped( color.B + i - color.GetIntensityByte(), color.G + i - color.GetIntensityByte(), color.R + i - color.GetIntensityByte(), color.A)); default: throw new Exception(); } }
public unsafe override ColorBgra Apply(ColorBgra src, int area, int *hb, int *hg, int *hr, int *ha) { int minCount1 = area * (100 - this.intensity) / 200; int minCount2 = area * (100 + this.intensity) / 200; int bCount = 0; int b1 = 0; while (b1 < 255 && hb[b1] == 0) { ++b1; } while (b1 < 255 && bCount < minCount1) { bCount += hb[b1]; ++b1; } int b2 = b1; while (b2 < 255 && bCount < minCount2) { bCount += hb[b2]; ++b2; } int gCount = 0; int g1 = 0; while (g1 < 255 && hg[g1] == 0) { ++g1; } while (g1 < 255 && gCount < minCount1) { gCount += hg[g1]; ++g1; } int g2 = g1; while (g2 < 255 && gCount < minCount2) { gCount += hg[g2]; ++g2; } int rCount = 0; int r1 = 0; while (r1 < 255 && hr[r1] == 0) { ++r1; } while (r1 < 255 && rCount < minCount1) { rCount += hr[r1]; ++r1; } int r2 = r1; while (r2 < 255 && rCount < minCount2) { rCount += hr[r2]; ++r2; } int aCount = 0; int a1 = 0; while (a1 < 255 && hb[a1] == 0) { ++a1; } while (a1 < 255 && aCount < minCount1) { aCount += ha[a1]; ++a1; } int a2 = a1; while (a2 < 255 && aCount < minCount2) { aCount += ha[a2]; ++a2; } return(ColorBgra.FromBgra( (byte)(255 - (b2 - b1)), (byte)(255 - (g2 - g1)), (byte)(255 - (r2 - r1)), (byte)(a2))); }
public unsafe override void Render(EffectConfigToken properties, RenderArgs dstArgs, RenderArgs srcArgs, Rectangle[] rois, int startIndex, int length) { TwoAmountsConfigToken token = (TwoAmountsConfigToken)properties; int brushSize = token.Amount1; byte smoothness = (byte)token.Amount2; Surface src = srcArgs.Surface; Surface dst = dstArgs.Surface; int width = src.Width; int height = src.Height; int arrayLens = 1 + smoothness; int* intensityCount = stackalloc int[arrayLens]; uint* avgRed = stackalloc uint[arrayLens]; uint* avgGreen = stackalloc uint[arrayLens]; uint* avgBlue = stackalloc uint[arrayLens]; uint* avgAlpha = stackalloc uint[arrayLens]; byte maxIntensity = smoothness; for (int r = startIndex; r < startIndex + length; ++r) { Rectangle rect = rois[r]; int rectTop = rect.Top; int rectBottom = rect.Bottom; int rectLeft = rect.Left; int rectRight = rect.Right; for (int y = rectTop; y < rectBottom; ++y) { ColorBgra *dstPtr = dst.GetPointAddress(rect.Left, y); int top = y - brushSize; int bottom = y + brushSize + 1; if (top < 0) { top = 0; } if (bottom > height) { bottom = height; } for (int x = rectLeft; x < rectRight; ++x) { int left = x - brushSize; int right = x + brushSize + 1; if (left < 0) { left = 0; } if (right > width) { right = width; } for (int i = 0; i < arrayLens; ++i) { intensityCount[i] = 0; avgRed[i] = 0; avgGreen[i] = 0; avgBlue[i] = 0; avgAlpha[i] = 0; } int numInt = 0; for (int j = top; j < bottom; ++j) { ColorBgra *srcPtr = src.GetPointAddress(left, j); for (int i = left; i < right; ++i) { byte intensity = (byte)((srcPtr->GetIntensityByte() * maxIntensity) / 255); ++intensityCount[intensity]; ++numInt; avgRed[intensity] += srcPtr->R; avgGreen[intensity] += srcPtr->G; avgBlue[intensity] += srcPtr->B; avgAlpha[intensity] += srcPtr->A; ++srcPtr; } } byte chosenIntensity = 0; int maxInstance = 0; for (int i = 0; i <= maxIntensity; ++i) { if (intensityCount[i] > maxInstance) { chosenIntensity = (byte)i; maxInstance = intensityCount[i]; } } byte R = (byte)(avgRed[chosenIntensity] / maxInstance); byte G = (byte)(avgGreen[chosenIntensity] / maxInstance); byte B = (byte)(avgBlue[chosenIntensity] / maxInstance); byte A = (byte)(avgAlpha[chosenIntensity] / maxInstance); *dstPtr = ColorBgra.FromBgra(B, G, R, A); ++dstPtr; } } } }
public override void Render(Surface src, Surface dst, Rectangle[] rois, int startIndex, int length) { long w = dst.Width; long h = dst.Height; long fox = (long)(dst.Width * offsetX * 32768.0); long foy = (long)(dst.Height * offsetY * 32768.0); long fcx = fox + (w << 15); long fcy = foy + (h << 15); long fz = this.amount; unsafe { for (int r = startIndex; r < startIndex + length; ++r) { Rectangle rect = rois[r]; for (int y = rect.Top; y < rect.Bottom; ++y) { ColorBgra *dstPtr = dst.GetPointAddressUnchecked(rect.Left, y); ColorBgra *srcPtr = src.GetPointAddressUnchecked(rect.Left, y); for (int x = rect.Left; x < rect.Right; ++x) { long fx = (x << 16) - fcx; long fy = (y << 16) - fcy; int sr = 0; int sg = 0; int sb = 0; int sa = 0; int sc = 0; sr += srcPtr->R * srcPtr->A; sg += srcPtr->G * srcPtr->A; sb += srcPtr->B * srcPtr->A; sa += srcPtr->A; ++sc; for (int i = 0; i < n; ++i) { fx -= ((fx >> 4) * fz) >> 10; fy -= ((fy >> 4) * fz) >> 10; int u = (int)(fx + fcx + 32768 >> 16); int v = (int)(fy + fcy + 32768 >> 16); if (src.IsVisible(u, v)) { ColorBgra *srcPtr2 = src.GetPointAddressUnchecked(u, v); sr += srcPtr2->R * srcPtr2->A; sg += srcPtr2->G * srcPtr2->A; sb += srcPtr2->B * srcPtr2->A; sa += srcPtr2->A; ++sc; } } if (sa != 0) { *dstPtr = ColorBgra.FromBgra( PixelUtils.ClampToByte(sb / sa), PixelUtils.ClampToByte(sg / sa), PixelUtils.ClampToByte(sr / sa), PixelUtils.ClampToByte(sa / sc)); } else { dstPtr->Bgra = 0; } ++srcPtr; ++dstPtr; } } } } }
public unsafe override void Render(ImageSurface src, ImageSurface dst, Gdk.Rectangle[] rois) { float twist = Data.Amount; float hw = dst.Width / 2.0f; float hh = dst.Height / 2.0f; float maxrad = Math.Min(hw, hh); twist = twist * twist * Math.Sign(twist); int aaLevel = Data.Antialias; int aaSamples = aaLevel * aaLevel + 1; PointD *aaPoints = stackalloc PointD[aaSamples]; for (int i = 0; i < aaSamples; ++i) { PointD pt = new PointD( ((i * aaLevel) / (float)aaSamples), i / (float)aaSamples); pt.X -= (int)pt.X; aaPoints[i] = pt; } int src_width = src.Width; ColorBgra *src_data_ptr = (ColorBgra *)src.DataPtr; foreach (var rect in rois) { for (int y = rect.Top; y < rect.Bottom; y++) { float j = y - hh; ColorBgra *dstPtr = dst.GetPointAddressUnchecked(rect.Left, y); ColorBgra *srcPtr = src.GetPointAddressUnchecked(src_data_ptr, src_width, rect.Left, y); for (int x = rect.Left; x < rect.Right; x++) { float i = x - hw; if (i * i + j * j > (maxrad + 1) * (maxrad + 1)) { *dstPtr = *srcPtr; } else { int b = 0; int g = 0; int r = 0; int a = 0; for (int p = 0; p < aaSamples; ++p) { float u = i + (float)aaPoints[p].X; float v = j + (float)aaPoints[p].Y; double rad = Math.Sqrt(u * u + v * v); double theta = Math.Atan2(v, u); double t = 1 - rad / maxrad; t = (t < 0) ? 0 : (t * t * t); theta += (t * twist) / 100; ColorBgra sample = src.GetPointUnchecked(src_data_ptr, src_width, (int)(hw + (float)(rad * Math.Cos(theta))), (int)(hh + (float)(rad * Math.Sin(theta)))); b += sample.B; g += sample.G; r += sample.R; a += sample.A; } *dstPtr = ColorBgra.FromBgra( (byte)(b / aaSamples), (byte)(g / aaSamples), (byte)(r / aaSamples), (byte)(a / aaSamples)); } ++dstPtr; ++srcPtr; } } } }
protected unsafe override void RenderLine(ISurface src, ISurface dest, Rectangle roi) { // Glow backgound glow_effect.Render(src, dest, roi); // Create black outlines by finding the edges of objects for (int y = roi.Top; y <= roi.Bottom; ++y) { int top = y - radius; int bottom = y + radius + 1; if (top < 0) { top = 0; } if (bottom > dest.Height) { bottom = dest.Height; } ColorBgra *srcPtr = src.GetPointAddress(roi.X, y); ColorBgra *dstPtr = dest.GetPointAddress(roi.X, y); for (int x = roi.Left; x <= roi.Right; ++x) { int left = x - radius; int right = x + radius + 1; if (left < 0) { left = 0; } if (right > dest.Width) { right = dest.Width; } int r = 0; int g = 0; int b = 0; for (int v = top; v < bottom; v++) { ColorBgra *pRow = src.GetRowAddress(v); int j = v - y + radius; for (int u = left; u < right; u++) { int i1 = u - x + radius; int w = conv[j][i1]; ColorBgra *pRef = pRow + u; r += pRef->R * w; g += pRef->G * w; b += pRef->B * w; } } ColorBgra topLayer = ColorBgra.FromBgr( Utility.ClampToByte(b), Utility.ClampToByte(g), Utility.ClampToByte(r)); // Desaturate topLayer = this.desaturate_op.Apply(topLayer); // Adjust Brightness and Contrast if (topLayer.R > (ink_outline * 255 / 100)) { topLayer = ColorBgra.FromBgra(255, 255, 255, topLayer.A); } else { topLayer = ColorBgra.FromBgra(0, 0, 0, topLayer.A); } // Change Blend Mode to Darken ColorBgra myPixel = this.darken_op.Apply(topLayer, *dstPtr); * dstPtr = myPixel; ++srcPtr; ++dstPtr; } } }