Skip to content

Commit

Permalink
Finish converting to Span<ColorBgra>
Browse files Browse the repository at this point in the history
  • Loading branch information
cameronwhite committed Dec 29, 2022
1 parent ec647f0 commit 9c3ad88
Show file tree
Hide file tree
Showing 11 changed files with 53 additions and 112 deletions.
6 changes: 3 additions & 3 deletions Pinta.Core/Actions/ImageActions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ private void HandlePintaCoreActionsImageCropToSelectionActivated (object sender,
private static bool IsConstantRow (ImageSurface surf, Cairo.Color color, int y)
{
for (int x = 0; x < surf.Width; ++x) {
if (!color.Equals (surf.GetPixel (x, y)))
if (!color.Equals (surf.GetColorBgra (x, y).ToCairoColor ()))
return false;
}

Expand All @@ -220,7 +220,7 @@ private static bool IsConstantRow (ImageSurface surf, Cairo.Color color, int y)
private static bool IsConstantColumn (ImageSurface surf, Cairo.Color color, Gdk.Rectangle rect, int x)
{
for (int y = rect.Top; y < rect.Bottom; ++y) {
if (!color.Equals (surf.GetPixel (x, y)))
if (!color.Equals (surf.GetColorBgra (x, y).ToCairoColor ()))
return false;
}

Expand All @@ -235,7 +235,7 @@ private void HandlePintaCoreActionsImageAutoCropActivated (object sender, EventA

using (var image = doc.GetFlattenedImage ()) {
Gdk.Rectangle rect = image.GetBounds ();
Cairo.Color border_color = image.GetPixel (0, 0);
Cairo.Color border_color = image.GetColorBgra (0, 0).ToCairoColor ();

// Top down.
for (int y = 0; y < image.Height; ++y) {
Expand Down
4 changes: 2 additions & 2 deletions Pinta.Core/Classes/Document.cs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ public ColorBgra GetComputedPixel (int x, int y)
using (var dst = CairoExtensions.CreateImageSurface (Format.Argb32, 1, 1)) {
using (var g = new Context (dst)) {
foreach (var layer in Layers.GetLayersToPaint ()) {
var color = layer.Surface.GetColorBgraUnchecked (x, y).ToStraightAlpha ().ToCairoColor ();
var color = layer.Surface.GetColorBgra (x, y).ToStraightAlpha ().ToCairoColor ();

g.SetBlendMode (layer.BlendMode);
g.SetSourceColor (color);
Expand All @@ -254,7 +254,7 @@ public ColorBgra GetComputedPixel (int x, int y)
}
}

return dst.GetColorBgraUnchecked (0, 0);
return dst.GetColorBgra (0, 0);
}
}

Expand Down
137 changes: 39 additions & 98 deletions Pinta.Core/Extensions/CairoExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -743,18 +743,6 @@ public static Gdk.Pixbuf ToPixbuf (this Cairo.ImageSurface surfSource)
return new Gdk.Pixbuf (surfSource, 0, 0, surfSource.Width, surfSource.Height);
}

public static Color GetPixel (this Cairo.ImageSurface surf, int x, int y)
{
ColorBgra c = surf.GetReadOnlyData ()[y * surf.Width + x];

return new Color (c.R / 255f, c.G / 255f, c.B / 255f, c.A / 255f);
}

public static ColorBgra GetColorBgraUnchecked (this Cairo.ImageSurface surf, int x, int y)
{
return surf.GetReadOnlyData ()[y * surf.Width + x];
}

public static ColorBgra ToColorBgra (this Cairo.Color color)
{
ColorBgra c = new ColorBgra ();
Expand Down Expand Up @@ -939,71 +927,22 @@ public static bool IsVisible (this ImageSurface surf, int x, int y)
return x >= 0 && x < surf.Width && y >= 0 && y < surf.Height;
}


public static unsafe ColorBgra* GetPointAddressUnchecked (this ImageSurface surf, int x, int y)
{
ColorBgra* dstPtr = (ColorBgra*) surf.DataPtr;

dstPtr += (x) + (y * surf.Width);

return dstPtr;
}

public static unsafe ColorBgra* GetPointAddressUnchecked (this ImageSurface surf, ColorBgra* surfDataPtr, int surfWidth, int x, int y)
{
ColorBgra* dstPtr = surfDataPtr;

dstPtr += (x) + (y * surfWidth);

return dstPtr;
}

// This isn't really an extension method, since it doesn't use
// the passed in argument, but it's nice to have the same calling
// convention as the uncached version. If you can use this one
// over the other, it is much faster in tight loops (like effects).
public static unsafe ColorBgra GetPointUnchecked (this ImageSurface surf, ColorBgra* surfDataPtr, int surfWidth, int x, int y)
{
ColorBgra* dstPtr = surfDataPtr;

dstPtr += (x) + (y * surfWidth);

return *dstPtr;
}

// This isn't really an extension method, since it doesn't use
// the passed in argument, but it's nice to have the same calling
// convention as the uncached version. If you can use this one
// over the other, it is much faster in tight loops (like effects).
public static ref readonly ColorBgra GetPoint (this ImageSurface surf, ReadOnlySpan<ColorBgra> data, int width, int x, int y)
public static ref readonly ColorBgra GetColorBgra (this ImageSurface surf, ReadOnlySpan<ColorBgra> data, int width, int x, int y)
{
return ref data[width * y + x];
}

public static unsafe ColorBgra* GetRowAddressUnchecked (this ImageSurface surf, int y)
{
ColorBgra* dstPtr = (ColorBgra*) surf.DataPtr;

dstPtr += y * surf.Width;

return dstPtr;
}

public static unsafe ColorBgra* GetRowAddressUnchecked (this ImageSurface surf, ColorBgra* surfDataPtr, int surfWidth, int y)
{
ColorBgra* dstPtr = surfDataPtr;

dstPtr += y * surfWidth;

return dstPtr;
}

public static unsafe ColorBgra* GetPointAddress (this ImageSurface surf, int x, int y)
/// <summary>
/// Prefer using the variant which takes the surface data and width, for improved performance
/// if there are repeated calls in a loop.
/// </summary>
public static ref readonly ColorBgra GetColorBgra (this ImageSurface surf, int x, int y)
{
if (x < 0 || x >= surf.Width)
throw new ArgumentOutOfRangeException ("x", "Out of bounds: x=" + x.ToString ());

return surf.GetPointAddressUnchecked (x, y);
return ref surf.GetColorBgra (surf.GetReadOnlyData (), surf.Width, x, y);
}

public static Gdk.Rectangle GetBounds (this ImageSurface surf)
Expand Down Expand Up @@ -1083,10 +1022,10 @@ public static ColorBgra GetBilinearSample (this ImageSurface src, ReadOnlySpan<C
else
sbottom = stop + 1;

ref readonly ColorBgra cul = ref src.GetPoint (src_data, srcWidth, sleft, stop);
ref readonly ColorBgra cur = ref src.GetPoint (src_data, srcWidth, sright, stop);
ref readonly ColorBgra cll = ref src.GetPoint (src_data, srcWidth, sleft, sbottom);
ref readonly ColorBgra clr = ref src.GetPoint (src_data, srcWidth, sright, sbottom);
ref readonly ColorBgra cul = ref src.GetColorBgra (src_data, srcWidth, sleft, stop);
ref readonly ColorBgra cur = ref src.GetColorBgra (src_data, srcWidth, sright, stop);
ref readonly ColorBgra cll = ref src.GetColorBgra (src_data, srcWidth, sleft, sbottom);
ref readonly ColorBgra clr = ref src.GetColorBgra (src_data, srcWidth, sright, sbottom);

return ColorBgra.BlendColors4W16IP (cul, wul, cur, wur, cll, wll, clr, wlr);
}
Expand Down Expand Up @@ -1150,10 +1089,10 @@ public static ColorBgra GetBilinearSampleClamped (this ImageSurface src, ReadOnl
else
sbottom = stop + 1;

ref readonly ColorBgra cul = ref src.GetPoint (src_data, srcWidth, sleft, stop);
ref readonly ColorBgra cur = ref src.GetPoint (src_data, srcWidth, sright, stop);
ref readonly ColorBgra cll = ref src.GetPoint (src_data, srcWidth, sleft, sbottom);
ref readonly ColorBgra clr = ref src.GetPoint (src_data, srcWidth, sright, sbottom);
ref readonly ColorBgra cul = ref src.GetColorBgra (src_data, srcWidth, sleft, stop);
ref readonly ColorBgra cur = ref src.GetColorBgra (src_data, srcWidth, sright, stop);
ref readonly ColorBgra cll = ref src.GetColorBgra (src_data, srcWidth, sleft, sbottom);
ref readonly ColorBgra clr = ref src.GetColorBgra (src_data, srcWidth, sright, sbottom);

return ColorBgra.BlendColors4W16IP (cul, wul, cur, wur, cll, wll, clr, wlr);
}
Expand Down Expand Up @@ -1214,10 +1153,10 @@ public static ColorBgra GetBilinearSampleWrapped (this ImageSurface src, ReadOnl
else
sbottom = stop + 1;

ref readonly ColorBgra cul = ref src.GetPoint (src_data, srcWidth, sleft, stop);
ref readonly ColorBgra cur = ref src.GetPoint (src_data, srcWidth, sright, stop);
ref readonly ColorBgra cll = ref src.GetPoint (src_data, srcWidth, sleft, sbottom);
ref readonly ColorBgra clr = ref src.GetPoint (src_data, srcWidth, sright, sbottom);
ref readonly ColorBgra cul = ref src.GetColorBgra (src_data, srcWidth, sleft, stop);
ref readonly ColorBgra cur = ref src.GetColorBgra (src_data, srcWidth, sright, stop);
ref readonly ColorBgra cll = ref src.GetColorBgra (src_data, srcWidth, sleft, sbottom);
ref readonly ColorBgra clr = ref src.GetColorBgra (src_data, srcWidth, sright, sbottom);

return ColorBgra.BlendColors4W16IP (cul, wul, cur, wur, cll, wll, clr, wlr);
}
Expand Down Expand Up @@ -1657,10 +1596,12 @@ public static Rectangle PointsToRectangle (PointD p1, PointD p2)
}

// Ported from PDN.
public unsafe static void FillStencilFromPoint (ImageSurface surface, BitMask stencil, Point start, int tolerance,
public static void FillStencilFromPoint (ImageSurface surface, BitMask stencil, Point start, int tolerance,
out Rectangle boundingBox, Cairo.Region limitRegion, bool limitToSelection)
{
ColorBgra cmp = surface.GetColorBgraUnchecked (start.X, start.Y);
ReadOnlySpan<ColorBgra> surf_data = surface.GetReadOnlyData ();
int surf_width = surface.Width;
ColorBgra cmp = surface.GetColorBgra (surf_data, surf_width, start.X, start.Y);
int top = int.MaxValue;
int bottom = int.MinValue;
int left = int.MaxValue;
Expand Down Expand Up @@ -1690,36 +1631,37 @@ public unsafe static void FillStencilFromPoint (ImageSurface surface, BitMask st
while (queue.Count > 0) {
Point pt = queue.Dequeue ();

ColorBgra* rowPtr = surface.GetRowAddressUnchecked (pt.Y);
ReadOnlySpan<ColorBgra> row = surf_data.Slice (pt.Y * surf_width, surf_width);
int localLeft = pt.X - 1;
int localRight = pt.X;

while (localLeft >= 0 &&
!stencil.Get (localLeft, pt.Y) &&
ColorBgra.ColorsWithinTolerance (cmp, rowPtr[localLeft], tolerance)) {
ColorBgra.ColorsWithinTolerance (cmp, row[localLeft], tolerance)) {
stencil.Set (localLeft, pt.Y, true);
--localLeft;
}

int surfaceWidth = surface.Width;
while (localRight < surfaceWidth &&
!stencil.Get (localRight, pt.Y) &&
ColorBgra.ColorsWithinTolerance (cmp, rowPtr[localRight], tolerance)) {
ColorBgra.ColorsWithinTolerance (cmp, row[localRight], tolerance)) {
stencil.Set (localRight, pt.Y, true);
++localRight;
}

++localLeft;
--localRight;

Action<int> checkRow = (row) => {
void checkRow (ReadOnlySpan<ColorBgra> surf_data, int row)
{
int sleft = localLeft;
int sright = localLeft;
ColorBgra* otherRowPtr = surface.GetRowAddressUnchecked (row);
ReadOnlySpan<ColorBgra> other_row = surf_data.Slice (row * surf_width, surf_width);

for (int sx = localLeft; sx <= localRight; ++sx) {
if (!stencil.Get (sx, row) &&
ColorBgra.ColorsWithinTolerance (cmp, otherRowPtr[sx], tolerance)) {
ColorBgra.ColorsWithinTolerance (cmp, other_row[sx], tolerance)) {
++sright;
} else {
if (sright - sleft > 0) {
Expand All @@ -1734,14 +1676,14 @@ public unsafe static void FillStencilFromPoint (ImageSurface surface, BitMask st
if (sright - sleft > 0) {
queue.Enqueue (new Point (sleft, row));
}
};
}

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

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

if (localLeft < left) {
Expand All @@ -1768,9 +1710,11 @@ public unsafe static void FillStencilFromPoint (ImageSurface surface, BitMask st
}

// Ported from PDN
public unsafe static void FillStencilByColor (ImageSurface surface, BitMask stencil, ColorBgra cmp, int tolerance,
public static void FillStencilByColor (ImageSurface surface, BitMask stencil, ColorBgra cmp, int tolerance,
out Rectangle boundingBox, Cairo.Region limitRegion, bool limitToSelection)
{
int surf_width = surface.Width;

int top = int.MaxValue;
int bottom = int.MinValue;
int left = int.MaxValue;
Expand All @@ -1795,11 +1739,10 @@ public unsafe static void FillStencilByColor (ImageSurface surface, BitMask sten

Parallel.For (0, surface.Height, y => {
bool foundPixelInRow = false;
ColorBgra* ptr = surface.GetRowAddressUnchecked (y);
ReadOnlySpan<ColorBgra> row = surface.GetReadOnlyData ().Slice (y * surf_width, surf_width);

int surfaceWidth = surface.Width;
for (int x = 0; x < surfaceWidth; ++x) {
if (ColorBgra.ColorsWithinTolerance (cmp, *ptr, tolerance)) {
for (int x = 0; x < surf_width; ++x) {
if (ColorBgra.ColorsWithinTolerance (cmp, row[x], tolerance)) {
stencil.Set (x, y, true);

if (x < left) {
Expand All @@ -1812,8 +1755,6 @@ public unsafe static void FillStencilByColor (ImageSurface surface, BitMask sten

foundPixelInRow = true;
}

++ptr;
}

if (foundPixelInRow) {
Expand Down
2 changes: 1 addition & 1 deletion Pinta.Effects/Effects/EmbossEffect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public override void Render (ImageSurface src, ImageSurface dst, Gdk.Rectangle[]
for (int fy = fyStart; fy < fyEnd; ++fy) {
for (int fx = fxStart; fx < fxEnd; ++fx) {
double weight = weights[fy, fx];
ref readonly ColorBgra c = ref src.GetPoint (src_data, srcWidth, x - 1 + fx, y - 1 + fy);
ref readonly ColorBgra c = ref src.GetColorBgra (src_data, srcWidth, x - 1 + fx, y - 1 + fy);
double intensity = (double) c.GetIntensityByte ();
sum += weight * intensity;
}
Expand Down
2 changes: 1 addition & 1 deletion Pinta.Effects/Effects/FragmentEffect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public override void Render (ImageSurface src, ImageSurface dst, Gdk.Rectangle[]
int v = y - pointOffsetsPtr[i].Y;

if (u >= 0 && u < src_width && v >= 0 && v < src_height) {
samples[sampleCount] = src.GetPoint (src_data, src_width, u, v);
samples[sampleCount] = src.GetColorBgra (src_data, src_width, u, v);
++sampleCount;
}
}
Expand Down
4 changes: 2 additions & 2 deletions Pinta.Effects/Effects/GaussianBlurEffect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public override void Render (ImageSurface src, ImageSurface dest, Gdk.Rectangle[
int srcY = y + wy - r;

if (srcY >= 0 && srcY < src_height) {
ColorBgra c = src.GetPoint (src_data, src_width, srcX, srcY).ToStraightAlpha ();
ColorBgra c = src.GetColorBgra (src_data, src_width, srcX, srcY).ToStraightAlpha ();
int wp = w[wy];

waSums[wx] += wp;
Expand Down Expand Up @@ -194,7 +194,7 @@ public override void Render (ImageSurface src, ImageSurface dest, Gdk.Rectangle[
int srcY = y + wy - r;

if (srcY >= 0 && srcY < src_height) {
ColorBgra c = src.GetPoint (src_data, src_width, srcX, srcY).ToStraightAlpha ();
ColorBgra c = src.GetColorBgra (src_data, src_width, srcX, srcY).ToStraightAlpha ();
int wp = w[wy];

waSums[wx] += wp;
Expand Down
2 changes: 1 addition & 1 deletion Pinta.Effects/Effects/TileEffect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public override void Render (ImageSurface src, ImageSurface dst, Gdk.Rectangle[]
ySample = (ySample + height) % height;
}

ref readonly ColorBgra sample = ref src.GetPoint (src_data, src_width, xSample, ySample);
ref readonly ColorBgra sample = ref src.GetColorBgra (src_data, src_width, xSample, ySample);

b += sample.B;
g += sample.G;
Expand Down
2 changes: 1 addition & 1 deletion Pinta.Effects/Effects/TwistEffect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public override void Render (ImageSurface src, ImageSurface dst, Gdk.Rectangle[]

theta += (t * twist) / 100;

ref readonly ColorBgra sample = ref src.GetPoint (src_data, width,
ref readonly ColorBgra sample = ref src.GetColorBgra (src_data, width,
(int) (hw + (float) (rad * Math.Cos (theta))),
(int) (hh + (float) (rad * Math.Sin (theta))));

Expand Down
2 changes: 1 addition & 1 deletion Pinta.Effects/Effects/ZoomBlurEffect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public override void Render (ImageSurface src, ImageSurface dst, Gdk.Rectangle[]
int v = (int) (fy + fcy + 32768 >> 16);

if (src_bounds.Contains (u, v)) {
ref readonly ColorBgra src_pixel_2 = ref src.GetPoint (src_data, src_width, u, v);
ref readonly ColorBgra src_pixel_2 = ref src.GetColorBgra (src_data, src_width, u, v);

sr += src_pixel_2.R * src_pixel_2.A;
sg += src_pixel_2.G * src_pixel_2.A;
Expand Down
2 changes: 1 addition & 1 deletion Pinta.Tools/Tools/ColorPickerTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ private ColorBgra[] GetPixelsFromPoint (Document document, Point point)
private ColorBgra GetPixel (Document document, int x, int y)
{
if (SampleLayerOnly)
return document.Layers.CurrentUserLayer.Surface.GetColorBgraUnchecked (x, y);
return document.Layers.CurrentUserLayer.Surface.GetColorBgra (x, y);
else
return document.GetComputedPixel (x, y);
}
Expand Down
2 changes: 1 addition & 1 deletion Pinta.Tools/Tools/FloodTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ protected override void OnMouseDown (Document document, ToolMouseEventArgs e)
if (IsContinguousMode)
CairoExtensions.FillStencilFromPoint (surface, stencilBuffer, pos, tol, out boundingBox, currentRegion, LimitToSelection);
else
CairoExtensions.FillStencilByColor (surface, stencilBuffer, surface.GetColorBgraUnchecked (pos.X, pos.Y), tol, out boundingBox, currentRegion, LimitToSelection);
CairoExtensions.FillStencilByColor (surface, stencilBuffer, surface.GetColorBgra (pos.X, pos.Y), tol, out boundingBox, currentRegion, LimitToSelection);

OnFillRegionComputed (document, stencilBuffer);

Expand Down

0 comments on commit 9c3ad88

Please sign in to comment.