Ejemplo n.º 1
0
        unsafe public override void Render(ImageSurface src, ImageSurface dst, Gdk.Rectangle[] rois)
        {
            int w = dst.Width;
            int h = dst.Height;

            double invH    = 1.0 / h;
            double zoom    = 1 + zoomFactor * Data.Zoom;
            double invZoom = 1.0 / zoom;

            double invQuality = 1.0 / (double)Data.Quality;

            int    count      = Data.Quality * Data.Quality + 1;
            double invCount   = 1.0 / (double)count;
            double angleTheta = (Data.Angle * 2 * Math.PI) / 360;

            ColorBgra *dst_dataptr = (ColorBgra *)dst.DataPtr;
            int        dst_width   = dst.Width;

            foreach (Gdk.Rectangle rect in rois)
            {
                for (int y = rect.Top; y <= rect.GetBottom(); y++)
                {
                    ColorBgra *dstPtr = dst.GetPointAddressUnchecked(dst_dataptr, dst_width, rect.Left, y);

                    for (int x = rect.Left; x <= rect.GetRight(); x++)
                    {
                        int r = 0;
                        int g = 0;
                        int b = 0;
                        int a = 0;

                        for (double i = 0; i < count; i++)
                        {
                            double u = (2.0 * x - w + (i * invCount)) * invH;
                            double v = (2.0 * y - h + ((i * invQuality) % 1)) * invH;

                            double radius  = Math.Sqrt((u * u) + (v * v));
                            double radiusP = radius;
                            double theta   = Math.Atan2(v, u);
                            double thetaP  = theta + angleTheta;

                            double uP = radiusP * Math.Cos(thetaP);
                            double vP = radiusP * Math.Sin(thetaP);

                            double m = Mandelbrot((uP * invZoom) + this.xOffset, (vP * invZoom) + this.yOffset, Data.Factor);

                            double c = 64 + Data.Factor * m;

                            r += Utility.ClampToByte(c - 768);
                            g += Utility.ClampToByte(c - 512);
                            b += Utility.ClampToByte(c - 256);
                            a += Utility.ClampToByte(c - 0);
                        }

                        *dstPtr = ColorBgra.FromBgra(Utility.ClampToByte(b / count), Utility.ClampToByte(g / count), Utility.ClampToByte(r / count), Utility.ClampToByte(a / count));

                        ++dstPtr;
                    }
                }

                if (Data.InvertColors)
                {
                    for (int y = rect.Top; y <= rect.GetBottom(); y++)
                    {
                        ColorBgra *dstPtr = dst.GetPointAddressUnchecked(dst_dataptr, dst_width, rect.Left, y);

                        for (int x = rect.Left; x <= rect.GetRight(); ++x)
                        {
                            ColorBgra c = *dstPtr;

                            c.B = (byte)(255 - c.B);
                            c.G = (byte)(255 - c.G);
                            c.R = (byte)(255 - c.R);

                            *dstPtr = c;
                            ++dstPtr;
                        }
                    }
                }
            }
        }
Ejemplo n.º 2
0
        public unsafe void RenderRect(
            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];
            int *     ha      = 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);
                SetToZero(ha, hSize);

                int area = 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)
                    {
                        if ((u * u + v * v) <= cutoff)
                        {
                            ++area;
                            ++hb[psamp->B];
                            ++hg[psamp->G];
                            ++hr[psamp->R];
                            ++ha[psamp->A];
                        }

                        ++psamp;
                    }
                }

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

                    // 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;

                        --hb[p->B];
                        --hg[p->G];
                        --hr[p->R];
                        --ha[p->A];
                        --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;

                        ++hb[p->B];
                        ++hg[p->G];
                        ++hr[p->R];
                        ++ha[p->A];
                        ++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;

                        --hb[p->B];
                        --hg[p->G];
                        --hr[p->R];
                        --ha[p->A];
                        --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;

                        ++hb[p->B];
                        ++hg[p->G];
                        ++hr[p->R];
                        ++ha[p->A];
                        ++area;

                        ++v;
                    }

                    ++ps;
                    ++pd;
                }
            }
        }
Ejemplo n.º 3
0
        public static unsafe ColorBgra GetBilinearSampleClamped(this ImageSurface src, ColorBgra *srcDataPtr, int srcWidth, int srcHeight, float x, float y)
        {
            if (!Utility.IsNumber(x) || !Utility.IsNumber(y))
            {
                return(ColorBgra.Transparent);
            }

            float u = x;
            float v = y;

            if (u < 0)
            {
                u = 0;
            }
            else if (u > srcWidth - 1)
            {
                u = srcWidth - 1;
            }

            if (v < 0)
            {
                v = 0;
            }
            else if (v > srcHeight - 1)
            {
                v = srcHeight - 1;
            }

            unchecked {
                int  iu        = (int)Math.Floor(u);
                uint sxfrac    = (uint)(256 * (u - (float)iu));
                uint sxfracinv = 256 - sxfrac;

                int  iv        = (int)Math.Floor(v);
                uint syfrac    = (uint)(256 * (v - (float)iv));
                uint syfracinv = 256 - syfrac;

                uint wul = (uint)(sxfracinv * syfracinv);
                uint wur = (uint)(sxfrac * syfracinv);
                uint wll = (uint)(sxfracinv * syfrac);
                uint wlr = (uint)(sxfrac * syfrac);

                int sx    = iu;
                int sy    = iv;
                int sleft = sx;
                int sright;

                if (sleft == (srcWidth - 1))
                {
                    sright = sleft;
                }
                else
                {
                    sright = sleft + 1;
                }

                int stop = sy;
                int sbottom;

                if (stop == (srcHeight - 1))
                {
                    sbottom = stop;
                }
                else
                {
                    sbottom = stop + 1;
                }

                ColorBgra *cul = src.GetPointAddressUnchecked(srcDataPtr, srcWidth, sleft, stop);
                ColorBgra *cur = cul + (sright - sleft);
                ColorBgra *cll = src.GetPointAddressUnchecked(srcDataPtr, srcWidth, sleft, sbottom);
                ColorBgra *clr = cll + (sright - sleft);

                ColorBgra c = ColorBgra.BlendColors4W16IP(*cul, wul, *cur, wur, *cll, wll, *clr, wlr);
                return(c);
            }
        }
