/// <summary> /// Provides a default implementation for performing dst = F(dst, src) or F(src) over some rectangle /// of interest. May be slightly faster than calling the other multi-parameter Apply method, as less /// variables are used in the implementation, thus inducing less register pressure. /// </summary> /// <param name="dst">The Surface to write pixels to, and from which pixels are read and used as the lhs parameter for calling the method <b>ColorBgra Apply(ColorBgra, ColorBgra)</b>.</param> /// <param name="dstOffset">The pixel offset that defines the upper-left of the rectangle-of-interest for the dst Surface.</param> /// <param name="src">The Surface to read pixels from for the rhs parameter given to the method <b>ColorBgra Apply(ColorBgra, ColorBgra)</b>.</param> /// <param name="srcOffset">The pixel offset that defines the upper-left of the rectangle-of-interest for the src Surface.</param> /// <param name="roiSize">The size of the rectangles-of-interest for all Surfaces.</param> public void ApplyBase (ImageSurface dst, Gdk.Point dstOffset, ImageSurface src, Gdk.Point srcOffset, Gdk.Size roiSize) { // Create bounding rectangles for each Surface Gdk.Rectangle dstRect = new Gdk.Rectangle (dstOffset, roiSize); if (dstRect.Width == 0 || dstRect.Height == 0) return; Gdk.Rectangle srcRect = new Gdk.Rectangle (srcOffset, roiSize); if (srcRect.Width == 0 || srcRect.Height == 0) return; // Clip those rectangles to those Surface's bounding rectangles Gdk.Rectangle dstClip = Gdk.Rectangle.Intersect (dstRect, dst.GetBounds ()); Gdk.Rectangle srcClip = Gdk.Rectangle.Intersect (srcRect, src.GetBounds ()); // If any of those Rectangles actually got clipped, then throw an exception if (dstRect != dstClip) throw new ArgumentOutOfRangeException ( "roiSize", "Destination roi out of bounds" + string.Format (", dst.Size=({0},{1}", dst.Width, dst.Height) + ", dst.Bounds=" + dst.GetBounds ().ToString () + ", dstOffset=" + dstOffset.ToString () + string.Format (", src.Size=({0},{1}", src.Width, src.Height) + ", srcOffset=" + srcOffset.ToString () + ", roiSize=" + roiSize.ToString () + ", dstRect=" + dstRect.ToString () + ", dstClip=" + dstClip.ToString () + ", srcRect=" + srcRect.ToString () + ", srcClip=" + srcClip.ToString () ); if (srcRect != srcClip) throw new ArgumentOutOfRangeException ("roiSize", "Source roi out of bounds"); // Cache the width and height properties int width = roiSize.Width; int height = roiSize.Height; // Do the work. unsafe { for (int row = 0; row < height; ++row) { ColorBgra* dstPtr = dst.GetPointAddress (dstOffset.X, dstOffset.Y + row); ColorBgra* srcPtr = src.GetPointAddress (srcOffset.X, srcOffset.Y + row); Apply (dstPtr, srcPtr, width); } } }
unsafe public override void Render (ImageSurface src, ImageSurface dest, Gdk.Rectangle[] rois) { var cellSize = Data.CellSize; Gdk.Rectangle src_bounds = src.GetBounds (); Gdk.Rectangle dest_bounds = dest.GetBounds (); foreach (var rect in rois) { for (int y = rect.Top; y <= rect.GetBottom (); ++y) { int yEnd = y + 1; for (int x = rect.Left; x <= rect.GetRight (); ++x) { var cellRect = GetCellBox (x, y, cellSize); cellRect.Intersect (dest_bounds); var color = ComputeCellColor (x, y, src, cellSize, src_bounds); int xEnd = Math.Min (rect.GetRight (), cellRect.GetRight ()); yEnd = Math.Min (rect.GetBottom (), cellRect.GetBottom ()); for (int y2 = y; y2 <= yEnd; ++y2) { ColorBgra* ptr = dest.GetPointAddressUnchecked (x, y2); for (int x2 = x; x2 <= xEnd; ++x2) { ptr->Bgra = color.Bgra; ++ptr; } } x = xEnd; } y = yEnd; } } }
public void Apply(ImageSurface surface, Gdk.Rectangle[] roi, int startIndex, int length) { Gdk.Rectangle regionBounds = Utility.GetRegionBounds (roi, startIndex, length); if (regionBounds != Gdk.Rectangle.Intersect (surface.GetBounds (), regionBounds)) throw new ArgumentOutOfRangeException ("roi", "Region is out of bounds"); unsafe { for (int x = startIndex; x < startIndex + length; ++x) ApplyRectangle (surface, roi[x]); } }
/// <summary> /// Gets the final pixel color for the given point, taking layers, opacity, and blend modes into account. /// </summary> public ColorBgra GetComputedPixel (int x, int y) { using (var dst = new ImageSurface (Format.Argb32, 1, 1)) { using (var g = new Context (dst)) { foreach (var layer in GetLayersToPaint ()) { var color = layer.Surface.GetColorBgraUnchecked (x, y).ToStraightAlpha ().ToCairoColor (); g.SetBlendMode (layer.BlendMode); g.SetSourceColor (color); g.Rectangle (dst.GetBounds ().ToCairoRectangle ()); g.PaintWithAlpha (layer.Opacity); } } return dst.GetColorBgraUnchecked (0, 0); } }
public unsafe override void RenderEffect(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.Bottom; ++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.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.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; } } } }
public void Draw(ImageSurface dst, PixelOp pixelOp) { if (disposed) throw new ObjectDisposedException ("PlacedSurface"); Gdk.Rectangle dstRect = Bounds; Gdk.Rectangle dstClip = Gdk.Rectangle.Intersect (dstRect, dst.GetBounds ()); if (dstClip.Width > 0 && dstClip.Height > 0) { int dtX = dstClip.X - where.X; int dtY = dstClip.Y - where.Y; pixelOp.Apply (dst, dstClip.Location, what, new Gdk.Point (dtX, dtY), dstClip.Size); } }
public unsafe void RenderColorDifferenceEffect (double[][] weights, ImageSurface src, ImageSurface dest, Gdk.Rectangle[] rois) { Gdk.Rectangle src_rect = src.GetBounds (); // Cache these for a massive performance boost int src_width = src.Width; ColorBgra* src_data_ptr = (ColorBgra*)src.DataPtr; foreach (Gdk.Rectangle rect in rois) { // loop through each line of target rectangle for (int y = rect.Y; y < rect.Y + rect.Height; ++y) { int fyStart = 0; int fyEnd = 3; if (y == src_rect.Y) fyStart = 1; if (y == src_rect.Y + src_rect.Height - 1) fyEnd = 2; // loop through each point in the line ColorBgra* dstPtr = dest.GetPointAddressUnchecked (rect.X, y); for (int x = rect.X; x < rect.X + rect.Width; ++x) { int fxStart = 0; int fxEnd = 3; if (x == src_rect.X) fxStart = 1; if (x == src_rect.X + src_rect.Width - 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 (src_data_ptr, src_width, 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; } } } }