예제 #1
0
		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);
			}
		}
예제 #2
0
		public unsafe override void Render (ImageSurface src, ImageSurface dest, Gdk.Rectangle[] rois)
		{
			int warmth = Data.Warmth;
			float redAdjust = 1.0f + (warmth / 100.0f);
            float blueAdjust = 1.0f - (warmth / 100.0f);

            this.blurEffect.Render(src, dest, rois);
            this.bacAdjustment.Render(src, dest, rois);

			foreach (Gdk.Rectangle roi in rois) {
                for (int y = roi.Top; y <= roi.GetBottom (); ++y) {
                    ColorBgra* srcPtr = src.GetPointAddress(roi.X, y);
                    ColorBgra* dstPtr = dest.GetPointAddress(roi.X, y);

                    for (int x = roi.Left; x <= roi.GetRight (); ++x) {
                        ColorBgra srcGrey = this.desaturateOp.Apply(*srcPtr);

                        srcGrey.R = Utility.ClampToByte((int)((float)srcGrey.R * redAdjust));
                        srcGrey.B = Utility.ClampToByte((int)((float)srcGrey.B * blueAdjust));

                        ColorBgra mypixel = this.overlayOp.Apply(srcGrey, *dstPtr);
                        *dstPtr = mypixel;

                        ++srcPtr;
                        ++dstPtr;
                    }
                }
			}
		}
예제 #3
0
 public override void Apply(ImageSurface dst, Gdk.Point dstOffset, ImageSurface src, Gdk.Point srcOffset, int scanLength)
 {
     Apply (dst.GetPointAddress (dstOffset), src.GetPointAddress (srcOffset), scanLength);
 }
예제 #4
0
        public unsafe void Render(ImageSurface surface, Gdk.Rectangle[] rois)
        {
            byte startAlpha;
            byte endAlpha;

            if (this.alphaOnly) {
                ComputeAlphaOnlyValuesFromColors (this.startColor, this.endColor, out startAlpha, out endAlpha);
            } else {
                startAlpha = this.startColor.A;
                endAlpha = this.endColor.A;
            }

            ColorBgra* src_data_ptr = (ColorBgra*)surface.DataPtr;
            int src_width = surface.Width;

            for (int ri = 0; ri < rois.Length; ++ri) {
                Gdk.Rectangle rect = rois[ri];

                if (this.startPoint.X == this.endPoint.X && this.startPoint.Y == this.endPoint.Y) {
                    // Start and End point are the same ... fill with solid color.
                    for (int y = rect.Top; y < rect.Bottom; ++y) {
                        ColorBgra* pixelPtr = surface.GetPointAddress(rect.Left, y);

                        for (int x = rect.Left; x < rect.Right; ++x) {
                            ColorBgra result;

                            if (this.alphaOnly && this.alphaBlending) {
                                byte resultAlpha = (byte)Utility.FastDivideShortByByte ((ushort)(pixelPtr->A * endAlpha), 255);
                                result = *pixelPtr;
                                result.A = resultAlpha;
                            } else if (this.alphaOnly && !this.alphaBlending) {
                                result = *pixelPtr;
                                result.A = endAlpha;
                            } else if (!this.alphaOnly && this.alphaBlending) {
                                result = this.normalBlendOp.Apply (*pixelPtr, this.endColor);
                            //if (!this.alphaOnly && !this.alphaBlending)
                            } else {
                                result = this.endColor;
                            }

                            *pixelPtr = result;
                            ++pixelPtr;
                        }
                    }
                } else {
                    for (int y = rect.Top; y < rect.Bottom; ++y) {
                        ColorBgra* pixelPtr = surface.GetPointAddress(rect.Left, y);

                        if (this.alphaOnly && this.alphaBlending) {
                            for (int x = rect.Left; x < rect.Right; ++x) {
                                double lerpUnbounded = ComputeUnboundedLerp (x, y);
                                double lerpBounded = BoundLerp (lerpUnbounded);
                                byte lerpByte = (byte)(lerpBounded * 255f);
                                byte lerpAlpha = this.lerpAlphas[lerpByte];
                                byte resultAlpha = Utility.FastScaleByteByByte (pixelPtr->A, lerpAlpha);
                                pixelPtr->A = resultAlpha;
                                ++pixelPtr;
                            }
                        } else if (this.alphaOnly && !this.alphaBlending) {
                            for (int x = rect.Left; x < rect.Right; ++x) {
                                double lerpUnbounded = ComputeUnboundedLerp (x, y);
                                double lerpBounded = BoundLerp (lerpUnbounded);
                                byte lerpByte = (byte)(lerpBounded * 255f);
                                byte lerpAlpha = this.lerpAlphas[lerpByte];
                                pixelPtr->A = lerpAlpha;
                                ++pixelPtr;
                            }
                        } else if (!this.alphaOnly && (this.alphaBlending && (startAlpha != 255 || endAlpha != 255))) {
                            // If we're doing all color channels, and we're doing alpha blending, and if alpha blending is necessary
                            for (int x = rect.Left; x < rect.Right; ++x) {
                                double lerpUnbounded = ComputeUnboundedLerp (x, y);
                                double lerpBounded = BoundLerp (lerpUnbounded);
                                byte lerpByte = (byte)(lerpBounded * 255f);
                                ColorBgra lerpColor = this.lerpColors[lerpByte];
                                ColorBgra result = this.normalBlendOp.Apply (*pixelPtr, lerpColor);
                                *pixelPtr = result;
                                ++pixelPtr;
                            }
                        //if (!this.alphaOnly && !this.alphaBlending) // or sC.A == 255 && eC.A == 255
                        } else {
                            for (int x = rect.Left; x < rect.Right; ++x) {
                                double lerpUnbounded = ComputeUnboundedLerp (x, y);
                                double lerpBounded = BoundLerp (lerpUnbounded);
                                byte lerpByte = (byte)(lerpBounded * 255f);
                                ColorBgra lerpColor = this.lerpColors[lerpByte];
                                *pixelPtr = lerpColor;
                                ++pixelPtr;
                            }
                        }
                    }
                }
            }

            AfterRender ();
        }