Ejemplo n.º 4
0
        public unsafe override void Render(ImageSurface src, ImageSurface dst, Gdk.Rectangle[] rois)
        {
            var selection = PintaCore.LivePreview.RenderBounds;

            this.defaultRadius  = Math.Min(selection.Width, selection.Height) * 0.5;
            this.defaultRadius2 = this.defaultRadius * this.defaultRadius;

            var x_center_offset = selection.Left + (selection.Width * (1.0 + Data.CenterOffset.X) * 0.5);
            var y_center_offset = selection.Top + (selection.Height * (1.0 + Data.CenterOffset.Y) * 0.5);

            ColorBgra colPrimary     = PintaCore.Palette.PrimaryColor.ToColorBgra();
            ColorBgra colSecondary   = PintaCore.Palette.SecondaryColor.ToColorBgra();
            ColorBgra colTransparent = ColorBgra.Transparent;

            int aaSampleCount = Data.Quality * Data.Quality;

            Cairo.PointD *aaPoints = stackalloc Cairo.PointD[aaSampleCount];
            Utility.GetRgssOffsets(aaPoints, aaSampleCount, Data.Quality);
            ColorBgra *samples = stackalloc ColorBgra[aaSampleCount];

            TransformData td;

            foreach (Gdk.Rectangle rect in rois)
            {
                for (int y = rect.Top; y <= rect.GetBottom(); y++)
                {
                    ColorBgra *dstPtr = dst.GetPointAddressUnchecked(rect.Left, y);

                    double relativeY = y - y_center_offset;

                    for (int x = rect.Left; x <= rect.GetRight(); x++)
                    {
                        double relativeX = x - x_center_offset;

                        int sampleCount = 0;

                        for (int p = 0; p < aaSampleCount; ++p)
                        {
                            td.X = relativeX + aaPoints[p].X;
                            td.Y = relativeY - aaPoints[p].Y;

                            InverseTransform(ref td);

                            float sampleX = (float)(td.X + x_center_offset);
                            float sampleY = (float)(td.Y + y_center_offset);

                            ColorBgra sample = colPrimary;

                            if (IsOnSurface(src, sampleX, sampleY))
                            {
                                sample = src.GetBilinearSample(sampleX, sampleY);
                            }
                            else
                            {
                                switch (Data.EdgeBehavior)
                                {
                                case WarpEdgeBehavior.Clamp:
                                    sample = src.GetBilinearSampleClamped(sampleX, sampleY);
                                    break;

                                case WarpEdgeBehavior.Wrap:
                                    sample = src.GetBilinearSampleWrapped(sampleX, sampleY);
                                    break;

                                case WarpEdgeBehavior.Reflect:
                                    sample = src.GetBilinearSampleClamped(ReflectCoord(sampleX, src.Width), ReflectCoord(sampleY, src.Height));

                                    break;

                                case WarpEdgeBehavior.Primary:
                                    sample = colPrimary;
                                    break;

                                case WarpEdgeBehavior.Secondary:
                                    sample = colSecondary;
                                    break;

                                case WarpEdgeBehavior.Transparent:
                                    sample = colTransparent;
                                    break;

                                case WarpEdgeBehavior.Original:
                                    sample = src.GetColorBgraUnchecked(x, y);
                                    break;

                                default:

                                    break;
                                }
                            }

                            samples[sampleCount] = sample;
                            ++sampleCount;
                        }

                        *dstPtr = ColorBgra.Blend(samples, sampleCount);
                        ++dstPtr;
                    }
                }
            }
        }
