public unsafe static Image ApplyBlur(Bitmap bmp, int radius, bool expand) { if (expand) { bmp = (Bitmap)Core.AddCanvas(bmp, radius); } Bitmap bmp2 = new Bitmap(bmp.Width, bmp.Height); using (BitmapCache src = new BitmapCache(bmp, ImageLockMode.ReadWrite)) using (BitmapCache dst = new BitmapCache(bmp2, ImageLockMode.ReadWrite)) { int[] w = CreateGaussianBlurRow(radius); int wlen = w.Length; Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); if (rect.Height >= 1 && rect.Width >= 1) { for (int y = rect.Top; y < rect.Bottom; ++y) { long *waSums = stackalloc long[wlen]; long *wcSums = stackalloc long[wlen]; long *aSums = stackalloc long[wlen]; long *bSums = stackalloc long[wlen]; long *gSums = stackalloc long[wlen]; long *rSums = stackalloc long[wlen]; long waSum = 0; long wcSum = 0; long aSum = 0; long bSum = 0; long gSum = 0; long rSum = 0; ColorBgra *dstPtr = dst.GetPointAddress(rect.Left, y); for (int wx = 0; wx < wlen; ++wx) { int srcX = rect.Left + wx - radius; waSums[wx] = 0; wcSums[wx] = 0; aSums[wx] = 0; bSums[wx] = 0; gSums[wx] = 0; rSums[wx] = 0; if (srcX >= 0 && srcX < src.BitmapSize.Width) { for (int wy = 0; wy < wlen; ++wy) { int srcY = y + wy - radius; if (srcY >= 0 && srcY < src.BitmapSize.Height) { ColorBgra c = src.GetPoint(srcX, srcY); int wp = w[wy]; waSums[wx] += wp; wp *= c.A + (c.A >> 7); wcSums[wx] += wp; wp >>= 8; aSums[wx] += wp * c.A; bSums[wx] += wp * c.B; gSums[wx] += wp * c.G; rSums[wx] += wp * c.R; } } int wwx = w[wx]; waSum += wwx * waSums[wx]; wcSum += wwx * wcSums[wx]; aSum += wwx * aSums[wx]; bSum += wwx * bSums[wx]; gSum += wwx * gSums[wx]; rSum += wwx * rSums[wx]; } } wcSum >>= 8; if (waSum == 0 || wcSum == 0) { dstPtr->Bgra = 0; } else { int alpha = (int)(aSum / waSum); int blue = (int)(bSum / wcSum); int green = (int)(gSum / wcSum); int red = (int)(rSum / wcSum); dstPtr->Bgra = ColorBgra.BgraToUInt32(blue, green, red, alpha); } ++dstPtr; for (int x = rect.Left + 1; x < rect.Right; ++x) { for (int i = 0; i < wlen - 1; ++i) { waSums[i] = waSums[i + 1]; wcSums[i] = wcSums[i + 1]; aSums[i] = aSums[i + 1]; bSums[i] = bSums[i + 1]; gSums[i] = gSums[i + 1]; rSums[i] = rSums[i + 1]; } waSum = 0; wcSum = 0; aSum = 0; bSum = 0; gSum = 0; rSum = 0; int wx; for (wx = 0; wx < wlen - 1; ++wx) { long wwx = (long)w[wx]; waSum += wwx * waSums[wx]; wcSum += wwx * wcSums[wx]; aSum += wwx * aSums[wx]; bSum += wwx * bSums[wx]; gSum += wwx * gSums[wx]; rSum += wwx * rSums[wx]; } wx = wlen - 1; waSums[wx] = 0; wcSums[wx] = 0; aSums[wx] = 0; bSums[wx] = 0; gSums[wx] = 0; rSums[wx] = 0; int srcX = x + wx - radius; if (srcX >= 0 && srcX < src.BitmapSize.Width) { for (int wy = 0; wy < wlen; ++wy) { int srcY = y + wy - radius; if (srcY >= 0 && srcY < src.BitmapSize.Height) { ColorBgra c = src.GetPoint(srcX, srcY); int wp = w[wy]; waSums[wx] += wp; wp *= c.A + (c.A >> 7); wcSums[wx] += wp; wp >>= 8; aSums[wx] += wp * (long)c.A; bSums[wx] += wp * (long)c.B; gSums[wx] += wp * (long)c.G; rSums[wx] += wp * (long)c.R; } } int wr = w[wx]; waSum += (long)wr * waSums[wx]; wcSum += (long)wr * wcSums[wx]; aSum += (long)wr * aSums[wx]; bSum += (long)wr * bSums[wx]; gSum += (long)wr * gSums[wx]; rSum += (long)wr * rSums[wx]; } wcSum >>= 8; if (waSum == 0 || wcSum == 0) { dstPtr->Bgra = 0; } else { int alpha = (int)(aSum / waSum); int blue = (int)(bSum / wcSum); int green = (int)(gSum / wcSum); int red = (int)(rSum / wcSum); dstPtr->Bgra = ColorBgra.BgraToUInt32(blue, green, red, alpha); } ++dstPtr; } } } } return(bmp2); }
public unsafe override void Render(ImageSurface src, ImageSurface dest, Gdk.Rectangle[] rois) { if (Data.Radius == 0) { // Copy src to dest return; } int r = Data.Radius; int[] w = CreateGaussianBlurRow(r); int wlen = w.Length; int localStoreSize = wlen * 6 * sizeof(long); byte *localStore = stackalloc byte[localStoreSize]; byte *p = localStore; long *waSums = (long *)p; p += wlen * sizeof(long); long *wcSums = (long *)p; p += wlen * sizeof(long); long *aSums = (long *)p; p += wlen * sizeof(long); long *bSums = (long *)p; p += wlen * sizeof(long); long *gSums = (long *)p; p += wlen * sizeof(long); long *rSums = (long *)p; p += wlen * sizeof(long); // Cache these for a massive performance boost int src_width = src.Width; int src_height = src.Height; ColorBgra *src_data_ptr = (ColorBgra *)src.DataPtr; foreach (Gdk.Rectangle rect in rois) { if (rect.Height >= 1 && rect.Width >= 1) { for (int y = rect.Top; y <= rect.GetBottom(); ++y) { //Memory.SetToZero (localStore, (ulong)localStoreSize); long waSum = 0; long wcSum = 0; long aSum = 0; long bSum = 0; long gSum = 0; long rSum = 0; ColorBgra *dstPtr = dest.GetPointAddressUnchecked(rect.Left, y); for (int wx = 0; wx < wlen; ++wx) { int srcX = rect.Left + wx - r; waSums[wx] = 0; wcSums[wx] = 0; aSums[wx] = 0; bSums[wx] = 0; gSums[wx] = 0; rSums[wx] = 0; if (srcX >= 0 && srcX < src_width) { for (int wy = 0; wy < wlen; ++wy) { int srcY = y + wy - r; if (srcY >= 0 && srcY < src_height) { ColorBgra c = src.GetPointUnchecked(src_data_ptr, src_width, srcX, srcY); int wp = w[wy]; waSums[wx] += wp; wp *= c.A + (c.A >> 7); wcSums[wx] += wp; wp >>= 8; aSums[wx] += wp * c.A; bSums[wx] += wp * c.B; gSums[wx] += wp * c.G; rSums[wx] += wp * c.R; } } int wwx = w[wx]; waSum += wwx * waSums[wx]; wcSum += wwx * wcSums[wx]; aSum += wwx * aSums[wx]; bSum += wwx * bSums[wx]; gSum += wwx * gSums[wx]; rSum += wwx * rSums[wx]; } } wcSum >>= 8; if (waSum == 0 || wcSum == 0) { dstPtr->Bgra = 0; } else { int alpha = (int)(aSum / waSum); int blue = (int)(bSum / wcSum); int green = (int)(gSum / wcSum); int red = (int)(rSum / wcSum); dstPtr->Bgra = ColorBgra.BgraToUInt32(blue, green, red, alpha); } ++dstPtr; for (int x = rect.Left + 1; x <= rect.GetRight(); ++x) { for (int i = 0; i < wlen - 1; ++i) { waSums[i] = waSums[i + 1]; wcSums[i] = wcSums[i + 1]; aSums[i] = aSums[i + 1]; bSums[i] = bSums[i + 1]; gSums[i] = gSums[i + 1]; rSums[i] = rSums[i + 1]; } waSum = 0; wcSum = 0; aSum = 0; bSum = 0; gSum = 0; rSum = 0; int wx; for (wx = 0; wx < wlen - 1; ++wx) { long wwx = (long)w[wx]; waSum += wwx * waSums[wx]; wcSum += wwx * wcSums[wx]; aSum += wwx * aSums[wx]; bSum += wwx * bSums[wx]; gSum += wwx * gSums[wx]; rSum += wwx * rSums[wx]; } wx = wlen - 1; waSums[wx] = 0; wcSums[wx] = 0; aSums[wx] = 0; bSums[wx] = 0; gSums[wx] = 0; rSums[wx] = 0; int srcX = x + wx - r; if (srcX >= 0 && srcX < src_width) { for (int wy = 0; wy < wlen; ++wy) { int srcY = y + wy - r; if (srcY >= 0 && srcY < src_height) { ColorBgra c = src.GetPointUnchecked(src_data_ptr, src_width, srcX, srcY); int wp = w[wy]; waSums[wx] += wp; wp *= c.A + (c.A >> 7); wcSums[wx] += wp; wp >>= 8; aSums[wx] += wp * (long)c.A; bSums[wx] += wp * (long)c.B; gSums[wx] += wp * (long)c.G; rSums[wx] += wp * (long)c.R; } } int wr = w[wx]; waSum += (long)wr * waSums[wx]; wcSum += (long)wr * wcSums[wx]; aSum += (long)wr * aSums[wx]; bSum += (long)wr * bSums[wx]; gSum += (long)wr * gSums[wx]; rSum += (long)wr * rSums[wx]; } wcSum >>= 8; if (waSum == 0 || wcSum == 0) { dstPtr->Bgra = 0; } else { int alpha = (int)(aSum / waSum); int blue = (int)(bSum / wcSum); int green = (int)(gSum / wcSum); int red = (int)(rSum / wcSum); dstPtr->Bgra = ColorBgra.BgraToUInt32(blue, green, red, alpha); } ++dstPtr; } } } } }
public override void Render(Surface src, Surface dst, Rectangle[] rois, int startIndex, int length) { unsafe { if (this.radius == 0) { for (int ri = startIndex; ri < startIndex + length; ++ri) { dst.CopySurface(src, rois[ri].Location, rois[ri]); } return; } int r = this.radius; int[] w = CreateGaussianBlurRow(r); int wlen = w.Length; int localStoreSize = wlen * 6 * sizeof(long); byte *localStore = stackalloc byte[localStoreSize]; byte *p = localStore; long *waSums = (long *)p; p += wlen * sizeof(long); long *wcSums = (long *)p; p += wlen * sizeof(long); long *aSums = (long *)p; p += wlen * sizeof(long); long *bSums = (long *)p; p += wlen * sizeof(long); long *gSums = (long *)p; p += wlen * sizeof(long); long *rSums = (long *)p; p += wlen * sizeof(long); ulong arraysLength = (ulong)(sizeof(long) * wlen); for (int ri = startIndex; ri < startIndex + length; ++ri) { Rectangle rect = rois[ri]; if (rect.Height >= 1 && rect.Width >= 1) { for (int y = rect.Top; y < rect.Bottom; ++y) { PlatformMemory.SetToZero(localStore, (ulong)localStoreSize); long waSum = 0; long wcSum = 0; long aSum = 0; long bSum = 0; long gSum = 0; long rSum = 0; ColorBgra *dstPtr = dst.GetPointAddressUnchecked(rect.Left, y); for (int wx = 0; wx < wlen; ++wx) { int srcX = rect.Left + wx - r; waSums[wx] = 0; wcSums[wx] = 0; aSums[wx] = 0; bSums[wx] = 0; gSums[wx] = 0; rSums[wx] = 0; if (srcX >= 0 && srcX < src.Width) { for (int wy = 0; wy < wlen; ++wy) { int srcY = y + wy - r; if (srcY >= 0 && srcY < src.Height) { ColorBgra c = src.GetPointUnchecked(srcX, srcY); int wp = w[wy]; waSums[wx] += wp; wp *= c.A + (c.A >> 7); wcSums[wx] += wp; wp >>= 8; aSums[wx] += wp * c.A; bSums[wx] += wp * c.B; gSums[wx] += wp * c.G; rSums[wx] += wp * c.R; } } int wwx = w[wx]; waSum += wwx * waSums[wx]; wcSum += wwx * wcSums[wx]; aSum += wwx * aSums[wx]; bSum += wwx * bSums[wx]; gSum += wwx * gSums[wx]; rSum += wwx * rSums[wx]; } } wcSum >>= 8; if (waSum == 0 || wcSum == 0) { dstPtr->Bgra = 0; } else { int alpha = (int)(aSum / waSum); int blue = (int)(bSum / wcSum); int green = (int)(gSum / wcSum); int red = (int)(rSum / wcSum); dstPtr->Bgra = ColorBgra.BgraToUInt32(blue, green, red, alpha); } ++dstPtr; for (int x = rect.Left + 1; x < rect.Right; ++x) { for (int i = 0; i < wlen - 1; ++i) { waSums[i] = waSums[i + 1]; wcSums[i] = wcSums[i + 1]; aSums[i] = aSums[i + 1]; bSums[i] = bSums[i + 1]; gSums[i] = gSums[i + 1]; rSums[i] = rSums[i + 1]; } waSum = 0; wcSum = 0; aSum = 0; bSum = 0; gSum = 0; rSum = 0; int wx; for (wx = 0; wx < wlen - 1; ++wx) { long wwx = (long)w[wx]; waSum += wwx * waSums[wx]; wcSum += wwx * wcSums[wx]; aSum += wwx * aSums[wx]; bSum += wwx * bSums[wx]; gSum += wwx * gSums[wx]; rSum += wwx * rSums[wx]; } wx = wlen - 1; waSums[wx] = 0; wcSums[wx] = 0; aSums[wx] = 0; bSums[wx] = 0; gSums[wx] = 0; rSums[wx] = 0; int srcX = x + wx - r; if (srcX >= 0 && srcX < src.Width) { for (int wy = 0; wy < wlen; ++wy) { int srcY = y + wy - r; if (srcY >= 0 && srcY < src.Height) { ColorBgra c = src.GetPointUnchecked(srcX, srcY); int wp = w[wy]; waSums[wx] += wp; wp *= c.A + (c.A >> 7); wcSums[wx] += wp; wp >>= 8; aSums[wx] += wp * (long)c.A; bSums[wx] += wp * (long)c.B; gSums[wx] += wp * (long)c.G; rSums[wx] += wp * (long)c.R; } } int wr = w[wx]; waSum += (long)wr * waSums[wx]; wcSum += (long)wr * wcSums[wx]; aSum += (long)wr * aSums[wx]; bSum += (long)wr * bSums[wx]; gSum += (long)wr * gSums[wx]; rSum += (long)wr * rSums[wx]; } wcSum >>= 8; if (waSum == 0 || wcSum == 0) { dstPtr->Bgra = 0; } else { int alpha = (int)(aSum / waSum); int blue = (int)(bSum / wcSum); int green = (int)(gSum / wcSum); int red = (int)(rSum / wcSum); dstPtr->Bgra = ColorBgra.BgraToUInt32(blue, green, red, alpha); } ++dstPtr; } } } } } }
private unsafe void OnRenderImpl <TMaskSampler>(ISurface <ColorBgra> dstContent, PointInt32 renderOffset, ref TMaskSampler baseMaskSampler) where TMaskSampler : IMaskSampler { if (Interlocked.Exchange(ref this.isLazyDeltaSelectionMaskFirstTimePrefetched, 1) == 0) { this.lazyDeltaSelectionMask.EnsureEvaluated(); } else if (Interlocked.Exchange(ref this.isLazyFinalSelectionMaskFirstTimePrefetched, 1) == 0) { this.lazyFinalSelectionMask.EnsureEvaluated(); } base.ThrowIfCancellationRequested(); int width = dstContent.Width; int height = dstContent.Height; ColorBgra *bgraPtr = (ColorBgra *)dstContent.Scan0; int stride = dstContent.Stride; int num4 = stride - (width * 4); RectInt32 bounds = new RectInt32(renderOffset.X, renderOffset.Y, width, height); uint num6 = this.changes.BackFillColor.Bgra; using (ISurface <ColorAlpha8> surface = alpha8Allocator.Allocate(width, height, AllocationOptions.ZeroFillNotRequired)) { base.ThrowIfCancellationRequested(); this.sourceTx.Render(dstContent, surface, renderOffset); base.ThrowIfCancellationRequested(); using (ISurface <ColorAlpha8> surface2 = this.lazyFinalSelectionMask.Value.UseTileOrToSurface(bounds)) { base.ThrowIfCancellationRequested(); ColorBgra *pointAddress = this.activeLayer.Surface.GetPointAddress(renderOffset.X, renderOffset.Y); int num7 = this.activeLayer.Surface.Stride - (width * 4); byte * numPtr = (byte *)surface2.Scan0; int num8 = surface2.Stride - bounds.Width; byte * numPtr2 = (byte *)surface.Scan0; int num9 = surface.Stride - bounds.Width; ColorBgra *bgraPtr3 = bgraPtr + width; baseMaskSampler.Initialize(); for (int i = 0; i < height; i++) { for (ColorBgra *bgraPtr4 = bgraPtr3 - width; bgraPtr4 < bgraPtr3; bgraPtr4++) { byte next = baseMaskSampler.GetNext(); byte num12 = numPtr[0]; byte num13 = numPtr2[0]; byte num14 = Math.Min(num13, num12); if (num14 == 0) { byte frac = (byte)(0xff - next); if (frac == 0) { bgraPtr4->Bgra = num6; } else { ColorBgra bgra = pointAddress[0]; if (frac != 0xff) { bgra.A = ByteUtil.FastScale(bgra.A, frac); } bgraPtr4->Bgra = bgra.Bgra; } } else if (num14 != 0xff) { byte num16 = Math.Min((byte)(0xff - num14), (byte)(0xff - next)); ColorBgra bgra2 = bgraPtr4[0]; ColorBgra bgra3 = pointAddress[0]; ushort d = (ushort)((bgra3.A * num16) + (bgra2.A * num14)); if (d == 0) { bgraPtr4->Bgra = num6; } else { int num18 = UInt16Util.FastDivideBy255((ushort)((bgra3.A * num16) + (bgra2.A * num14))); uint num19 = UInt32Util.FastDivideByUInt16((uint)(((bgra3.A * num16) * bgra3.B) + ((bgra2.A * num14) * bgra2.B)), d); uint num20 = UInt32Util.FastDivideByUInt16((uint)(((bgra3.A * num16) * bgra3.G) + ((bgra2.A * num14) * bgra2.G)), d); uint num21 = UInt32Util.FastDivideByUInt16((uint)(((bgra3.A * num16) * bgra3.R) + ((bgra2.A * num14) * bgra2.R)), d); bgraPtr4->Bgra = ColorBgra.BgraToUInt32((byte)num19, (byte)num20, (byte)num21, (byte)num18); } } pointAddress++; numPtr++; numPtr2++; } pointAddress += num7; baseMaskSampler.MoveToNextRow(); numPtr += num8; numPtr2 += num9; bgraPtr3 += stride; base.ThrowIfCancellationRequested(); } } } }
public override unsafe void Render(EffectConfigToken parameters, RenderArgs dstArgs, RenderArgs srcArgs, Rectangle[] rois, int startIndex, int length) { AmountEffectConfigToken bect = (AmountEffectConfigToken)parameters; Surface dst = dstArgs.Surface; Surface src = srcArgs.Surface; int r = bect.Amount; int[] w = CreateGaussianBlurRow(bect.Amount); int wlen = w.Length; for (int ri = startIndex; ri < startIndex + length; ++ri) { Rectangle rect = rois[ri]; if (rect.Height >= 1 && rect.Width >= 1) { for (int y = rect.Top; y < rect.Bottom; ++y) { long * waSums = stackalloc long[wlen]; long * wcSums = stackalloc long[wlen]; long * aSums = stackalloc long[wlen]; long * bSums = stackalloc long[wlen]; long * gSums = stackalloc long[wlen]; long * rSums = stackalloc long[wlen]; long waSum = 0; long wcSum = 0; long aSum = 0; long bSum = 0; long gSum = 0; long rSum = 0; ColorBgra *dstPtr = dst.GetPointAddressUnchecked(rect.Left, y); for (int wx = 0; wx < wlen; ++wx) { int srcX = rect.Left + wx - r; waSums[wx] = 0; wcSums[wx] = 0; aSums[wx] = 0; bSums[wx] = 0; gSums[wx] = 0; rSums[wx] = 0; if (srcX >= 0 && srcX < src.Width) { for (int wy = 0; wy < wlen; ++wy) { int srcY = y + wy - r; if (srcY >= 0 && srcY < src.Height) { ColorBgra c = src.GetPointUnchecked(srcX, srcY); int wp = w[wy]; waSums[wx] += wp; wp *= c.A + (c.A >> 7); wcSums[wx] += wp; wp >>= 8; aSums[wx] += wp * c.A; bSums[wx] += wp * c.B; gSums[wx] += wp * c.G; rSums[wx] += wp * c.R; } } int wwx = w[wx]; waSum += wwx * waSums[wx]; wcSum += wwx * wcSums[wx]; aSum += wwx * aSums[wx]; bSum += wwx * bSums[wx]; gSum += wwx * gSums[wx]; rSum += wwx * rSums[wx]; } } wcSum >>= 8; if (waSum == 0 || wcSum == 0) { dstPtr->Bgra = 0; } else { int alpha = (int)(aSum / waSum); int blue = (int)(bSum / wcSum); int green = (int)(gSum / wcSum); int red = (int)(rSum / wcSum); dstPtr->Bgra = ColorBgra.BgraToUInt32(blue, green, red, alpha); } ++dstPtr; for (int x = rect.Left + 1; x < rect.Right; ++x) { for (int i = 0; i < wlen - 1; ++i) { waSums[i] = waSums[i + 1]; wcSums[i] = wcSums[i + 1]; aSums[i] = aSums[i + 1]; bSums[i] = bSums[i + 1]; gSums[i] = gSums[i + 1]; rSums[i] = rSums[i + 1]; } waSum = 0; wcSum = 0; aSum = 0; bSum = 0; gSum = 0; rSum = 0; int wx; for (wx = 0; wx < wlen - 1; ++wx) { long wwx = (long)w[wx]; waSum += wwx * waSums[wx]; wcSum += wwx * wcSums[wx]; aSum += wwx * aSums[wx]; bSum += wwx * bSums[wx]; gSum += wwx * gSums[wx]; rSum += wwx * rSums[wx]; } wx = wlen - 1; waSums[wx] = 0; wcSums[wx] = 0; aSums[wx] = 0; bSums[wx] = 0; gSums[wx] = 0; rSums[wx] = 0; int srcX = x + wx - r; if (srcX >= 0 && srcX < src.Width) { for (int wy = 0; wy < wlen; ++wy) { int srcY = y + wy - r; if (srcY >= 0 && srcY < src.Height) { ColorBgra c = src.GetPointUnchecked(srcX, srcY); int wp = w[wy]; waSums[wx] += wp; wp *= c.A + (c.A >> 7); wcSums[wx] += wp; wp >>= 8; aSums[wx] += wp * (long)c.A; bSums[wx] += wp * (long)c.B; gSums[wx] += wp * (long)c.G; rSums[wx] += wp * (long)c.R; } } int wr = w[wx]; waSum += (long)wr * waSums[wx]; wcSum += (long)wr * wcSums[wx]; aSum += (long)wr * aSums[wx]; bSum += (long)wr * bSums[wx]; gSum += (long)wr * gSums[wx]; rSum += (long)wr * rSums[wx]; } wcSum >>= 8; if (waSum == 0 || wcSum == 0) { dstPtr->Bgra = 0; } else { int alpha = (int)(aSum / waSum); int blue = (int)(bSum / wcSum); int green = (int)(gSum / wcSum); int red = (int)(rSum / wcSum); dstPtr->Bgra = ColorBgra.BgraToUInt32(blue, green, red, alpha); } ++dstPtr; } } } } }
private unsafe void RenderRectangle(Surface dst, Surface src, Rectangle rect) { double shadowFactor = (double)(Token.GetProperty <Int32Property>("ShadowEffect.Alpha").Value) / 255.0; // The blurring algorithm was stolen directly from the BlurEffect code. I couldn't // use it directly because the source image must be transformed prior to applying // the blur effect. Also, I gradually increase the blur radius from one end // of the shadow to the other, which the blur effect code doesn't support either. if (rect.Height >= 1 && rect.Width >= 1) { // For each row in the rectangle for (int y = rect.Top; y < rect.Bottom; ++y) { double radius = invertedYcoordinate(y, src.Height) / (double)rowsPerBlurRadius; int[] w = CreateGaussianBlurRow(radius); int wlen = w.Length; int r = (wlen - 1) / 2; long[] waSums = new long[wlen]; long[] aSums = new long[wlen]; long waSum = 0; long aSum = 0; ColorBgra *dstPtr = dst.GetPointAddressUnchecked(rect.Left, y); // For each item in the gaussian blur row for (int wx = 0; wx < wlen; ++wx) { int srcX = rect.Left + wx - r; waSums[wx] = 0; aSums[wx] = 0; if (srcX >= 0 && srcX < src.Width) { for (int wy = 0; wy < wlen; ++wy) { int srcY = y + wy - r; if (srcY >= 0 && srcY < src.Height) { ColorBgra c = getShadowPixel(srcX, srcY, src, shadowFactor, (int)Token.GetProperty <DoubleProperty>("ShadowEffect.ShadowAngle").Value, (int)Token.GetProperty <DoubleProperty>("ShadowEffect.ShadowDepthAngle").Value); int wp = w[wy]; waSums[wx] += wp; aSums[wx] += wp * c.A; } } int wwx = w[wx]; waSum += wwx * waSums[wx]; aSum += wwx * aSums[wx]; } } if (waSum == 0) { dstPtr->Bgra = 0; } else { dstPtr->Bgra = ColorBgra.BgraToUInt32(0, 0, 0, (int)(aSum / waSum)); } ++dstPtr; for (int x = rect.Left + 1; x < rect.Right; ++x) { ColorBgra OrginalImage = src[x, y]; for (int i = 0; i < wlen - 1; ++i) { waSums[i] = waSums[i + 1]; aSums[i] = aSums[i + 1]; } waSum = 0; aSum = 0; int wx; for (wx = 0; wx < wlen - 1; ++wx) { long wwx = (long)w[wx]; waSum += wwx * waSums[wx]; aSum += wwx * aSums[wx]; } wx = wlen - 1; waSums[wx] = 0; aSums[wx] = 0; int srcX = x + wx - r; if (srcX >= 0 && srcX < src.Width) { for (int wy = 0; wy < wlen; ++wy) { int srcY = y + wy - r; if (srcY >= 0 && srcY < src.Height) { ColorBgra c = getShadowPixel(srcX, srcY, src, shadowFactor, (int)Token.GetProperty <DoubleProperty>("ShadowEffect.ShadowAngle").Value, (int)Token.GetProperty <DoubleProperty>("ShadowEffect.ShadowDepthAngle").Value); int wp = w[wy]; waSums[wx] += wp; aSums[wx] += wp * (long)c.A; } } int wr = w[wx]; waSum += (long)wr * waSums[wx]; aSum += (long)wr * aSums[wx]; } ColorBgra Shadow = new ColorBgra(); if (waSum == 0) { Shadow = ColorBgra.FromBgra(0, 0, 0, 0); } else { Shadow = ColorBgra.FromBgra(0, 0, 0, (byte)(aSum / waSum)); } if (Token.GetProperty <BooleanProperty>("ShadowEffect.OriginalImage").Value) { dstPtr->Bgra = (uint)normalOp.Apply(Shadow, OrginalImage); } else { dstPtr->Bgra = (uint)Shadow; } ++dstPtr; } } } }
private unsafe void RenderContent(ISurface <ColorBgra> dstContent, PointInt32 renderOffset) { int width = dstContent.Width; int height = dstContent.Height; int stride = dstContent.Stride; int num4 = stride - (width * 4); RectInt32 num5 = RectInt32.Intersect(this.srcCoverageBounds, new RectInt32(0, 0, this.contentWidth, this.contentHeight)); int left = num5.Left; int top = num5.Top; int right = num5.Right; int bottom = num5.Bottom; long num10 = (this.srcOffsetOriginXFp + (renderOffset.X * this.srcOffsetDxDxFp)) + (renderOffset.Y * this.srcOffsetDxDyFp); long num11 = (this.srcOffsetOriginYFp + (renderOffset.X * this.srcOffsetDyDxFp)) + (renderOffset.Y * this.srcOffsetDyDyFp); ColorBgra *bgraPtr = this.contentScan0; int contentStride = this.contentStride; ColorBgra *bgraPtr2 = (ColorBgra *)dstContent.Scan0; ColorBgra *bgraPtr3 = bgraPtr2 + width; for (int i = 0; i < height; i++) { uint num16; int num17; base.ThrowIfCancellationRequested(); long num14 = num10; long num15 = num11; ColorBgra *bgraPtr4 = bgraPtr3 - width; int num18 = (int)((long)((bgraPtr3 - bgraPtr4) / sizeof(ColorBgra))); int num19 = (int)(num14 >> 0x18); int num20 = (int)(num15 >> 0x18); int num21 = ((num19 >= left) && (num19 < right)) ? 1 : 0; int num22 = ((num20 >= top) && (num20 < bottom)) ? 1 : 0; int num23 = ((num19 >= (left - 1)) && (num19 < (right - 1))) ? 1 : 0; int num24 = ((num20 >= (top - 1)) && (num20 < (bottom - 1))) ? 1 : 0; long num25 = num14 + (this.srcOffsetDxDxFp * num18); long num26 = num15 + (this.srcOffsetDyDxFp * num18); int num27 = (int)(num25 >> 0x18); int num28 = (int)(num26 >> 0x18); int num29 = ((num27 >= left) && (num27 < right)) ? 1 : 0; int num30 = ((num28 >= top) && (num28 < bottom)) ? 1 : 0; int num31 = ((num27 >= (left - 1)) && (num27 < (right - 1))) ? 1 : 0; int num32 = ((num28 >= (top - 1)) && (num28 < (bottom - 1))) ? 1 : 0; if ((((((((num21 + num22) + num23) + num24) + num29) + num30) + num31) + num32) == 8) { num17 = num18; } else { num17 = 0; } while ((bgraPtr4 < bgraPtr3) && (num17 > 0)) { num16 = 0; int num33 = (int)(num14 >> 0x18); int num34 = (int)(num15 >> 0x18); int num35 = 0x100 - (((int)(num14 & 0xffffffL)) >> 0x10); int num36 = 0x100 - (((int)(num15 & 0xffffffL)) >> 0x10); int num37 = (num35 * num36) >> 8; int num38 = ((0x100 - num35) * num36) >> 8; int num39 = (num35 * (0x100 - num36)) >> 8; int num40 = ((0x100 - num35) * (0x100 - num36)) >> 8; int num41 = num37; int num42 = num38; int num43 = num39; int num44 = num40; ushort d = (ushort)(((num41 + num42) + num43) + num44); long num46 = (num34 * contentStride) + (num33 * 4); ColorBgra32 bgra = *((ColorBgra32 *)(bgraPtr + num46)); ColorBgra32 bgra2 = *((ColorBgra32 *)(bgraPtr + (num46 + 4L))); ColorBgra32 bgra3 = *((ColorBgra32 *)(bgraPtr + (num46 + contentStride))); ColorBgra32 bgra4 = *((ColorBgra32 *)(bgraPtr + ((num46 + contentStride) + 4L))); int num47 = bgra.A * num41; int num48 = bgra2.A * num42; int num49 = bgra3.A * num43; int num50 = bgra4.A * num44; ushort n = (ushort)(((num47 + num48) + num49) + num50); if (n != 0) { uint num52 = UInt32Util.FastDivideByUInt16(n, d); uint num53 = UInt32Util.FastDivideByUInt16((uint)((((num47 * bgra.B) + (num48 * bgra2.B)) + (num49 * bgra3.B)) + (num50 * bgra4.B)), n); uint num54 = UInt32Util.FastDivideByUInt16((uint)((((num47 * bgra.G) + (num48 * bgra2.G)) + (num49 * bgra3.G)) + (num50 * bgra4.G)), n); uint num55 = UInt32Util.FastDivideByUInt16((uint)((((num47 * bgra.R) + (num48 * bgra2.R)) + (num49 * bgra3.R)) + (num50 * bgra4.R)), n); num16 = ColorBgra.BgraToUInt32((byte)num53, (byte)num54, (byte)num55, (byte)num52); } bgraPtr4->Bgra = num16; num14 += this.srcOffsetDxDxFp; num15 += this.srcOffsetDyDxFp; bgraPtr4++; num17--; } while (bgraPtr4 < bgraPtr3) { num16 = 0; int num56 = (int)(num14 >> 0x18); int num57 = (int)(num15 >> 0x18); int num58 = ((num56 >= left) && (num56 < right)) ? 1 : 0; int num59 = ((num57 >= top) && (num57 < bottom)) ? 1 : 0; int num60 = ((num56 >= (left - 1)) && (num56 < (right - 1))) ? 1 : 0; int num61 = ((num57 >= (top - 1)) && (num57 < (bottom - 1))) ? 1 : 0; int num62 = num59 * num58; int num63 = num59 * num60; int num64 = num61 * num58; int num65 = num61 * num60; if ((((num62 + num63) + num64) + num65) != 0) { int num67 = 0x100 - (((int)(num14 & 0xffffffL)) >> 0x10); int num68 = 0x100 - (((int)(num15 & 0xffffffL)) >> 0x10); int num69 = (num67 * num68) >> 8; int num70 = ((0x100 - num67) * num68) >> 8; int num71 = (num67 * (0x100 - num68)) >> 8; int num72 = ((0x100 - num67) * (0x100 - num68)) >> 8; int num73 = num62 * num69; int num74 = num63 * num70; int num75 = num64 * num71; int num76 = num65 * num72; ushort num77 = (ushort)(((num73 + num74) + num75) + num76); long num78 = (num57 * contentStride) + (num56 * 4); ColorBgra32 bgra5 = *((ColorBgra32 *)(bgraPtr + (num78 * num62))); ColorBgra32 bgra6 = *((ColorBgra32 *)(bgraPtr + ((num78 + 4L) * num63))); ColorBgra32 bgra7 = *((ColorBgra32 *)(bgraPtr + ((num78 + contentStride) * num64))); ColorBgra32 bgra8 = *((ColorBgra32 *)(bgraPtr + (((num78 + contentStride) + 4L) * num65))); int num79 = bgra5.A * num73; int num80 = bgra6.A * num74; int num81 = bgra7.A * num75; int num82 = bgra8.A * num76; ushort num83 = (ushort)(((num79 + num80) + num81) + num82); if (num83 != 0) { uint num84 = UInt32Util.FastDivideByUInt16(num83, num77); uint num85 = UInt32Util.FastDivideByUInt16((uint)((((num79 * bgra5.B) + (num80 * bgra6.B)) + (num81 * bgra7.B)) + (num82 * bgra8.B)), num83); uint num86 = UInt32Util.FastDivideByUInt16((uint)((((num79 * bgra5.G) + (num80 * bgra6.G)) + (num81 * bgra7.G)) + (num82 * bgra8.G)), num83); uint num87 = UInt32Util.FastDivideByUInt16((uint)((((num79 * bgra5.R) + (num80 * bgra6.R)) + (num81 * bgra7.R)) + (num82 * bgra8.R)), num83); num16 = ColorBgra.BgraToUInt32((byte)num85, (byte)num86, (byte)num87, (byte)num84); } } bgraPtr4->Bgra = num16; num14 += this.srcOffsetDxDxFp; num15 += this.srcOffsetDyDxFp; bgraPtr4++; } num10 += this.srcOffsetDxDyFp; num11 += this.srcOffsetDyDyFp; bgraPtr3 += stride; } }
protected unsafe override void RenderLine(ISurface src, ISurface dest, Rectangle rect) { if (radius == 0) { // Copy src to dest return; } int r = radius; int wlen = w.Length; int localStoreSize = wlen * 6 * sizeof(long); byte *localStore = stackalloc byte[localStoreSize]; byte *p = localStore; long *waSums = (long *)p; p += wlen * sizeof(long); long *wcSums = (long *)p; p += wlen * sizeof(long); long *aSums = (long *)p; p += wlen * sizeof(long); long *bSums = (long *)p; p += wlen * sizeof(long); long *gSums = (long *)p; p += wlen * sizeof(long); long *rSums = (long *)p; p += wlen * sizeof(long); int src_width = src.Width; int src_height = src.Height; if (rect.Height >= 1 && rect.Width >= 1) { for (int y = rect.Top; y <= rect.Bottom; ++y) { //Memory.SetToZero (localStore, (ulong)localStoreSize); long waSum = 0; long wcSum = 0; long aSum = 0; long bSum = 0; long gSum = 0; long rSum = 0; ColorBgra *dstPtr = dest.GetPointAddress(rect.Left, y); for (int wx = 0; wx < wlen; ++wx) { int srcX = rect.Left + wx - r; waSums[wx] = 0; wcSums[wx] = 0; aSums[wx] = 0; bSums[wx] = 0; gSums[wx] = 0; rSums[wx] = 0; if (srcX >= 0 && srcX < src_width) { for (int wy = 0; wy < wlen; ++wy) { int srcY = y + wy - r; if (srcY >= 0 && srcY < src_height) { ColorBgra c = src.GetPoint(srcX, srcY); int wp = w[wy]; waSums[wx] += wp; wp *= c.A + (c.A >> 7); wcSums[wx] += wp; wp >>= 8; aSums[wx] += wp * c.A; bSums[wx] += wp * c.B; gSums[wx] += wp * c.G; rSums[wx] += wp * c.R; } } int wwx = w[wx]; waSum += wwx * waSums[wx]; wcSum += wwx * wcSums[wx]; aSum += wwx * aSums[wx]; bSum += wwx * bSums[wx]; gSum += wwx * gSums[wx]; rSum += wwx * rSums[wx]; } } wcSum >>= 8; if (waSum == 0 || wcSum == 0) { dstPtr->Bgra = 0; } else { int alpha = (int)(aSum / waSum); int blue = (int)(bSum / wcSum); int green = (int)(gSum / wcSum); int red = (int)(rSum / wcSum); dstPtr->Bgra = ColorBgra.BgraToUInt32(blue, green, red, alpha); } ++dstPtr; for (int x = rect.Left + 1; x <= rect.Right; ++x) { for (int i = 0; i < wlen - 1; ++i) { waSums[i] = waSums[i + 1]; wcSums[i] = wcSums[i + 1]; aSums[i] = aSums[i + 1]; bSums[i] = bSums[i + 1]; gSums[i] = gSums[i + 1]; rSums[i] = rSums[i + 1]; } waSum = 0; wcSum = 0; aSum = 0; bSum = 0; gSum = 0; rSum = 0; int wx; for (wx = 0; wx < wlen - 1; ++wx) { long wwx = (long)w[wx]; waSum += wwx * waSums[wx]; wcSum += wwx * wcSums[wx]; aSum += wwx * aSums[wx]; bSum += wwx * bSums[wx]; gSum += wwx * gSums[wx]; rSum += wwx * rSums[wx]; } wx = wlen - 1; waSums[wx] = 0; wcSums[wx] = 0; aSums[wx] = 0; bSums[wx] = 0; gSums[wx] = 0; rSums[wx] = 0; int srcX = x + wx - r; if (srcX >= 0 && srcX < src_width) { for (int wy = 0; wy < wlen; ++wy) { int srcY = y + wy - r; if (srcY >= 0 && srcY < src_height) { ColorBgra c = src.GetPoint(srcX, srcY); int wp = w[wy]; waSums[wx] += wp; wp *= c.A + (c.A >> 7); wcSums[wx] += wp; wp >>= 8; aSums[wx] += wp * (long)c.A; bSums[wx] += wp * (long)c.B; gSums[wx] += wp * (long)c.G; rSums[wx] += wp * (long)c.R; } } int wr = w[wx]; waSum += (long)wr * waSums[wx]; wcSum += (long)wr * wcSums[wx]; aSum += (long)wr * aSums[wx]; bSum += (long)wr * bSums[wx]; gSum += (long)wr * gSums[wx]; rSum += (long)wr * rSums[wx]; } wcSum >>= 8; if (waSum == 0 || wcSum == 0) { dstPtr->Bgra = 0; } else { int alpha = (int)(aSum / waSum); int blue = (int)(bSum / wcSum); int green = (int)(gSum / wcSum); int red = (int)(rSum / wcSum); dstPtr->Bgra = ColorBgra.BgraToUInt32(blue, green, red, alpha); } ++dstPtr; } } } }
/// <summary> /// Creates the shadow of the source image /// </summary> /// <param name="dst">Describes the destination surface.</param> /// <param name="src">Describes the source surface.</param> /// <param name="rect">The rectangle that describes the region of interest.</param> /// <param name="configuration"></param> /// private unsafe void RenderRectangle(Surface dst, Surface src, Rectangle rect, ShadowEffectConfiguration configuration) { double shadowFactor = configuration.Opacity / ShadowEffectProperties.MaxOpacity; // // The blurring algorithm was stolen directly from the BlurEffect code. I couldn't // use it directly because the source image must be transformed prior to applying // the blur effect. Also, I gradually increase the blur radius from one end // of the shadow to the other, which the blur effect code doesn't support either. // if (rect.Height >= 1 && rect.Width >= 1) { // For each row in the rectangle for (int y = rect.Top; y < rect.Bottom; ++y) { // // Shadow Diffusion - The blur radius increases the further the row is from the bottom // Diffusion Factor - [0-100] How much the shadow is diffused. 0 = None, 100 = Max // double blurRadius = 0; if (configuration.DiffusionFactor > 0) { // diffusion factor of 50 = 5 rows/blur_radius double rowsPerBlurRadius = 250.0 / (double)configuration.DiffusionFactor; blurRadius = invertedYcoordinate(y, src.Height) / rowsPerBlurRadius; } int[] w = CreateGaussianBlurRow(blurRadius); int wlen = w.Length; int r = (wlen - 1) / 2; long[] waSums = new long[wlen]; long[] aSums = new long[wlen]; long waSum = 0; long aSum = 0; ColorBgra *dstPtr = dst.GetPointAddressUnchecked(rect.Left, y); // For each item in the gaussian blur row for (int wx = 0; wx < wlen; ++wx) { int srcX = rect.Left + wx - r; waSums[wx] = 0; aSums[wx] = 0; if (srcX >= 0 && srcX < src.Width) { for (int wy = 0; wy < wlen; ++wy) { int srcY = y + wy - r; if (srcY >= 0 && srcY < src.Height) { ColorBgra c = getShadowPixel(srcX, srcY, src, shadowFactor, configuration.Angle, configuration.DepthAngle); int wp = w[wy]; waSums[wx] += wp; aSums[wx] += wp * c.A; } } int wwx = w[wx]; waSum += wwx * waSums[wx]; aSum += wwx * aSums[wx]; } } if (waSum == 0) { dstPtr->Bgra = 0; } else { dstPtr->Bgra = ColorBgra.BgraToUInt32(0, 0, 0, (int)(aSum / waSum)); } ++dstPtr; for (int x = rect.Left + 1; x < rect.Right; ++x) { ColorBgra OrginalImage = src[x, y]; for (int i = 0; i < wlen - 1; ++i) { waSums[i] = waSums[i + 1]; aSums[i] = aSums[i + 1]; } waSum = 0; aSum = 0; int wx; for (wx = 0; wx < wlen - 1; ++wx) { long wwx = (long)w[wx]; waSum += wwx * waSums[wx]; aSum += wwx * aSums[wx]; } wx = wlen - 1; waSums[wx] = 0; aSums[wx] = 0; int srcX = x + wx - r; if (srcX >= 0 && srcX < src.Width) { for (int wy = 0; wy < wlen; ++wy) { int srcY = y + wy - r; if (srcY >= 0 && srcY < src.Height) { ColorBgra c = getShadowPixel(srcX, srcY, src, shadowFactor, configuration.Angle, configuration.DepthAngle); int wp = w[wy]; waSums[wx] += wp; aSums[wx] += wp * (long)c.A; } } int wr = w[wx]; waSum += (long)wr * waSums[wx]; aSum += (long)wr * aSums[wx]; } ColorBgra Shadow = new ColorBgra(); if (waSum == 0) { Shadow = ColorBgra.FromBgra(0, 0, 0, 0); } else { Shadow = ColorBgra.FromBgra(0, 0, 0, (byte)(aSum / waSum)); } if (configuration.KeepOriginalImage) { dstPtr->Bgra = (uint)_normalOp.Apply(Shadow, OrginalImage); } else { dstPtr->Bgra = (uint)Shadow; } ++dstPtr; } } } }