示例#1
0
        public void Clear(bool newValue)
        {
            unsafe {
                uint val = newValue ? 0xffffffff : 0;

                for (int y = 0; y < Height; ++y)
                {
                    ColorBgra *row = surface.GetRowAddressUnchecked(src_data_ptr, src_width, y);

                    int w = (this.Width + 31) / 32;

                    while (w > 0)
                    {
                        row->Bgra = val;
                        ++row;
                        --w;
                    }
                }
            }
        }
示例#2
0
        public unsafe override void Render(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.Render(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;
                    }
                }
            }
        }
示例#3
0
        public unsafe static void FillStencilByColor(ImageSurface surface, IBitVector2D stencil, ColorBgra cmp, int tolerance,
                                                     out Rectangle boundingBox, Gdk.Region limitRegion, bool limitToSelection)
        {
            int top    = int.MaxValue;
            int bottom = int.MinValue;
            int left   = int.MaxValue;
            int right  = int.MinValue;

            Gdk.Rectangle[] scans;

            stencil.Clear(false);

            if (limitToSelection)
            {
                using (Gdk.Region excluded = Gdk.Region.Rectangle(new Gdk.Rectangle(0, 0, stencil.Width, stencil.Height))) {
                    excluded.Xor(limitRegion);
                    scans = excluded.GetRectangles();
                }
            }
            else
            {
                scans = new Gdk.Rectangle[0];
            }

            foreach (Gdk.Rectangle rect in scans)
            {
                stencil.Set(rect, true);
            }

            Parallel.For(0, surface.Height, y =>
            {
                bool foundPixelInRow = false;
                ColorBgra *ptr       = surface.GetRowAddressUnchecked(y);

                int surfaceWidth = surface.Width;
                for (int x = 0; x < surfaceWidth; ++x)
                {
                    if (CheckColor(cmp, *ptr, tolerance))
                    {
                        stencil.SetUnchecked(x, y, true);

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

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

                        foundPixelInRow = true;
                    }

                    ++ptr;
                }

                if (foundPixelInRow)
                {
                    if (y < top)
                    {
                        top = y;
                    }

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

            foreach (Gdk.Rectangle rect in scans)
            {
                stencil.Set(rect, false);
            }

            boundingBox = new Rectangle(left, top, right - left + 1, bottom - top + 1);
        }
示例#4
0
        public unsafe static void FillStencilFromPoint(ImageSurface surface, IBitVector2D stencil, Point start, int tolerance,
                                                       out Rectangle boundingBox, Gdk.Region limitRegion, bool limitToSelection)
        {
            ColorBgra cmp    = surface.GetColorBgra(start.X, start.Y);
            int       top    = int.MaxValue;
            int       bottom = int.MinValue;
            int       left   = int.MaxValue;
            int       right  = int.MinValue;

            Gdk.Rectangle[] scans;

            stencil.Clear(false);

            if (limitToSelection)
            {
                using (Gdk.Region excluded = Gdk.Region.Rectangle(new Gdk.Rectangle(0, 0, stencil.Width, stencil.Height))) {
                    excluded.Xor(limitRegion);
                    scans = excluded.GetRectangles();
                }
            }
            else
            {
                scans = new Gdk.Rectangle[0];
            }

            foreach (Gdk.Rectangle rect in scans)
            {
                stencil.Set(rect, true);
            }

            Queue <Point> queue = new Queue <Point> (16);

            queue.Enqueue(start);

            while (queue.Count > 0)
            {
                Point pt = queue.Dequeue();

                ColorBgra *rowPtr     = surface.GetRowAddressUnchecked(pt.Y);
                int        localLeft  = pt.X - 1;
                int        localRight = pt.X;

                while (localLeft >= 0 &&
                       !stencil.GetUnchecked(localLeft, pt.Y) &&
                       CheckColor(cmp, rowPtr[localLeft], tolerance))
                {
                    stencil.SetUnchecked(localLeft, pt.Y, true);
                    --localLeft;
                }

                int surfaceWidth = surface.Width;
                while (localRight < surfaceWidth &&
                       !stencil.GetUnchecked(localRight, pt.Y) &&
                       CheckColor(cmp, rowPtr[localRight], tolerance))
                {
                    stencil.SetUnchecked(localRight, pt.Y, true);
                    ++localRight;
                }

                ++localLeft;
                --localRight;

                Action <int> checkRow = (row) =>
                {
                    int        sleft       = localLeft;
                    int        sright      = localLeft;
                    ColorBgra *otherRowPtr = surface.GetRowAddressUnchecked(row);

                    for (int sx = localLeft; sx <= localRight; ++sx)
                    {
                        if (!stencil.GetUnchecked(sx, row) &&
                            CheckColor(cmp, otherRowPtr[sx], tolerance))
                        {
                            ++sright;
                        }
                        else
                        {
                            if (sright - sleft > 0)
                            {
                                queue.Enqueue(new Point(sleft, row));
                            }

                            ++sright;
                            sleft = sright;
                        }
                    }

                    if (sright - sleft > 0)
                    {
                        queue.Enqueue(new Point(sleft, row));
                    }
                };

                if (pt.Y > 0)
                {
                    checkRow(pt.Y - 1);
                }

                if (pt.Y < surface.Height - 1)
                {
                    checkRow(pt.Y + 1);
                }

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

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

                if (pt.Y < top)
                {
                    top = pt.Y;
                }

                if (pt.Y > bottom)
                {
                    bottom = pt.Y;
                }
            }

            foreach (Gdk.Rectangle rect in scans)
            {
                stencil.Set(rect, false);
            }

            boundingBox = new Rectangle(left, top, right - left + 1, bottom - top + 1);
        }
示例#5
0
        protected unsafe void eraseSmooth(ImageSurface surf, Context g, PointD start, PointD end)
        {
            int rad = (int)(BrushWidth / 2.0) + 1;
            //Premultiply with alpha value
            byte bk_col_a  = (byte)(PintaCore.Palette.SecondaryColor.A * 255.0);
            byte bk_col_r  = (byte)(PintaCore.Palette.SecondaryColor.R * bk_col_a);
            byte bk_col_g  = (byte)(PintaCore.Palette.SecondaryColor.G * bk_col_a);
            byte bk_col_b  = (byte)(PintaCore.Palette.SecondaryColor.B * bk_col_a);
            int  num_steps = (int)start.Distance(end) / rad + 1;

            //Initialize lookup table when first used (to prevent slower startup of the application)
            initLookupTable();

            for (int step = 0; step < num_steps; step++)
            {
                PointD pt = Utility.Lerp(start, end, (float)step / num_steps);
                int    x = (int)pt.X, y = (int)pt.Y;

                Gdk.Rectangle surface_rect = new Gdk.Rectangle(0, 0, surf.Width, surf.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 > 0) && (dest_rect.Height > 0))
                {
                    //Allow Clipping through a temporary surface
                    using (ImageSurface tmp_surface = copySurfacePart(surf, dest_rect)) {
                        for (int iy = dest_rect.Top; iy < dest_rect.Bottom; iy++)
                        {
                            ColorBgra *srcRowPtr = tmp_surface.GetRowAddressUnchecked(iy - dest_rect.Top);
                            int        dy        = ((iy - y) * LUT_Resolution) / rad;
                            if (dy < 0)
                            {
                                dy = -dy;
                            }
                            byte[] lut_factor_row = lut_factor [dy];

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

                                int force = lut_factor_row [dx];
                                //Note: premultiplied alpha is used!
                                if (mouse_button == 3)
                                {
                                    col.A = (byte)((col.A * force + bk_col_a * (255 - force)) / 255);
                                    col.R = (byte)((col.R * force + bk_col_r * (255 - force)) / 255);
                                    col.G = (byte)((col.G * force + bk_col_g * (255 - force)) / 255);
                                    col.B = (byte)((col.B * force + bk_col_b * (255 - force)) / 255);
                                }
                                else
                                {
                                    col.A = (byte)(col.A * force / 255);
                                    col.R = (byte)(col.R * force / 255);
                                    col.G = (byte)(col.G * force / 255);
                                    col.B = (byte)(col.B * force / 255);
                                }
                                *srcRowPtr = col;
                                srcRowPtr++;
                            }
                        }
                        //Draw the final result on the surface
                        pasteSurfacePart(g, tmp_surface, dest_rect);
                    }
                }
            }
        }