Ejemplo n.º 5
0
        protected override unsafe Gdk.Rectangle OnMouseMove(Context g, Color strokeColor, ImageSurface surface,
                                                            int x, int y, int lastX, int lastY)
        {
            int rad = (int)(g.LineWidth / 2.0 + 0.5);

            rad /= 2;
            rad *= 2;
            if (rad < 2)
            {
                rad = 2;
            }


            //Initialize lookup table when first used (to prevent slower startup of the application)
            if (lut_factor == null)
            {
                lut_factor = new byte[LUT_Resolution + 1, LUT_Resolution + 1];

                for (int dy = 0; dy < LUT_Resolution + 1; dy++)
                {
                    for (int dx = 0; dx < LUT_Resolution + 1; dx++)
                    {
                        double d = Math.Sqrt(dx * dx + dy * dy) / LUT_Resolution;
                        if (d > 1.0)
                        {
                            lut_factor [dx, dy] = 0;
                        }
                        else
                        {
                            lut_factor [dx, dy] = (byte)(Math.Cos(Math.Sqrt(d) * Math.PI / 2.0) * 255.0);
                        }
                    }
                }
            }

            Gdk.Rectangle surface_rect = new Gdk.Rectangle(0, 0, surface.Width, surface.Height);
            Gdk.Rectangle brush_rect   = new Gdk.Rectangle(x - rad, y - rad, 2 * rad, 2 * rad);
            Gdk.Rectangle dest_rect    = Gdk.Rectangle.Intersect(surface_rect, brush_rect);

            if ((dest_rect.Width > 1) && (dest_rect.Height > 1))
            {
                //Allow Clipping through a temporary surface
                ImageSurface tmp_surface = new ImageSurface(Format.Argb32, dest_rect.Width, dest_rect.Height);

                using (Context g2 = new Context(tmp_surface)) {
                    g2.Operator = Operator.Source;
                    g2.SetSourceSurface(surface, -dest_rect.Left, -dest_rect.Top);
                    g2.Rectangle(new Rectangle(0, 0, dest_rect.Width, dest_rect.Height));
                    g2.Fill();
                }

                //Flush to make sure all drawing operations are finished
                tmp_surface.Flush();

                int[,] mean_r = new int[dest_rect.Width / 2 + 1, dest_rect.Height / 2 + 1];
                int[,] mean_g = new int[dest_rect.Width / 2 + 1, dest_rect.Height / 2 + 1];
                int[,] mean_b = new int[dest_rect.Width / 2 + 1, dest_rect.Height / 2 + 1];
                int[,] mean_a = new int[dest_rect.Width / 2 + 1, dest_rect.Height / 2 + 1];
                int[,] mean_c = new int[dest_rect.Width / 2 + 1, dest_rect.Height / 2 + 1];

                for (int iy = 0; iy < dest_rect.Height / 2; iy++)
                {
                    for (int ix = 0; ix < dest_rect.Width / 2; ix++)
                    {
                        mean_a[ix, iy] = 0;
                        mean_r[ix, iy] = 0;
                        mean_g[ix, iy] = 0;
                        mean_b[ix, iy] = 0;
                        mean_c[ix, iy] = 0;
                    }
                }

                for (int iy = 0; iy < dest_rect.Height; iy++)
                {
                    ColorBgra *srcRowPtr = tmp_surface.GetPointAddressUnchecked(0, iy);
                    for (int ix = 0; ix < dest_rect.Width; ix++)
                    {
                        ColorBgra col = (*srcRowPtr).ToStraightAlpha();
                        int       pos_x = ix >> 1, pos_y = iy >> 1;
                        mean_r[pos_x, pos_y] += col.R;
                        mean_g[pos_x, pos_y] += col.G;
                        mean_b[pos_x, pos_y] += col.B;
                        mean_a[pos_x, pos_y] += col.A;
                        mean_c[pos_x, pos_y]++;
                        srcRowPtr++;
                    }
                }

                for (int iy = 0; iy < dest_rect.Height; iy++)
                {
                    ColorBgra *dstRowPtr = tmp_surface.GetPointAddressUnchecked(0, iy);
                    int        dy        = ((iy + dest_rect.Top - y) * LUT_Resolution) / rad;
                    if (dy < 0)
                    {
                        dy = -dy;
                    }

                    for (int ix = 0; ix < dest_rect.Width; ix++)
                    {
                        ColorBgra col = (*dstRowPtr).ToStraightAlpha();

                        int dx = ((ix + dest_rect.Left - x) * LUT_Resolution) / rad;
                        if (dx < 0)
                        {
                            dx = -dx;
                        }

                        int factor = lut_factor[dx, dy];

                        int pos_x = ix >> 1, pos_y = iy >> 1;
                        int count = mean_c[pos_x, pos_y];

                        int red   = col.R + (col.R - mean_r[pos_x, pos_y] / count);
                        int green = col.G + (col.G - mean_g[pos_x, pos_y] / count);
                        int blue  = col.B + (col.B - mean_b[pos_x, pos_y] / count);
                        int alpha = col.A + (col.A - mean_a[pos_x, pos_y] / count);

                        /*
                         * int diff_red   = (4*red   - tmp[ix-1,iy].R - tmp[ix,iy-1].R - tmp[ix+1,iy].R - tmp[ix,iy+1].R)/4;
                         * int diff_green = (4*green - tmp[ix-1,iy].G - tmp[ix,iy-1].G - tmp[ix+1,iy].G - tmp[ix,iy+1].G)/4;
                         * int diff_blue  = (4*blue  - tmp[ix-1,iy].B - tmp[ix,iy-1].B - tmp[ix+1,iy].B - tmp[ix,iy+1].B)/4;
                         * int diff_alpha = (4*alpha  - tmp[ix-1,iy].A - tmp[ix,iy-1].A - tmp[ix+1,iy].A - tmp[ix,iy+1].A)/4;
                         */
                        //red -= diff_red;
                        //if ((red & 255) != 0) { //Negative or grater than 255
                        if (red > 255)
                        {
                            red = 255;
                        }
                        if (red < 0)
                        {
                            red = 0;
                        }
                        //}
                        //green -= diff_green;
                        //if ((green & 255) != 0) { //Negative or grater than 255
                        if (green > 255)
                        {
                            green = 255;
                        }
                        if (green < 0)
                        {
                            green = 0;
                        }
                        //}
                        //blue -= diff_blue;
                        //if ((blue & 255) != 0) { //Negative or grater than 255
                        if (blue > 255)
                        {
                            blue = 255;
                        }
                        if (blue < 0)
                        {
                            blue = 0;
                        }
                        //}
                        //alpha -= diff_alpha;
                        //if ((alpha & 255) != 0) { //Negative or grater than 255
                        if (alpha > 255)
                        {
                            alpha = 255;
                        }
                        if (alpha < 0)
                        {
                            alpha = 0;
                        }
                        col.R = (byte)((red * factor + col.R * (512 - factor)) >> 9);
                        col.G = (byte)((green * factor + col.G * (512 - factor)) >> 9);
                        col.B = (byte)((blue * factor + col.B * (512 - factor)) >> 9);
                        col.A = (byte)((alpha * factor + col.A * (512 - factor)) >> 9);
                        *dstRowPtr = col.ToPremultipliedAlpha();

                        dstRowPtr++;
                    }
                }

                //Draw the final result on the surface
                g.Operator = Operator.Source;
                g.SetSourceSurface(tmp_surface, dest_rect.Left, dest_rect.Top);
                g.Rectangle(new Rectangle(dest_rect.Left, dest_rect.Top, dest_rect.Width, dest_rect.Height));
                g.Fill();
            }
            return(Gdk.Rectangle.Zero);
        }