예제 #5
0
        public unsafe override void RenderEffect(ImageSurface src, ImageSurface dest, Gdk.Rectangle[] rois)
        {
            // Glow backgound
            glowEffect.Data.Radius = 6;
            glowEffect.Data.Brightness = -(Data.Coloring - 50) * 2;
            glowEffect.Data.Contrast = -(Data.Coloring - 50) * 2;

            this.glowEffect.RenderEffect (src, dest, rois);

            // Create black outlines by finding the edges of objects
            foreach (Gdk.Rectangle roi in rois) {
                for (int y = roi.Top; y < roi.Bottom; ++y) {
                    int top = y - radius;
                    int bottom = y + radius + 1;

                    if (top < 0) {
                        top = 0;
                    }

                    if (bottom > dest.Height) {
                        bottom = dest.Height;
                    }

                    ColorBgra* srcPtr = src.GetPointAddress (roi.X, y);
                    ColorBgra* dstPtr = dest.GetPointAddress (roi.X, y);

                    for (int x = roi.Left; x < roi.Right; ++x) {
                        int left = x - radius;
                        int right = x + radius + 1;

                        if (left < 0) {
                            left = 0;
                        }

                        if (right > dest.Width) {
                            right = dest.Width;
                        }

                        int r = 0;
                        int g = 0;
                        int b = 0;

                        int src_width = src.Width;
                        ColorBgra* src_dataptr = (ColorBgra*)src.DataPtr;

                        for (int v = top; v < bottom; v++) {
                            ColorBgra* pRow = src.GetRowAddressUnchecked (src_dataptr, src_width, v);
                            int j = v - y + radius;

                            for (int u = left; u < right; u++) {
                                int i1 = u - x + radius;
                                int w = conv[j][i1];

                                ColorBgra* pRef = pRow + u;

                                r += pRef->R * w;
                                g += pRef->G * w;
                                b += pRef->B * w;
                            }
                        }

                        ColorBgra topLayer = ColorBgra.FromBgr (
                            Utility.ClampToByte (b),
                            Utility.ClampToByte (g),
                            Utility.ClampToByte (r));

                        // Desaturate
                        topLayer = this.desaturateOp.Apply (topLayer);

                        // Adjust Brightness and Contrast
                        if (topLayer.R > (Data.InkOutline * 255 / 100)) {
                            topLayer = ColorBgra.FromBgra (255, 255, 255, topLayer.A);
                        } else {
                            topLayer = ColorBgra.FromBgra (0, 0, 0, topLayer.A);
                        }

                        // Change Blend Mode to Darken
                        ColorBgra myPixel = this.darkenOp.Apply (topLayer, *dstPtr);
                        *dstPtr = myPixel;

                        ++srcPtr;
                        ++dstPtr;
                    }
                }
            }
        }
