private unsafe void ApplyRectangle (ImageSurface surface, Gdk.Rectangle rect) { for (int y = rect.Left; y <= rect.GetBottom (); ++y) { ColorBgra* ptr = surface.GetPointAddress (rect.Left, y); Apply (ptr, rect.Width); } }
protected override unsafe void AddSurfaceRectangleToHistogram(ImageSurface surface, Gdk.Rectangle rect) { long[] histogramB = histogram[0]; long[] histogramG = histogram[1]; long[] histogramR = histogram[2]; int rect_right = rect.GetRight (); for (int y = rect.Y; y <= rect.GetBottom (); ++y) { ColorBgra* ptr = surface.GetPointAddressUnchecked(rect.X, y); for (int x = rect.X; x <= rect_right; ++x) { ++histogramB[ptr->B]; ++histogramG[ptr->G]; ++histogramR[ptr->R]; ++ptr; } } }
//same as RenderRect, except the histogram is alpha-weighted instead of keeping a separate alpha channel histogram. public unsafe void RenderRectWithAlpha( int rad, ImageSurface src, ImageSurface dst, Gdk.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.GetBottom (); y++) { SetToZero(hb, hSize); SetToZero(hg, hSize); SetToZero(hr, hSize); int area = 0; int sum = 0; ColorBgra* ps = src.GetPointAddressUnchecked(rect.Left, y); ColorBgra* pd = dst.GetPointAddressUnchecked(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.GetPointAddressUnchecked(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.GetRight (); 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; } } }
private unsafe static void RenderClouds(ImageSurface surface, Gdk.Rectangle rect, int scale, byte seed, double power, ColorBgra colorFrom, ColorBgra colorTo) { int w = surface.Width; int h = surface.Height; for (int y = rect.Top; y <= rect.GetBottom (); ++y) { ColorBgra* ptr = surface.GetPointAddressUnchecked(0, y - rect.Top); int dy = 2 * y - h; for (int x = rect.Left; x <= rect.GetRight (); ++x) { int dx = 2 * x - w; double val = 0; double mult = 1; int div = scale; for (int i = 0; i < 12 && mult > 0.03 && div > 0; ++i) { double dxr = 65536 + (double)dx / (double)div; double dyr = 65536 + (double)dy / (double)div; int dxd = (int)dxr; int dyd = (int)dyr; dxr -= dxd; dyr -= dyd; double noise = Noise( unchecked((byte)dxd), unchecked((byte)dyd), dxr, //(double)dxr / div, dyr, //(double)dyr / div, (byte)(seed ^ i)); val += noise * mult; div /= 2; mult *= power; } *ptr = ColorBgra.Lerp(colorFrom, colorTo, (val + 1) / 2); ++ptr; } } }
/// <summary> /// Performs the actual work of rendering an effect. Do not call base.Render (). /// </summary> /// <param name="src">The source surface. DO NOT MODIFY.</param> /// <param name="dst">The destination surface.</param> /// <param name="roi">A rectangle of interest (roi) specifying the area to modify. Only these areas should be modified</param> protected unsafe virtual void Render(ImageSurface src, ImageSurface dst, Gdk.Rectangle roi) { ColorBgra* src_data_ptr = (ColorBgra*)src.DataPtr; int src_width = src.Width; ColorBgra* dst_data_ptr = (ColorBgra*)dst.DataPtr; int dst_width = dst.Width; for (int y = roi.Y; y <= roi.GetBottom (); ++y) { ColorBgra* srcPtr = src.GetPointAddressUnchecked (src_data_ptr, src_width, roi.X, y); ColorBgra* dstPtr = dst.GetPointAddressUnchecked (dst_data_ptr, dst_width, roi.X, y); Render (srcPtr, dstPtr, roi.Width); } }
public void Apply (ImageSurface dst, ImageSurface src, Gdk.Rectangle roi) { ColorBgra* src_data_ptr = (ColorBgra*)src.DataPtr; int src_width = src.Width; ColorBgra* dst_data_ptr = (ColorBgra*)dst.DataPtr; int dst_width = dst.Width; for (int y = roi.Y; y <= roi.GetBottom(); ++y) { ColorBgra* dstPtr = dst.GetPointAddressUnchecked (dst_data_ptr, dst_width, roi.X, y); ColorBgra* srcPtr = src.GetPointAddressUnchecked (src_data_ptr, src_width, roi.X, y); Apply (dstPtr, srcPtr, roi.Width); } }
public void Invert (Gdk.Rectangle rect) { for (int y = rect.Y; y <= rect.GetBottom (); ++y) { for (int x = rect.X; x <= rect.GetRight (); ++x) { Invert (x, y); } } }
public void Set (Gdk.Rectangle rect, bool newValue) { for (int y = rect.Y; y <= rect.GetBottom (); ++y) { for (int x = rect.X; x <= rect.GetRight (); ++x) { Set (x, y, newValue); } } }