Ejemplo n.º 6
0
        unsafe public static void RenderBlurEffect(ImageSurface src, ImageSurface dest, Gdk.Rectangle[] rois, int radius)
        {
            int r = radius;

            int[] w    = CreateGaussianBlurRow(r);
            int   wlen = w.Length;

            int   localStoreSize = wlen * 6 * sizeof(long);
            byte *localStore     = stackalloc byte[localStoreSize];
            byte *p = localStore;

            long *waSums = (long *)p;

            p += wlen * sizeof(long);

            long *wcSums = (long *)p;

            p += wlen * sizeof(long);

            long *aSums = (long *)p;

            p += wlen * sizeof(long);

            long *bSums = (long *)p;

            p += wlen * sizeof(long);

            long *gSums = (long *)p;

            p += wlen * sizeof(long);

            long *rSums = (long *)p;

            p += wlen * sizeof(long);

            // Cache these for a massive performance boost
            int src_width    = src.Width;
            int src_height   = src.Height;
            var src_data_ptr = (ColorBgra *)src.DataPtr;

            foreach (Gdk.Rectangle rect in rois)
            {
                if (rect.Height >= 1 && rect.Width >= 1)
                {
                    for (int y = rect.Top; y < rect.Bottom; ++y)
                    {
                        //Memory.SetToZero (localStore, (ulong)localStoreSize);

                        long waSum = 0;
                        long wcSum = 0;
                        long aSum  = 0;
                        long bSum  = 0;
                        long gSum  = 0;
                        long rSum  = 0;

                        ColorBgra *dstPtr = dest.GetPointAddressUnchecked(rect.Left, y);

                        for (int wx = 0; wx < wlen; ++wx)
                        {
                            int srcX = rect.Left + wx - r;
                            waSums[wx] = 0;
                            wcSums[wx] = 0;
                            aSums[wx]  = 0;
                            bSums[wx]  = 0;
                            gSums[wx]  = 0;
                            rSums[wx]  = 0;

                            if (srcX >= 0 && srcX < src_width)
                            {
                                for (int wy = 0; wy < wlen; ++wy)
                                {
                                    int srcY = y + wy - r;

                                    if (srcY >= 0 && srcY < src_height)
                                    {
                                        var c  = src.GetPointUnchecked(src_data_ptr, src_width, srcX, srcY);
                                        int wp = w[wy];

                                        waSums[wx] += wp;
                                        wp         *= c.A + (c.A >> 7);
                                        wcSums[wx] += wp;
                                        wp        >>= 8;

                                        aSums[wx] += wp * c.A;
                                        bSums[wx] += wp * c.B;
                                        gSums[wx] += wp * c.G;
                                        rSums[wx] += wp * c.R;
                                    }
                                }

                                int wwx = w[wx];
                                waSum += wwx * waSums[wx];
                                wcSum += wwx * wcSums[wx];
                                aSum  += wwx * aSums[wx];
                                bSum  += wwx * bSums[wx];
                                gSum  += wwx * gSums[wx];
                                rSum  += wwx * rSums[wx];
                            }
                        }

                        wcSum >>= 8;

                        if (waSum == 0 || wcSum == 0)
                        {
                            dstPtr->Bgra = 0;
                        }
                        else
                        {
                            int alpha = (int)(aSum / waSum);
                            int blue  = (int)(bSum / wcSum);
                            int green = (int)(gSum / wcSum);
                            int red   = (int)(rSum / wcSum);

                            dstPtr->Bgra = ColorBgra.BgraToUInt32(blue, green, red, alpha);
                        }

                        ++dstPtr;

                        for (int x = rect.Left + 1; x < rect.Right; ++x)
                        {
                            for (int i = 0; i < wlen - 1; ++i)
                            {
                                waSums[i] = waSums[i + 1];
                                wcSums[i] = wcSums[i + 1];
                                aSums[i]  = aSums[i + 1];
                                bSums[i]  = bSums[i + 1];
                                gSums[i]  = gSums[i + 1];
                                rSums[i]  = rSums[i + 1];
                            }

                            waSum = 0;
                            wcSum = 0;
                            aSum  = 0;
                            bSum  = 0;
                            gSum  = 0;
                            rSum  = 0;

                            int wx;
                            for (wx = 0; wx < wlen - 1; ++wx)
                            {
                                long wwx = w[wx];
                                waSum += wwx * waSums[wx];
                                wcSum += wwx * wcSums[wx];
                                aSum  += wwx * aSums[wx];
                                bSum  += wwx * bSums[wx];
                                gSum  += wwx * gSums[wx];
                                rSum  += wwx * rSums[wx];
                            }

                            wx = wlen - 1;

                            waSums[wx] = 0;
                            wcSums[wx] = 0;
                            aSums[wx]  = 0;
                            bSums[wx]  = 0;
                            gSums[wx]  = 0;
                            rSums[wx]  = 0;

                            int srcX = x + wx - r;

                            if (srcX >= 0 && srcX < src_width)
                            {
                                for (int wy = 0; wy < wlen; ++wy)
                                {
                                    int srcY = y + wy - r;

                                    if (srcY >= 0 && srcY < src_height)
                                    {
                                        var c  = src.GetPointUnchecked(src_data_ptr, src_width, srcX, srcY);
                                        int wp = w[wy];

                                        waSums[wx] += wp;
                                        wp         *= c.A + (c.A >> 7);
                                        wcSums[wx] += wp;
                                        wp        >>= 8;

                                        aSums[wx] += wp * (long)c.A;
                                        bSums[wx] += wp * (long)c.B;
                                        gSums[wx] += wp * (long)c.G;
                                        rSums[wx] += wp * (long)c.R;
                                    }
                                }

                                int wr = w[wx];
                                waSum += wr * waSums[wx];
                                wcSum += wr * wcSums[wx];
                                aSum  += wr * aSums[wx];
                                bSum  += wr * bSums[wx];
                                gSum  += wr * gSums[wx];
                                rSum  += wr * rSums[wx];
                            }

                            wcSum >>= 8;

                            if (waSum == 0 || wcSum == 0)
                            {
                                dstPtr->Bgra = 0;
                            }
                            else
                            {
                                int alpha = (int)(aSum / waSum);
                                int blue  = (int)(bSum / wcSum);
                                int green = (int)(gSum / wcSum);
                                int red   = (int)(rSum / wcSum);

                                dstPtr->Bgra = ColorBgra.BgraToUInt32(blue, green, red, alpha);
                            }

                            ++dstPtr;
                        }
                    }
                }
            }
        }
