Pinta.ImageManipulation.Effects.LocalHistogramEffect.RenderRectWithAlpha C# (CSharp) Method

RenderRectWithAlpha() public method

public RenderRectWithAlpha ( int rad, ISurface src, ISurface dst, Rectangle rect ) : void
rad int
src ISurface
dst ISurface
rect Rectangle
return void
		public unsafe void RenderRectWithAlpha (int rad, ISurface src, ISurface dst, Rectangle rect)
		{
			int width = src.Width;
			int height = src.Height;

			int* leadingEdgeX = stackalloc int[rad + 1];
			int stride = src.Stride / sizeof (ColorBgra);

			// approximately (rad + 0.5)^2
			int cutoff = ((rad * 2 + 1) * (rad * 2 + 1) + 2) / 4;

			for (int v = 0; v <= rad; ++v) {
				for (int u = 0; u <= rad; ++u) {
					if (u * u + v * v <= cutoff) {
						leadingEdgeX[v] = u;
					}
				}
			}

			const int hLength = 256;
			int* hb = stackalloc int[hLength];
			int* hg = stackalloc int[hLength];
			int* hr = stackalloc int[hLength];
			uint hSize = (uint)(sizeof (int) * hLength);

			for (int y = rect.Top; y <= rect.Bottom; y++) {
				SetToZero (hb, hSize);
				SetToZero (hg, hSize);
				SetToZero (hr, hSize);

				int area = 0;
				int sum = 0;

				ColorBgra* ps = src.GetPointAddress (rect.Left, y);
				ColorBgra* pd = dst.GetPointAddress (rect.Left, y);

				// assert: v + y >= 0
				int top = -Math.Min (rad, y);

				// assert: v + y <= height - 1
				int bottom = Math.Min (rad, height - 1 - y);

				// assert: u + x >= 0
				int left = -Math.Min (rad, rect.Left);

				// assert: u + x <= width - 1
				int right = Math.Min (rad, width - 1 - rect.Left);

				for (int v = top; v <= bottom; ++v) {
					ColorBgra* psamp = src.GetPointAddress (rect.Left + left, y + v);

					for (int u = left; u <= right; ++u) {
						byte w = psamp->A;
						if ((u * u + v * v) <= cutoff) {
							++area;
							sum += w;
							hb[psamp->B] += w;
							hg[psamp->G] += w;
							hr[psamp->R] += w;
						}

						++psamp;
					}
				}

				for (int x = rect.Left; x <= rect.Right; x++) {
					*pd = ApplyWithAlpha (*ps, area, sum, hb, hg, hr);

					// assert: u + x >= 0
					left = -Math.Min (rad, x);

					// assert: u + x <= width - 1
					right = Math.Min (rad + 1, width - 1 - x);

					// Subtract trailing edge top half
					int v = -1;

					while (v >= top) {
						int u = leadingEdgeX[-v];

						if (-u >= left) {
							break;
						}

						--v;
					}

					while (v >= top) {
						int u = leadingEdgeX[-v];
						ColorBgra* p = unchecked (ps + (v * stride)) - u;
						byte w = p->A;

						hb[p->B] -= w;
						hg[p->G] -= w;
						hr[p->R] -= w;
						sum -= w;
						--area;

						--v;
					}

					// add leading edge top half
					v = -1;
					while (v >= top) {
						int u = leadingEdgeX[-v];

						if (u + 1 <= right) {
							break;
						}

						--v;
					}

					while (v >= top) {
						int u = leadingEdgeX[-v];
						ColorBgra* p = unchecked (ps + (v * stride)) + u + 1;
						byte w = p->A;

						hb[p->B] += w;
						hg[p->G] += w;
						hr[p->R] += w;
						sum += w;
						++area;

						--v;
					}

					// Subtract trailing edge bottom half
					v = 0;

					while (v <= bottom) {
						int u = leadingEdgeX[v];

						if (-u >= left) {
							break;
						}

						++v;
					}

					while (v <= bottom) {
						int u = leadingEdgeX[v];
						ColorBgra* p = ps + v * stride - u;
						byte w = p->A;

						hb[p->B] -= w;
						hg[p->G] -= w;
						hr[p->R] -= w;
						sum -= w;
						--area;

						++v;
					}

					// add leading edge bottom half
					v = 0;

					while (v <= bottom) {
						int u = leadingEdgeX[v];

						if (u + 1 <= right) {
							break;
						}

						++v;
					}

					while (v <= bottom) {
						int u = leadingEdgeX[v];
						ColorBgra* p = ps + v * stride + u + 1;
						byte w = p->A;

						hb[p->B] += w;
						hg[p->G] += w;
						hr[p->R] += w;
						sum += w;
						++area;

						++v;
					}

					++ps;
					++pd;
				}
			}
		}
	}