예제 #6
0
        public unsafe void Render(ImageSurface surface, Gdk.Rectangle[] rois)
        {
            byte startAlpha;
            byte endAlpha;

            if (this.alphaOnly) {
                ComputeAlphaOnlyValuesFromColors (this.startColor, this.endColor, out startAlpha, out endAlpha);
            } else {
                startAlpha = this.startColor.A;
                endAlpha = this.endColor.A;
            }

            surface.Flush ();

            ColorBgra* src_data_ptr = (ColorBgra*)surface.DataPtr;
            int src_width = surface.Width;

            for (int ri = 0; ri < rois.Length; ++ri) {
                Gdk.Rectangle rect = rois[ri];

                if (this.startPoint.X == this.endPoint.X && this.startPoint.Y == this.endPoint.Y) {
                    // Start and End point are the same ... fill with solid color.
                    for (int y = rect.Top; y <= rect.GetBottom (); ++y) {
                        ColorBgra* pixelPtr = surface.GetPointAddress(rect.Left, y);

                        for (int x = rect.Left; x <= rect.GetRight (); ++x) {
                            ColorBgra result;

                            if (this.alphaOnly && this.alphaBlending) {
                                byte resultAlpha = (byte)Utility.FastDivideShortByByte ((ushort)(pixelPtr->A * endAlpha), 255);
                                result = *pixelPtr;
                                result.A = resultAlpha;
                            } else if (this.alphaOnly && !this.alphaBlending) {
                                result = *pixelPtr;
                                result.A = endAlpha;
                            } else if (!this.alphaOnly && this.alphaBlending) {
                                result = this.normalBlendOp.Apply (*pixelPtr, this.endColor);
                            //if (!this.alphaOnly && !this.alphaBlending)
                            } else {
                                result = this.endColor;
                            }

                            *pixelPtr = result;
                            ++pixelPtr;
                        }
                    }
                } else {
                    var mainrect = rect;
                    var start = Environment.TickCount;
                    Parallel.ForEach(Enumerable.Range (rect.Top, rect.GetBottom () + 1),
                        (y) => ProcessGradientLine(startAlpha, endAlpha, y, mainrect, surface, src_data_ptr, src_width));
                    var end = Environment.TickCount;
                    Console.WriteLine ("Time: " + (end - start)+ "ms");
                }
            }

            surface.MarkDirty ();
            AfterRender ();
        }