Ejemplo n.º 7
0
        public unsafe override void Render(ImageSurface src, ImageSurface dst, Gdk.Rectangle[] rois)
        {
            this.intensity       = Data.Intensity;
            this.colorSaturation = Data.ColorSaturation;
            this.coverage        = 0.01 * Data.Coverage;

            int dev = this.intensity * this.intensity / 4;
            int sat = this.colorSaturation * 4096 / 100;

            if (threadRand == null)
            {
                threadRand = new Random(unchecked (System.Threading.Thread.CurrentThread.GetHashCode() ^
                                                   unchecked ((int)DateTime.Now.Ticks)));
            }

            Random localRand = threadRand;

            int[] localLookup = lookup;

            foreach (Gdk.Rectangle rect in rois)
            {
                for (int y = rect.Top; y < rect.Bottom; ++y)
                {
                    ColorBgra *srcPtr = src.GetPointAddressUnchecked(rect.Left, y);
                    ColorBgra *dstPtr = dst.GetPointAddressUnchecked(rect.Left, y);

                    for (int x = 0; x < rect.Width; ++x)
                    {
                        if (localRand.NextDouble() > this.coverage)
                        {
                            *dstPtr = *srcPtr;
                        }
                        else
                        {
                            int r;
                            int g;
                            int b;
                            int i;

                            r = localLookup[localRand.Next(tableSize)];
                            g = localLookup[localRand.Next(tableSize)];
                            b = localLookup[localRand.Next(tableSize)];

                            i = (4899 * r + 9618 * g + 1867 * b) >> 14;


                            r = i + (((r - i) * sat) >> 12);
                            g = i + (((g - i) * sat) >> 12);
                            b = i + (((b - i) * sat) >> 12);

                            dstPtr->R = Utility.ClampToByte(srcPtr->R + ((r * dev + 32768) >> 16));
                            dstPtr->G = Utility.ClampToByte(srcPtr->G + ((g * dev + 32768) >> 16));
                            dstPtr->B = Utility.ClampToByte(srcPtr->B + ((b * dev + 32768) >> 16));
                            dstPtr->A = srcPtr->A;
                        }

                        ++srcPtr;
                        ++dstPtr;
                    }
                }
            }
        }
