示例#1
0
        private ColorBgra ComputeCellColor(int x, int y, ImageSurface src, int cellSize, Gdk.Rectangle srcBounds)
        {
            Gdk.Rectangle cell = GetCellBox(x, y, cellSize);
            cell.Intersect(srcBounds);

            int left   = cell.Left;
            int right  = cell.Right - 1;
            int bottom = cell.Bottom - 1;
            int top    = cell.Top;

            ColorBgra colorTopLeft     = src.GetColorBgra(left, top);
            ColorBgra colorTopRight    = src.GetColorBgra(right, top);
            ColorBgra colorBottomLeft  = src.GetColorBgra(left, bottom);
            ColorBgra colorBottomRight = src.GetColorBgra(right, bottom);

            ColorBgra c = ColorBgra.BlendColors4W16IP(colorTopLeft, 16384, colorTopRight, 16384, colorBottomLeft, 16384, colorBottomRight, 16384);

            return(c);
        }
示例#2
0
        protected override void OnMouseDown(Gtk.DrawingArea canvas, Gtk.ButtonPressEventArgs args, PointD point)
        {
            Document doc = PintaCore.Workspace.ActiveDocument;

            Point pos = new Point((int)point.X, (int)point.Y);

            // Don't do anything if we're outside the canvas
            if (pos.X < 0 || pos.X >= doc.ImageSize.Width)
            {
                return;
            }
            if (pos.Y < 0 || pos.Y >= doc.ImageSize.Height)
            {
                return;
            }

            base.OnMouseDown(canvas, args, point);

            Gdk.Region currentRegion = Gdk.Region.Rectangle(doc.GetSelectedBounds(true));

            // See if the mouse click is valid
            if (!currentRegion.PointIn(pos.X, pos.Y) && limitToSelection)
            {
                currentRegion.Dispose();
                currentRegion = null;
                return;
            }

            ImageSurface surface         = doc.CurrentUserLayer.Surface;
            ImageSurface stencil_surface = new ImageSurface(Format.Argb32, (int)surface.Width, (int)surface.Height);

            IBitVector2D stencilBuffer = new BitVector2DSurfaceAdapter(stencil_surface);
            int          tol           = (int)(Tolerance * Tolerance * 256);
            Rectangle    boundingBox;

            if (IsContinguousMode)
            {
                FillStencilFromPoint(surface, stencilBuffer, pos, tol, out boundingBox, currentRegion, limitToSelection);
            }
            else
            {
                FillStencilByColor(surface, stencilBuffer, surface.GetColorBgra(pos.X, pos.Y), tol, out boundingBox, currentRegion, LimitToSelection);
            }

            stencil = stencilBuffer;
            OnFillRegionComputed(stencilBuffer);

            // If a derived tool is only going to use the stencil,
            // don't waste time building the polygon set
            if (CalculatePolygonSet)
            {
                Point[][] polygonSet = stencilBuffer.CreatePolygonSet(boundingBox, 0, 0);
                OnFillRegionComputed(polygonSet);
            }
        }
示例#3
0
        public static unsafe bool ContainsTranslucent(this ImageSurface surf)
        {
            bool ret = false;

            ColorBgra *ptr   = (ColorBgra *)surf.DataPtr;
            int        width = surf.Width;

            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < surf.Height; y++)
                {
                    int a = (int)surf.GetColorBgra(ptr, width, x, y).A;

                    if (a > 0 && a < 255)
                    {
                        Console.WriteLine(surf.GetColorBgra(ptr, width, x, y).ToString());
                        ret = true;
                    }
                }
            }

            return(ret);
        }
示例#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 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.CurrentLayer.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);
        }
示例#6
0
        private void Draw(DrawingArea drawingarea1, Color tool_color, Cairo.PointD point, bool first_pixel)
        {
            int x = (int)point.X;
            int y = (int)point.Y;

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

                if (!first_pixel)
                {
                    return;
                }
            }

            Document doc = PintaCore.Workspace.ActiveDocument;

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

            ImageSurface surf = doc.CurrentLayer.Surface;

            if (first_pixel)
            {
                // Does Cairo really not support a single-pixel-long single-pixel-wide line?
                surf.Flush();
                int       shiftedX = (int)point.X;
                int       shiftedY = (int)point.Y;
                ColorBgra source   = surf.GetColorBgra(shiftedX, shiftedY);
                source = UserBlendOps.NormalBlendOp.ApplyStatic(source, tool_color.ToColorBgra());
                surf.SetColorBgra(source, shiftedX, shiftedY);
                surf.MarkDirty();
            }
            else
            {
                using (Context g = new Context(surf)) {
                    g.AppendPath(doc.Selection.SelectionPath);
                    g.FillRule = FillRule.EvenOdd;
                    g.Clip();

                    g.Antialias = Antialias.None;

                    // Adding 0.5 forces cairo into the correct square:
                    // See https://bugs.launchpad.net/bugs/672232
                    g.MoveTo(last_point.X + 0.5, last_point.Y + 0.5);
                    g.LineTo(x + 0.5, y + 0.5);

                    g.Color     = tool_color;
                    g.LineWidth = 1;
                    g.LineCap   = LineCap.Square;

                    g.Stroke();
                }
            }

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

            if (doc.Workspace.IsPartiallyOffscreen(r))
            {
                doc.Workspace.Invalidate();
            }
            else
            {
                doc.Workspace.Invalidate(r);
            }

            last_point = new Point(x, y);
        }
示例#7
0
        public unsafe override void Render(ImageSurface src, ImageSurface dst, Gdk.Rectangle[] rois)
        {
            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 - Data.CenterOffset.Y;

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

                        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 + Data.CenterOffset.X);
                            float sampleY = (float)(td.Y + Data.CenterOffset.Y);

                            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.GetColorBgra(x, y);
                                    break;

                                default:

                                    break;
                                }
                            }

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

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