/// <summary> /// </summary> protected override void OnSetRenderInfo(PropertyBasedEffectConfigToken token, RenderArgs dstArgs, RenderArgs srcArgs) { // // This is an expensive operation, so pull the effect configuration once here rather than each time its needed during // effect rendering // _effectConfiguration = ShadowEffectConfiguration.FromToken(token); base.OnSetRenderInfo(token, dstArgs, srcArgs); }
/// <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; } } } }