Ejemplo n.º 8
0
        unsafe public override void Render(ImageSurface src, ImageSurface dst, Gdk.Rectangle[] rois)
        {
            int   width     = dst.Width;
            int   height    = dst.Height;
            float hw        = width / 2f;
            float hh        = height / 2f;
            float sin       = (float)Math.Sin(Data.Rotation * Math.PI / 180.0);
            float cos       = (float)Math.Cos(Data.Rotation * Math.PI / 180.0);
            float scale     = (float)Math.PI / Data.TileSize;
            float intensity = Data.Intensity;

            intensity = intensity * intensity / 10 * Math.Sign(intensity);

            int     aaLevel   = 4;
            int     aaSamples = aaLevel * aaLevel + 1;
            PointD *aaPoints  = stackalloc PointD[aaSamples];

            for (int i = 0; i < aaSamples; ++i)
            {
                double x = (i * aaLevel) / (double)aaSamples;
                double y = i / (double)aaSamples;

                x -= (int)x;

                // RGSS + rotation to maximize AA quality
                aaPoints[i] = new PointD((double)(cos * x + sin * y), (double)(cos * y - sin * x));
            }

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

            foreach (var rect in rois)
            {
                for (int y = rect.Top; y <= rect.GetBottom(); y++)
                {
                    float      j      = y - hh;
                    ColorBgra *dstPtr = dst.GetPointAddressUnchecked(rect.Left, y);

                    for (int x = rect.Left; x <= rect.GetRight(); x++)
                    {
                        int   b = 0;
                        int   g = 0;
                        int   r = 0;
                        int   a = 0;
                        float i = x - hw;

                        for (int p = 0; p < aaSamples; ++p)
                        {
                            PointD pt = aaPoints[p];

                            float u = i + (float)pt.X;
                            float v = j - (float)pt.Y;

                            float s = cos * u + sin * v;
                            float t = -sin * u + cos * v;

                            s += intensity * (float)Math.Tan(s * scale);
                            t += intensity * (float)Math.Tan(t * scale);
                            u  = cos * s - sin * t;
                            v  = sin * s + cos * t;

                            int xSample = (int)(hw + u);
                            int ySample = (int)(hh + v);

                            xSample = (xSample + width) % width;
                            // This makes it a little faster
                            if (xSample < 0)
                            {
                                xSample = (xSample + width) % width;
                            }

                            ySample = (ySample + height) % height;
                            // This makes it a little faster
                            if (ySample < 0)
                            {
                                ySample = (ySample + height) % height;
                            }

                            ColorBgra sample = *src.GetPointAddressUnchecked(src_data_ptr, src_width, xSample, ySample);

                            b += sample.B;
                            g += sample.G;
                            r += sample.R;
                            a += sample.A;
                        }

                        *(dstPtr++) = ColorBgra.FromBgra((byte)(b / aaSamples), (byte)(g / aaSamples),
                                                         (byte)(r / aaSamples), (byte)(a / aaSamples));
                    }
                }
            }
        }
Ejemplo n.º 9
0
        protected unsafe override void OnMouseMove(object o, Gtk.MotionNotifyEventArgs args, Cairo.PointD point)
        {
            Document doc = PintaCore.Workspace.ActiveDocument;

            ColorBgra old_color;
            ColorBgra new_color;

            if (mouse_button == 1)
            {
                old_color = PintaCore.Palette.PrimaryColor.ToColorBgra();
                new_color = PintaCore.Palette.SecondaryColor.ToColorBgra();
            }
            else if (mouse_button == 3)
            {
                old_color = PintaCore.Palette.SecondaryColor.ToColorBgra();
                new_color = PintaCore.Palette.PrimaryColor.ToColorBgra();
            }
            else
            {
                last_point = point_empty;
                return;
            }

            int x = (int)point.X;
            int y = (int)point.Y;

            if (last_point.Equals(point_empty))
            {
                last_point = new Point(x, y);
            }

            if (doc.Workspace.PointInCanvas(point))
            {
                surface_modified = true;
            }

            ImageSurface surf      = doc.CurrentUserLayer.Surface;
            ImageSurface tmp_layer = doc.ToolLayer.Surface;

            Gdk.Rectangle roi = GetRectangleFromPoints(last_point, new Point(x, y));

            roi         = PintaCore.Workspace.ClampToImageSize(roi);
            myTolerance = (int)(Tolerance * 256);

            tmp_layer.Flush();

            ColorBgra *tmp_data_ptr  = (ColorBgra *)tmp_layer.DataPtr;
            int        tmp_width     = tmp_layer.Width;
            ColorBgra *surf_data_ptr = (ColorBgra *)surf.DataPtr;
            int        surf_width    = surf.Width;

            // The stencil lets us know if we've already checked this
            // pixel, providing a nice perf boost
            // Maybe this should be changed to a BitVector2DSurfaceAdapter?
            for (int i = roi.X; i <= roi.GetRight(); i++)
            {
                for (int j = roi.Y; j <= roi.GetBottom(); j++)
                {
                    if (stencil[i, j])
                    {
                        continue;
                    }

                    if (IsColorInTolerance(new_color, surf.GetColorBgra(surf_data_ptr, surf_width, i, j)))
                    {
                        *tmp_layer.GetPointAddressUnchecked(tmp_data_ptr, tmp_width, i, j) = AdjustColorDifference(new_color, old_color, surf.GetColorBgra(surf_data_ptr, surf_width, i, j));
                    }

                    stencil[i, j] = true;
                }
            }

            tmp_layer.MarkDirty();

            using (Context g = new Context(surf)) {
                g.AppendPath(doc.Selection.SelectionPath);
                g.FillRule = FillRule.EvenOdd;
                g.Clip();

                g.Antialias = UseAntialiasing ? Antialias.Subpixel : Antialias.None;

                g.MoveTo(last_point.X, last_point.Y);
                g.LineTo(x, y);

                g.LineWidth = BrushWidth;
                g.LineJoin  = LineJoin.Round;
                g.LineCap   = LineCap.Round;

                g.SetSource(tmp_layer);

                g.Stroke();
            }

            doc.Workspace.Invalidate(roi);

            last_point = new Point(x, y);
        }