예제 #7
0
        public unsafe override void RenderEffect(ImageSurface src, ImageSurface dst, Gdk.Rectangle[] rois)
        {
            int width = src.Width;
            int height = src.Height;
            int r = Data.Amount;
            Random localRandom = this.random;

            int* intensityCount = stackalloc int[256];
            uint* avgRed = stackalloc uint[256];
            uint* avgGreen = stackalloc uint[256];
            uint* avgBlue = stackalloc uint[256];
            uint* avgAlpha = stackalloc uint[256];
            byte* intensityChoices = stackalloc byte[(1 + (r * 2)) * (1 + (r * 2))];

            int src_width = src.Width;
            ColorBgra* src_data_ptr = (ColorBgra*)src.DataPtr;

            foreach (var rect in rois) {
                int rectTop = rect.Top;
                int rectBottom = rect.Bottom;
                int rectLeft = rect.Left;
                int rectRight = rect.Right;

                for (int y = rectTop; y < rectBottom; ++y) {
                    ColorBgra* dstPtr = dst.GetPointAddress (rect.Left, y);

                    int top = y - r;
                    int bottom = y + r + 1;

                    if (top < 0) {
                        top = 0;
                    }

                    if (bottom > height) {
                        bottom = height;
                    }

                    for (int x = rectLeft; x < rectRight; ++x) {
                        int intensityChoicesIndex = 0;

                        for (int i = 0; i < 256; ++i) {
                            intensityCount[i] = 0;
                            avgRed[i] = 0;
                            avgGreen[i] = 0;
                            avgBlue[i] = 0;
                            avgAlpha[i] = 0;
                        }

                        int left = x - r;
                        int right = x + r + 1;

                        if (left < 0) {
                            left = 0;
                        }

                        if (right > width) {
                            right = width;
                        }

                        for (int j = top; j < bottom; ++j) {
                            if (j < 0 || j >= height) {
                                continue;
                            }

                            ColorBgra* srcPtr = src.GetPointAddressUnchecked (src_data_ptr, src_width, left, j);

                            for (int i = left; i < right; ++i) {
                                byte intensity = srcPtr->GetIntensityByte ();

                                intensityChoices[intensityChoicesIndex] = intensity;
                                ++intensityChoicesIndex;

                                ++intensityCount[intensity];

                                avgRed[intensity] += srcPtr->R;
                                avgGreen[intensity] += srcPtr->G;
                                avgBlue[intensity] += srcPtr->B;
                                avgAlpha[intensity] += srcPtr->A;

                                ++srcPtr;
                            }
                        }

                        int randNum;

                        lock (localRandom) {
                            randNum = localRandom.Next (intensityChoicesIndex);
                        }

                        byte chosenIntensity = intensityChoices[randNum];

                        byte R = (byte)(avgRed[chosenIntensity] / intensityCount[chosenIntensity]);
                        byte G = (byte)(avgGreen[chosenIntensity] / intensityCount[chosenIntensity]);
                        byte B = (byte)(avgBlue[chosenIntensity] / intensityCount[chosenIntensity]);
                        byte A = (byte)(avgAlpha[chosenIntensity] / intensityCount[chosenIntensity]);

                        *dstPtr = ColorBgra.FromBgra (B, G, R, A);
                        ++dstPtr;

                        // prepare the array for the next loop iteration
                        for (int i = 0; i < intensityChoicesIndex; ++i) {
                            intensityChoices[i] = 0;
                        }
                    }
                }
            }
        }
예제 #8
0
        public unsafe override void Render(ImageSurface src, ImageSurface dst, Gdk.Rectangle[] rois)
        {
            double[,] weights = Weights;

            var srcWidth = src.Width;
            var srcHeight = src.Height;

            ColorBgra* src_data_ptr = (ColorBgra*)src.DataPtr;

            foreach (var rect in rois) {
                // loop through each line of target rectangle
                for (int y = rect.Top; y <= rect.GetBottom (); ++y) {
                    int fyStart = 0;
                    int fyEnd = 3;

                    if (y == 0)
                        fyStart = 1;

                    if (y == srcHeight - 1)
                        fyEnd = 2;

                    // loop through each point in the line
                    ColorBgra* dstPtr = dst.GetPointAddress (rect.Left, y);

                    for (int x = rect.Left; x <= rect.GetRight (); ++x) {
                        int fxStart = 0;
                        int fxEnd = 3;

                        if (x == 0)
                            fxStart = 1;

                        if (x == srcWidth - 1)
                            fxEnd = 2;

                        // loop through each weight
                        double sum = 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, srcWidth, x - 1 + fx, y - 1 + fy);
                                double intensity = (double)c.GetIntensityByte ();
                                sum += weight * intensity;
                            }
                        }

                        int iSum = (int)sum;
                        iSum += 128;

                        if (iSum > 255)
                            iSum = 255;

                        if (iSum < 0)
                            iSum = 0;

                        *dstPtr = ColorBgra.FromBgra ((byte)iSum, (byte)iSum, (byte)iSum, 255);

                        ++dstPtr;
                    }
                }
            }
        }
예제 #9
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);
				}
			}
		}