示例#1
0
文件: PixelOp.cs 项目: msiyer/Pinta
		/// <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);
				}
			}
		}
示例#2
0
		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;
				}
			}
		}
示例#3
0
        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]);
            }
        }
示例#4
0
文件: Document.cs 项目: msiyer/Pinta
		/// <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);
            }
		}
示例#5
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;
                    }
                }
            }
        }
示例#6
0
        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);
            }
        }
示例#7
0
		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;
					}
				}
			}
		}