Ejemplo n.º 10
0
        protected override unsafe Gdk.Rectangle OnMouseMove(Context g, Color strokeColor, ImageSurface surface,
                                                            int x, int y, int lastX, int lastY)
        {
            int rad      = (int)(g.LineWidth / 2.0) + 1;
            int stroke_a = (int)(255.0 * strokeColor.A);
            int stroke_r = (int)(255.0 * strokeColor.R);
            int stroke_g = (int)(255.0 * strokeColor.G);
            int stroke_b = (int)(255.0 * strokeColor.B);

            Gdk.Rectangle surface_rect = new Gdk.Rectangle(0, 0, surface.Width, surface.Height);
            Gdk.Rectangle brush_rect   = new Gdk.Rectangle(x - rad, y - rad, 2 * rad, 2 * rad);
            Gdk.Rectangle dest_rect    = Gdk.Rectangle.Intersect(surface_rect, brush_rect);

            //Initialize lookup table when first used (to prevent slower startup of the application)
            if (lut_factor == null)
            {
                lut_factor = new byte[LUT_Resolution + 1, LUT_Resolution + 1];

                for (int dy = 0; dy < LUT_Resolution + 1; dy++)
                {
                    for (int dx = 0; dx < LUT_Resolution + 1; dx++)
                    {
                        double d = Math.Sqrt(dx * dx + dy * dy) / LUT_Resolution;
                        if (d > 1.0)
                        {
                            lut_factor [dx, dy] = 0;
                        }
                        else
                        {
                            lut_factor [dx, dy] = (byte)(Math.Cos(Math.Sqrt(d) * Math.PI / 2.0) * 255);
                        }
                    }
                }
            }

            if ((dest_rect.Width > 0) && (dest_rect.Height > 0))
            {
                //Allow Clipping through a temporary surface
                ImageSurface tmp_surface = new ImageSurface(Format.Argb32, dest_rect.Width, dest_rect.Height);

                using (Context g2 = new Context(tmp_surface)) {
                    g2.Operator = Operator.Source;
                    g2.SetSourceSurface(surface, -dest_rect.Left, -dest_rect.Top);
                    g2.Rectangle(new Rectangle(0, 0, dest_rect.Width, dest_rect.Height));
                    g2.Fill();
                }

                //Flush to make sure all drawing operations are finished
                tmp_surface.Flush();

                for (int iy = dest_rect.Top; iy < dest_rect.Bottom; iy++)
                {
                    ColorBgra *srcRowPtr = tmp_surface.GetPointAddressUnchecked(0, iy - dest_rect.Top);
                    int        dy        = ((iy - y) * LUT_Resolution) / rad;
                    if (dy < 0)
                    {
                        dy = -dy;
                    }
                    for (int ix = dest_rect.Left; ix < dest_rect.Right; ix++)
                    {
                        ColorBgra col = (*srcRowPtr).ToStraightAlpha();
                        int       dx  = ((ix - x) * LUT_Resolution) / rad;
                        if (dx < 0)
                        {
                            dx = -dx;
                        }

                        int force = lut_factor[dx, dy];
                        col.A = (byte)((col.A * (255 - force) + stroke_a * force) / 255);
                        col.R = (byte)((col.R * (255 - force) + stroke_r * force) / 255);
                        col.G = (byte)((col.G * (255 - force) + stroke_g * force) / 255);
                        col.B = (byte)((col.B * (255 - force) + stroke_b * force) / 255);
                        *srcRowPtr = col.ToPremultipliedAlpha();
                        srcRowPtr++;
                    }
                }
                //Draw the final result on the surface
                g.Operator = Operator.Source;
                g.SetSourceSurface(tmp_surface, dest_rect.Left, dest_rect.Top);
                g.Rectangle(new Rectangle(dest_rect.Left, dest_rect.Top, dest_rect.Width, dest_rect.Height));
                g.Fill();
            }
            return(Gdk.Rectangle.Zero);
        }
Ejemplo n.º 11
0
        public unsafe override void Render(ImageSurface src, ImageSurface dest, Gdk.Rectangle[] rois)
        {
            int width  = src.Width;
            int height = src.Height;

            int arrayLens = 1 + Data.Coarseness;

            int localStoreSize = arrayLens * 5 * sizeof(int);

            byte *localStore = stackalloc byte[localStoreSize];
            byte *p          = localStore;

            int *intensityCount = (int *)p;

            p += arrayLens * sizeof(int);

            uint *avgRed = (uint *)p;

            p += arrayLens * sizeof(uint);

            uint *avgGreen = (uint *)p;

            p += arrayLens * sizeof(uint);

            uint *avgBlue = (uint *)p;

            p += arrayLens * sizeof(uint);

            uint *avgAlpha = (uint *)p;

            p += arrayLens * sizeof(uint);

            byte maxIntensity = (byte)Data.Coarseness;

            foreach (Gdk.Rectangle rect in rois)
            {
                int rectTop    = rect.Top;
                int rectBottom = rect.GetBottom();
                int rectLeft   = rect.Left;
                int rectRight  = rect.GetRight();

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

                for (int y = rectTop; y <= rectBottom; ++y)
                {
                    ColorBgra *dstPtr = dest.GetPointAddressUnchecked(dst_dataptr, dst_width, rect.Left, y);

                    int top    = y - Data.BrushSize;
                    int bottom = y + Data.BrushSize + 1;

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

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

                    for (int x = rectLeft; x <= rectRight; ++x)
                    {
                        SetToZero(localStore, (ulong)localStoreSize);

                        int left  = x - Data.BrushSize;
                        int right = x + Data.BrushSize + 1;

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

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

                        int numInt = 0;

                        for (int j = top; j < bottom; ++j)
                        {
                            ColorBgra *srcPtr = src.GetPointAddressUnchecked(src_dataptr, src_width, left, j);

                            for (int i = left; i < right; ++i)
                            {
                                byte intensity = Utility.FastScaleByteByByte(srcPtr->GetIntensityByte(), maxIntensity);

                                ++intensityCount[intensity];
                                ++numInt;

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

                                ++srcPtr;
                            }
                        }

                        byte chosenIntensity = 0;
                        int  maxInstance     = 0;

                        for (int i = 0; i <= maxIntensity; ++i)
                        {
                            if (intensityCount[i] > maxInstance)
                            {
                                chosenIntensity = (byte)i;
                                maxInstance     = intensityCount[i];
                            }
                        }

                        // TODO: correct handling of alpha values?

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

                        *dstPtr = ColorBgra.FromBgra(B, G, R, A);
                        ++dstPtr;
                    }
                }
            }
        }
