private void Image_Loaded(object sender, RoutedEventArgs e) { Image image = (Image)sender; using (ImageSurface surface = new ImageSurface(Format.Argb32, (int)image.Width, (int)image.Height)) { using (Context context = new Context(surface)) { PointD p = new PointD(10.0, 10.0); PointD p2 = new PointD(100.0, 10.0); PointD p3 = new PointD(100.0, 100.0); PointD p4 = new PointD(10.0, 100.0); context.MoveTo(p); context.LineTo(p2); context.LineTo(p3); context.LineTo(p4); context.LineTo(p); context.ClosePath(); context.Fill(); context.MoveTo(140.0, 110.0); context.SetFontSize(32.0); context.SetSourceColor(new Color(0.0, 0.0, 0.8, 1.0)); context.ShowText("Hello Cairo!"); surface.Flush(); RgbaBitmapSource source = new RgbaBitmapSource(surface.Data, surface.Width); image.Source = source; } } }
protected override Gdk.Rectangle OnMouseMove(Context g, Color strokeColor, ImageSurface surface, int x, int y, int lastX, int lastY) { // Cairo does not support a single-pixel-long single-pixel-wide line if (x == lastX && y == lastY && g.LineWidth == 1 && PintaCore.Workspace.ActiveWorkspace.PointInCanvas(new PointD(x, y))) { surface.Flush(); ColorBgra source = surface.GetColorBgraUnchecked(x, y); source = UserBlendOps.NormalBlendOp.ApplyStatic(source, strokeColor.ToColorBgra()); surface.SetColorBgra(source, x, y); surface.MarkDirty(); return(new Gdk.Rectangle(x - 1, y - 1, 3, 3)); } g.MoveTo(lastX + 0.5, lastY + 0.5); g.LineTo(x + 0.5, y + 0.5); g.StrokePreserve(); Gdk.Rectangle dirty = g.FixedStrokeExtents().ToGdkRectangle(); // For some reason (?!) we need to inflate the dirty // rectangle for small brush widths in zoomed images dirty.Inflate(1, 1); return(dirty); }
public unsafe override void Render(ImageSurface src, ImageSurface dest, Gdk.Rectangle[] rois) { dest.Flush(); foreach (Gdk.Rectangle rect in rois) { time ^= System.Environment.TickCount; time = time * 17 + 7; Random rnd = new Random(time); for (int y = rect.Top; y <= rect.GetBottom(); y++) { ColorBgra *srcRowPtr = src.GetPointAddressUnchecked(rect.Left, y); ColorBgra *dstRowPtr = dest.GetPointAddressUnchecked(rect.Left, y); ColorBgra *dstRowEndPtr = dstRowPtr + rect.Width; while (dstRowPtr < dstRowEndPtr) { ColorBgra col = (*srcRowPtr).ToStraightAlpha(); col.A = (byte)(rnd.Next() & 255); *dstRowPtr = col.ToPremultipliedAlpha(); ++dstRowPtr; ++srcRowPtr; } } } }
private Pixbuf ProcessImpl(Pixbuf input, Cms.Profile input_profile, bool fast) { Pixbuf result; using (ImageInfo info = new ImageInfo(input)) { using (ImageSurface surface = new ImageSurface(Format.Argb32, input.Width, input.Height)) { using (Context ctx = new Context(surface)) { ctx.Matrix = info.Fill(info.Bounds, angle); using (SurfacePattern p = new SurfacePattern(info.Surface)) { if (fast) { p.Filter = Filter.Fast; } ctx.Source = p; ctx.Paint(); } result = surface.ToPixbuf(); surface.Flush(); } } } return(result); }
public unsafe override void Render(ImageSurface src, ImageSurface dest, Gdk.Rectangle[] rois) { dest.Flush(); foreach (Gdk.Rectangle rect in rois) { for (int y = rect.Top; y <= rect.GetBottom(); y++) { ColorBgra *srcRowPtr = src.GetPointAddressUnchecked(rect.Left, y); ColorBgra *dstRowPtr = dest.GetPointAddressUnchecked(rect.Left, y); ColorBgra *dstRowEndPtr = dstRowPtr + rect.Width; while (dstRowPtr < dstRowEndPtr) { //ToStraightAlpha() and ToPremultipliedAlpha() are not needed here ColorBgra col = (*srcRowPtr); col.R = col.A; col.G = col.A; col.B = col.A; col.A = 255; *dstRowPtr = col; ++dstRowPtr; ++srcRowPtr; } } } }
void updateGraphic(string file) { int width = 100; int height = 15; int x = 10; int y = 6; Bitmap bmp = new Bitmap(file); BitmapData data = bmp.LockBits(new System.Drawing.Rectangle(x, y, width, height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); int stride = 4 * width; using (ImageSurface draw = new ImageSurface(data.Scan0, Format.Argb32, width, height, stride)) { using (Context gr = new Context(draw)) { //Rectangle r = new Rectangle(0, 0, renderBounds.Width, renderBounds.Height); gr.SelectFontFace("MagicMedieval", FontSlant.Normal, FontWeight.Bold); gr.SetFontSize(12); gr.SetSourceColor(Crow.Color.Black); string test = "Test string"; FontExtents fe = gr.FontExtents; TextExtents te = gr.TextExtents(test); double xt = 20;// 0.5 - te.XBearing - te.Width / 2, double yt = fe.Height; gr.MoveTo(xt, yt); gr.ShowText(test); using (ImageSurface imgSurf = new ImageSurface(@"images/manaw.png")) { gr.SetSourceSurface(imgSurf, 0, 0); gr.Paint(); } draw.Flush(); } //draw.WriteToPng(directories.rootDir + @"test.png"); } imgHelpers.imgHelpers.flipY(data.Scan0, stride, height); GL.TexSubImage2D(TextureTarget.Texture2D, 0, x, bmp.Height - y - height, width, height, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0); bmp.UnlockBits(data); }
private ImageSurface copySurfacePart(ImageSurface surf, Gdk.Rectangle dest_rect) { ImageSurface tmp_surface = new ImageSurface(Format.Argb32, dest_rect.Width, dest_rect.Height); using (Context g = new Context(tmp_surface)) { g.Operator = Operator.Source; g.SetSourceSurface(surf, -dest_rect.Left, -dest_rect.Top); g.Rectangle(new Rectangle(0, 0, dest_rect.Width, dest_rect.Height)); g.Fill(); } //Flush to make sure all drawing operations are finished tmp_surface.Flush(); return(tmp_surface); }
protected unsafe override void OnFillRegionComputed(IBitVector2D stencil) { Document doc = PintaCore.Workspace.ActiveDocument; ImageSurface surf = doc.ToolLayer.Surface; using (var g = new Context(surf)) { g.Operator = Operator.Source; g.SetSource(doc.CurrentUserLayer.Surface); g.Paint(); } SimpleHistoryItem hist = new SimpleHistoryItem(Icon, Name); hist.TakeSnapshotOfLayer(doc.CurrentUserLayer); ColorBgra color = fill_color.ToColorBgra().ToPremultipliedAlpha(); ColorBgra *dstPtr = (ColorBgra *)surf.DataPtr; int width = surf.Width; surf.Flush(); // Color in any pixel that the stencil says we need to fill Parallel.For(0, stencil.Height, y => { int stencil_width = stencil.Width; for (int x = 0; x < stencil_width; ++x) { if (stencil.GetUnchecked(x, y)) { surf.SetColorBgraUnchecked(dstPtr, width, color, x, y); } } }); surf.MarkDirty(); // Transfer the temp layer to the real one, // respecting any selection area using (var g = doc.CreateClippedContext()) { g.Operator = Operator.Source; g.SetSource(surf); g.Paint(); } doc.ToolLayer.Clear(); doc.History.PushNewItem(hist); doc.Workspace.Invalidate(); }
/// <summary> /// Internal drawing context creation on a cached surface limited to slot size /// this trigger the effective drawing routine </summary> protected virtual void RecreateCache () { int stride = 4 * Slot.Width; int bmpSize = Math.Abs (stride) * Slot.Height; bmp = new byte[bmpSize]; IsDirty = false; using (ImageSurface draw = new ImageSurface(bmp, Format.Argb32, Slot.Width, Slot.Height, stride)) { using (Context gr = new Context (draw)) { gr.Antialias = Interface.Antialias; onDraw (gr); } draw.Flush (); } }
public static Color GetPixel(this ImageSurface sf, int x, int y) { int pixelSize; switch (sf.Format) { case Format.Argb32: pixelSize = 4; break; case Format.Rgb24: pixelSize = 3; break; default: throw new ArgumentOutOfRangeException(); } sf.Flush(); int start = x * pixelSize + y * sf.Stride; byte [] data = sf.Data; switch (sf.Format) { case Format.Argb32: return(new Color( data [start + 1] / 255.0, data [start + 2] / 255.0, data [start + 3] / 255.0, data [start + 0] / 255.0)); case Format.Rgb24: return(new Color( data [start + 0] / 255.0, data [start + 1] / 255.0, data [start + 2] / 255.0)); default: throw new ArgumentOutOfRangeException(); } }
private unsafe void ApplyAndSwap(ImageSurface dst, bool swap) { dst.Flush(); var dest_width = dst.Width; var dst_ptr = (ColorBgra *)dst.DataPtr; var mask_index = 0; ColorBgra swap_pixel; fixed(ColorBgra *fixed_ptr = pixels) { var pixel_ptr = fixed_ptr; dst_ptr += bounds.X + bounds.Y * dest_width; for (int y = bounds.Y; y <= bounds.GetBottom(); y++) { for (int x = bounds.X; x <= bounds.GetRight(); x++) { if (bitmask[mask_index++]) { if (swap) { swap_pixel = *dst_ptr; *dst_ptr = *pixel_ptr; *pixel_ptr++ = swap_pixel; } else { *dst_ptr = *pixel_ptr++; } } dst_ptr++; } dst_ptr += dest_width - bounds.Width; } } dst.MarkDirty(); }
Pixbuf ProcessImpl(Pixbuf input, Cms.Profile inputProfile, bool fast) { Pixbuf result; using (var info = new ImageInfo(input)) { using (var soft = new SoftFocus(info)) { soft.Radius = radius; using (var surface = new ImageSurface(Format.Argb32, input.Width, input.Height)) { using (var ctx = new Context(surface)) { soft.Apply(ctx, info.Bounds); } result = surface.ToPixbuf(); surface.Flush(); } } } return(result); }
protected override void RecreateCache() { lock (mutex) { int stride = 4 * Slot.Width; int bmpSize = Math.Abs(stride) * Slot.Height; if (lastVisibleLines > 0) { byte[] newBmp = new byte[bmpSize]; using (ImageSurface draw = new ImageSurface(newBmp, Format.Argb32, Slot.Width, Slot.Height, stride)) { using (Context gr = new Context(draw)) { using (ImageSurface lastDraw = new ImageSurface(bmp, Format.Argb32, LastPaintedSlot.Width, LastPaintedSlot.Height, LastPaintedSlot.Width * 4)) { gr.SetSource(lastDraw, 0, (lastScroll - scroll) * lineHeight); gr.Paint(); } } } bmp = newBmp; } else { bmp = new byte[bmpSize]; } IsDirty = false; using (ImageSurface draw = new ImageSurface(bmp, Format.Argb32, Slot.Width, Slot.Height, stride)) { using (Context gr = new Context(draw)) { gr.Antialias = Interface.Antialias; onDraw(gr); } draw.Flush(); } } }
static void Main(string[] args) { int height = 512; int width = 512; int stride = 4 * width; int bmpSize = stride * height; byte[] bmp = new byte[bmpSize]; using (ImageSurface surf = new ImageSurface(bmp, Format.Argb32, width, height, stride)) { using (Context ctx = new Context(surf)) { ctx.SetSourceRGB(1, 0, 0); ctx.Rectangle(10, 10, 100, 100); ctx.Fill(); } surf.Flush(); //surf.WriteToPng(@"c:/test.png"); } //now you have bmp filled, and may pass it to your game engine as texture }
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); if (rad < 2) { rad = 2; } 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(); ColorBgra[,] tmp = new ColorBgra[dest_rect.Width, dest_rect.Height]; 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++) { tmp[ix, iy] = (*srcRowPtr).ToStraightAlpha(); srcRowPtr++; } } for (int iy = 1; iy < dest_rect.Height - 1; iy++) { ColorBgra *dstRowPtr = tmp_surface.GetPointAddressUnchecked(1, iy); int dy = dest_rect.Top + iy - y; for (int ix = 1; ix < dest_rect.Width - 1; ix++) { int dx = dest_rect.Left + ix - x; if ((dx * dx + dy * dy) < rad * rad) { ColorBgra col = ColorBgra.Black; col.R = (byte)((2 * tmp[ix, iy].R + tmp[ix - 1, iy].R + tmp[ix + 1, iy].R + tmp[ix, iy - 1].R + tmp[ix, iy + 1].R + 3) / 6); col.G = (byte)((2 * tmp[ix, iy].G + tmp[ix - 1, iy].G + tmp[ix + 1, iy].G + tmp[ix, iy - 1].G + tmp[ix, iy + 1].G + 3) / 6); col.B = (byte)((2 * tmp[ix, iy].B + tmp[ix - 1, iy].B + tmp[ix + 1, iy].B + tmp[ix, iy - 1].B + tmp[ix, iy + 1].B + 3) / 6); col.A = (byte)((2 * tmp[ix, iy].A + tmp[ix - 1, iy].A + tmp[ix + 1, iy].A + tmp[ix, iy - 1].A + tmp[ix, iy + 1].A + 3) / 6); *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); }
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.GetColorBgraUnchecked(surf_data_ptr, surf_width, i, j))) { *tmp_layer.GetPointAddressUnchecked(tmp_data_ptr, tmp_width, i, j) = AdjustColorDifference(new_color, old_color, surf.GetColorBgraUnchecked(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); }
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; 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.0); } } } } 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(); int mean_r = 0, mean_g = 0, mean_b = 0; int max_diff_r = 1, max_diff_g = 1, max_diff_b = 1; int sz = 0; byte[,] factors = new byte[dest_rect.Right - dest_rect.Left, dest_rect.Bottom - dest_rect.Top]; for (int iy = dest_rect.Top; iy < dest_rect.Bottom; iy++) { ColorBgra *srcRowPtr = tmp_surface.GetPointAddressUnchecked(0, iy - dest_rect.Top); 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 dy = ((iy - y) * LUT_Resolution) / rad; if (dy < 0) { dy = -dy; } int factor = lut_factor[dx, dy]; sz += factor; mean_r += col.R * factor; mean_g += col.G * factor; mean_b += col.B * factor; srcRowPtr++; } } if (sz > 0) { mean_r /= sz; mean_g /= sz; mean_b /= sz; } for (int iy = dest_rect.Top; iy < dest_rect.Bottom; iy++) { ColorBgra *srcRowPtr = tmp_surface.GetPointAddressUnchecked(0, iy - dest_rect.Top); for (int ix = dest_rect.Left; ix < dest_rect.Right; ix++) { ColorBgra col = (*srcRowPtr).ToStraightAlpha(); int dr = col.R - mean_r; int dg = col.G - mean_g; int db = col.B - mean_b; if (dr < 0) { dr = -dr; } if (dg < 0) { dg = -dg; } if (db < 0) { db = -db; } if (dr > max_diff_r) { max_diff_r = dr; } if (dg > max_diff_g) { max_diff_g = dg; } if (db > max_diff_b) { max_diff_b = db; } srcRowPtr++; } } 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 dr = ((col.R - mean_r) * 2 * LUT_Resolution) / max_diff_r; int dg = ((col.G - mean_g) * 2 * LUT_Resolution) / max_diff_g; int db = ((col.B - mean_b) * 2 * LUT_Resolution) / max_diff_b; if (dr < 0) { dr = -dr; } if (dg < 0) { dg = -dg; } if (db < 0) { db = -db; } if (dr > LUT_Resolution) { dr = LUT_Resolution; } if (dg > LUT_Resolution) { dg = LUT_Resolution; } if (db > LUT_Resolution) { db = LUT_Resolution; } int factor; if ((max_diff_r > 32) || (max_diff_g > 32) || (max_diff_b > 32)) { factor = lut_factor[dx, dy] * lut_factor[dg, (dr + db) / 2]; col.A = (byte)((col.A * (0xFFFF - factor)) / 0xFFFF); } else { factor = lut_factor[dx, dy]; col.A = (byte)((col.A * (0xFF - factor)) / 0xFF); } *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); }
unsafe public 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; Parallel.ForEach(Enumerable.Range(rect.Top, rect.Height), (y) => ProcessGradientLine(startAlpha, endAlpha, y, mainrect, surface, src_data_ptr, src_width)); } } surface.MarkDirty(); AfterRender(); }
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.CurrentUserLayer.Surface; if (first_pixel && doc.Workspace.PointInCanvas(point)) { // 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.GetColorBgraUnchecked(shiftedX, shiftedY); if (UseAlphaBlending) { source = UserBlendOps.NormalBlendOp.ApplyStatic(source, tool_color.ToColorBgra()); } else { source = tool_color.ToColorBgra(); } surf.SetColorBgra(source.ToPremultipliedAlpha(), 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.SetSourceColor(tool_color); if (UseAlphaBlending) { g.SetBlendMode(BlendMode.Normal); } else { g.Operator = Operator.Source; } g.LineWidth = 1; g.LineCap = LineCap.Square; g.Stroke(); } } Gdk.Rectangle r = GetRectangleFromPoints(last_point, new Point(x, y)); doc.Workspace.Invalidate(doc.ClampToImageSize(r)); last_point = new Point(x, y); }
/// <summary> /// The average color of the pixels in the current represenation of the item, /// weighted for saturation and opacity. /// </summary> /// <returns> /// A <see cref="Cairo.Color"/> /// </returns> public Cairo.Color AverageColor() { if (icon_buffers [0] == null) { return(new Cairo.Color(1, 1, 1, 1)); } if (average_color.HasValue) { return(average_color.Value); } ImageSurface sr = new ImageSurface(Format.ARGB32, icon_buffers [0].Width, icon_buffers [0].Height); using (Context cr = new Context(sr)) { cr.Operator = Operator.Source; icon_buffers [0].Internal.Show(cr, 0, 0); } sr.Flush(); byte [] data; try { data = sr.Data; } catch { return(new Cairo.Color(1, 1, 1, 1)); } byte r, g, b; double rTotal = 0; double gTotal = 0; double bTotal = 0; unsafe { fixed(byte *dataSrc = data) { byte *dataPtr = dataSrc; for (int i = 0; i < data.Length - 3; i += 4) { b = dataPtr [0]; g = dataPtr [1]; r = dataPtr [2]; byte max = Math.Max(r, Math.Max(g, b)); byte min = Math.Min(r, Math.Min(g, b)); double delta = max - min; double sat; if (delta == 0) { sat = 0; } else { sat = delta / max; } double score = .2 + .8 * sat; rTotal += r * score; gTotal += g * score; bTotal += b * score; dataPtr += 4; } } } double pixelCount = icon_buffers [0].Width * icon_buffers [0].Height * byte.MaxValue; // FIXME: once we use mono 2.6.3+ we can do sr.Dispose () (sr as IDisposable).Dispose(); sr.Destroy(); average_color = new Cairo.Color(rTotal / pixelCount, gTotal / pixelCount, bTotal / pixelCount) .SetValue(.8) .MultiplySaturation(1.15); return(average_color.Value); }
public void SetDrawable(Drawable drawable) { _drawable = drawable; _surface.Flush(); }
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); }
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); if (rad < 2) { rad = 2; } 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(); ColorBgra[,] tmp = new ColorBgra[dest_rect.Width, dest_rect.Height]; 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++) { tmp[ix, iy] = (*srcRowPtr).ToStraightAlpha(); srcRowPtr++; } } for (int iy = 1; iy < dest_rect.Height - 1; iy++) { ColorBgra *dstRowPtr = tmp_surface.GetPointAddressUnchecked(1, iy); int dy = dest_rect.Top + iy - y; for (int ix = 1; ix < dest_rect.Width - 1; ix++) { int dx = dest_rect.Left + ix - x; if ((dx * dx + dy * dy) < rad * rad) { ColorBgra col; ColorBgra tmpCol = tmp [ix, iy]; int red = tmpCol.R; int green = tmpCol.G; int blue = tmpCol.B; int alpha = tmpCol.A; 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 = ColorBgra.FromBgra((byte)blue, (byte)green, (byte)red, (byte)alpha).ToPremultipliedAlpha(); *dstRowPtr = col; } 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); }
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); int stroke_cb = (-173 * stroke_r - 339 * stroke_g + 512 * stroke_b) >> 9; int stroke_cr = (512 * stroke_r - 429 * stroke_g - 83 * stroke_b) >> 9; 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] * stroke_a); int col_y = (306 * col.R + 601 * col.G + 117 * col.B + 256) >> 9; int red = (256 * col_y + 359 * stroke_cr + 256) >> 9; int green = (256 * col_y - 88 * stroke_cb - 183 * stroke_cr + 256) >> 9; int blue = (256 * col_y + 454 * stroke_cb + 256) >> 9; if (red > 255) { red = 255; } if (red < 0) { red = 0; } if (green > 255) { green = 255; } if (green < 0) { green = 0; } if (blue > 255) { blue = 255; } if (blue < 0) { blue = 0; } col.R = (byte)((col.R * (255 * 255 - force) + red * force + 32512) / (255 * 255)); col.G = (byte)((col.G * (255 * 255 - force) + green * force + 32512) / (255 * 255)); col.B = (byte)((col.B * (255 * 255 - force) + blue * force + 32512) / (255 * 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); }