Ejemplo n.º 12
0
        public unsafe override void Render(ImageSurface src, ImageSurface dst, Gdk.Rectangle[] rois)
        {
            if (Data.Angle == 0)
            {
                // Copy src to dest
                return;
            }

            int w   = dst.Width;
            int h   = dst.Height;
            int fcx = (w << 15) + (int)(Data.Offset.X * (w << 15));
            int fcy = (h << 15) + (int)(Data.Offset.Y * (h << 15));

            int n = (Data.Quality * Data.Quality) * (30 + Data.Quality * Data.Quality);

            int fr = (int)(Data.Angle * Math.PI * 65536.0 / 181.0);

            foreach (Gdk.Rectangle rect in rois)
            {
                for (int y = rect.Top; y <= rect.GetBottom(); ++y)
                {
                    ColorBgra *dstPtr = dst.GetPointAddressUnchecked(rect.Left, y);
                    ColorBgra *srcPtr = src.GetPointAddressUnchecked(rect.Left, y);

                    for (int x = rect.Left; x <= rect.GetRight(); ++x)
                    {
                        int fx = (x << 16) - fcx;
                        int fy = (y << 16) - fcy;

                        int fsr = fr / n;

                        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;

                        int ox1 = fx;
                        int ox2 = fx;
                        int oy1 = fy;
                        int oy2 = fy;

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

                        for (int i = 0; i < n; ++i)
                        {
                            Rotate(ref ox1, ref oy1, fsr);
                            Rotate(ref ox2, ref oy2, -fsr);

                            int u1 = ox1 + fcx + 32768 >> 16;
                            int v1 = oy1 + fcy + 32768 >> 16;

                            if (u1 > 0 && v1 > 0 && u1 < w && v1 < h)
                            {
                                ColorBgra *sample = src.GetPointAddressUnchecked(src_dataptr, src_width, u1, v1);

                                sr += sample->R * sample->A;
                                sg += sample->G * sample->A;
                                sb += sample->B * sample->A;
                                sa += sample->A;
                                ++sc;
                            }

                            int u2 = ox2 + fcx + 32768 >> 16;
                            int v2 = oy2 + fcy + 32768 >> 16;

                            if (u2 > 0 && v2 > 0 && u2 < w && v2 < h)
                            {
                                ColorBgra *sample = src.GetPointAddressUnchecked(src_dataptr, src_width, u2, v2);

                                sr += sample->R * sample->A;
                                sg += sample->G * sample->A;
                                sb += sample->B * sample->A;
                                sa += sample->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;
                        }

                        ++dstPtr;
                        ++srcPtr;
                    }
                }
            }
        }
Ejemplo n.º 13
0
        public unsafe override void Render(ImageSurface src, ImageSurface dst, Gdk.Rectangle[] rois)
        {
            PointD start = new PointD(0, 0);
            double theta = ((double)(Data.Angle + 180) * 2 * Math.PI) / 360.0;
            double alpha = (double)Data.Distance;
            PointD end   = new PointD((float)alpha * Math.Cos(theta), (float)(-alpha * Math.Sin(theta)));

            if (Data.Centered)
            {
                start.X = -end.X / 2.0f;
                start.Y = -end.Y / 2.0f;

                end.X /= 2.0f;
                end.Y /= 2.0f;
            }

            PointD[] points = new PointD[((1 + Data.Distance) * 3) / 2];

            if (points.Length == 1)
            {
                points[0] = new PointD(0, 0);
            }
            else
            {
                for (int i = 0; i < points.Length; ++i)
                {
                    float frac = (float)i / (float)(points.Length - 1);
                    points[i] = Utility.Lerp(start, end, frac);
                }
            }

            ColorBgra *samples = stackalloc ColorBgra[points.Length];

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

            foreach (Gdk.Rectangle rect in rois)
            {
                for (int y = rect.Top; y <= rect.GetBottom(); ++y)
                {
                    ColorBgra *dstPtr = dst.GetPointAddressUnchecked(rect.Left, y);

                    for (int x = rect.Left; x <= rect.GetRight(); ++x)
                    {
                        int sampleCount = 0;

                        for (int j = 0; j < points.Length; ++j)
                        {
                            PointD pt = new PointD(points[j].X + (float)x, points[j].Y + (float)y);

                            if (pt.X >= 0 && pt.Y >= 0 && pt.X <= (src_width - 1) && pt.Y <= (src_height - 1))
                            {
                                samples[sampleCount] = src.GetBilinearSample(src_dataptr, src_width, src_height, (float)pt.X, (float)pt.Y);
                                ++sampleCount;
                            }
                        }

                        *dstPtr = ColorBgra.Blend(samples, sampleCount);
                        ++dstPtr;
                    }
                }
            }
        }