Skip to content

Commit

Permalink
Merge branch 'PintaProject:master' into refactoring/remove_namespace_…
Browse files Browse the repository at this point in the history
…warnings
  • Loading branch information
Lehonti authored Dec 24, 2024
2 parents f63966f + e482bf5 commit afff4de
Show file tree
Hide file tree
Showing 16 changed files with 1,555 additions and 407 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Thanks to the following contributors who worked on this release:
- Upgraded the minimum required .NET version to 8.0
- Restored support for add-ins, which had been disabled in Pinta 2.0 due to technical limitations
- Added a preference (in the `View` menu) for switching between a dark or light color scheme
- Added an improved color picker dialog (#570, #761, #1025)
- Added a canvas grid with customizable size, replacing the previous pixel grid (#1028, #1105)
- Added ability to choose tile type (#1051) and edge behavior (#1141) in tile reflection effect
- Added a new "Dithering" effect (#457)
Expand Down
7 changes: 4 additions & 3 deletions Pinta.Core/Classes/ColorBgra.cs
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ public static ColorBgra Blend (ReadOnlySpan<ColorBgra> colors)
/// <returns>A ColorBgra value in premultiplied alpha form</returns>
public readonly ColorBgra ToPremultipliedAlpha () => FromBgra ((byte) (B * A / 255), (byte) (G * A / 255), (byte) (R * A / 255), A);

public static bool ColorsWithinTolerance (ColorBgra a, ColorBgra b, int tolerance)
public static int ColorDifference (ColorBgra a, ColorBgra b)
{
int diffR = a.R - b.R;
int diffG = a.G - b.G;
Expand All @@ -337,10 +337,11 @@ public static bool ColorsWithinTolerance (ColorBgra a, ColorBgra b, int toleranc
int summandA = diffA * diffA;

int sum = summandR + summandG + summandB + summandA;

return sum <= tolerance * tolerance * 4;
return sum;
}

public static bool ColorsWithinTolerance (ColorBgra a, ColorBgra b, int tolerance) => ColorDifference (a, b) <= tolerance * tolerance * 4;

/// <summary>
/// Brings the color channels from premultiplied alpha in straight alpha form.
/// This is required for direct memory manipulation when reading from Cairo surfaces
Expand Down
135 changes: 20 additions & 115 deletions Pinta.Core/Classes/HsvColor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,141 +6,46 @@
/////////////////////////////////////////////////////////////////////////////////

using System;
using Cairo;

namespace Pinta.Core;

/// <summary>
/// Adapted from:
/// Adapted from:
/// "A Primer on Building a Color Picker User Control with GDI+ in Visual Basic .NET or C#"
/// http://www.msdnaa.net/Resources/display.aspx?ResID=2460
/// </summary>
public readonly struct HsvColor
{
public readonly int Hue { get; } // 0-360
public readonly int Saturation { get; } // 0-100
public readonly int Value { get; } // 0-100
public double Hue { get; init; } // 0-360
public double Sat { get; init; } // 0-1
public double Val { get; init; } // 0-1

public static bool operator == (HsvColor lhs, HsvColor rhs)
=> lhs.Hue == rhs.Hue && lhs.Saturation == rhs.Saturation && lhs.Value == rhs.Value;

public static bool operator != (HsvColor lhs, HsvColor rhs)
=> !(lhs == rhs);

public override readonly bool Equals (object? obj)
=> obj is HsvColor hsv && this == hsv;

public override readonly int GetHashCode ()
=> (Hue + (Saturation << 8) + (Value << 16)).GetHashCode ();

public HsvColor (int hue, int saturation, int value)
public HsvColor (double hue, double sat, double val)
{
if (hue < 0 || hue > 360)
throw new ArgumentOutOfRangeException (nameof (hue), "must be in the range [0, 360]");

if (saturation < 0 || saturation > 100)
throw new ArgumentOutOfRangeException (nameof (saturation), "must be in the range [0, 100]");
if (sat < 0 || sat > 1)
throw new ArgumentOutOfRangeException (nameof (sat), "must be in the range [0, 1]");

if (value < 0 || value > 100)
throw new ArgumentOutOfRangeException (nameof (value), "must be in the range [0, 100]");
if (val < 0 || val > 1)
throw new ArgumentOutOfRangeException (nameof (val), "must be in the range [0, 1]");

Hue = hue;
Saturation = saturation;
Value = value;
Sat = sat;
Val = val;
}

// public static HsvColor FromColor(Color color)
// {
// RgbColor rgb = new RgbColor(color.R, color.G, color.B);
// return rgb.ToHsv();
// }
//
// public Color ToColor()
// {
// RgbColor rgb = ToRgb();
// return Color.FromArgb(rgb.Red, rgb.Green, rgb.Blue);
// }

public readonly RgbColor ToRgb ()
{
// HsvColor contains values scaled as in the color wheel.
// Scale Hue to be between 0 and 360. Saturation
// and value scale to be between 0 and 1.
double h = (double) Hue % 360;
double s = (double) Saturation / 100;
double v = (double) Value / 100;

double r = 0;
double g = 0;
double b = 0;

if (s == 0) {
// If s is 0, all colors are the same.
// This is some flavor of gray.
r = v;
g = v;
b = v;
} else {
// The color wheel consists of 6 sectors.
// Figure out which sector you're in.
double sectorPos = h / 60;
int sectorNumber = (int) (Math.Floor (sectorPos));

// get the fractional part of the sector.
// That is, how many degrees into the sector
// are you?
double fractionalSector = sectorPos - sectorNumber;
public static HsvColor FromColor (Color c) => c.ToHsv ();
public Color ToColor (double alpha = 1) => Color.FromHsv (this, alpha);
public static HsvColor FromBgra (ColorBgra c) => c.ToCairoColor ().ToHsv ();
public ColorBgra ToBgra () => this.ToColor ().ToColorBgra ();

// Calculate values for the three axes
// of the color.
double p = v * (1 - s);
double q = v * (1 - (s * fractionalSector));
double t = v * (1 - (s * (1 - fractionalSector)));

// Assign the fractional colors to r, g, and b
// based on the sector the angle is in.
switch (sectorNumber) {
case 0:
r = v;
g = t;
b = p;
break;

case 1:
r = q;
g = v;
b = p;
break;

case 2:
r = p;
g = v;
b = t;
break;

case 3:
r = p;
g = q;
b = v;
break;

case 4:
r = t;
g = p;
b = v;
break;

case 5:
r = v;
g = p;
b = q;
break;
}
}
// return an RgbColor structure, with values scaled
// to be between 0 and 255.
return new RgbColor ((int) (r * 255), (int) (g * 255), (int) (b * 255));
}

public override readonly string ToString ()
=> $"({Hue}, {Saturation}, {Value})";
=> $"({Hue:F2}, {Sat:F2}, {Val:F2})";

public override int GetHashCode ()
=> ((int) Hue + ((int) Sat << 8) + ((int) Val << 16)).GetHashCode ();
}
115 changes: 0 additions & 115 deletions Pinta.Core/Classes/RgbColor.cs

This file was deleted.

11 changes: 4 additions & 7 deletions Pinta.Core/Effects/UnaryPixelOps.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public SetChannel (int channel, byte setValue)
/// <summary>
/// Specialization of SetChannel that sets the alpha channel.
/// </summary>
/// <remarks>This class depends on the system being litte-endian with the alpha channel
/// <remarks>This class depends on the system being litte-endian with the alpha channel
/// occupying the 8 most-significant-bits of a ColorBgra instance.
/// By the way, we use addition instead of bitwise-OR because an addition can be
/// perform very fast (0.5 cycles) on a Pentium 4.</remarks>
Expand Down Expand Up @@ -669,19 +669,16 @@ public override ColorBgra Apply (in ColorBgra src_color)
color.G = Utility.ClampToByte ((intensity * 1024 + (color.G - intensity) * sat_factor) >> 10);
color.B = Utility.ClampToByte ((intensity * 1024 + (color.B - intensity) * sat_factor) >> 10);

HsvColor hsvColor = (new RgbColor (color.R, color.G, color.B)).ToHsv ();
int newHue = hsvColor.Hue;
HsvColor hsvColor = HsvColor.FromBgra (color);
int newHue = (int) hsvColor.Hue;

newHue += hue_delta;

while (newHue < 0) { newHue += 360; }

while (newHue > 360) { newHue -= 360; }

hsvColor = new HsvColor (newHue, hsvColor.Saturation, hsvColor.Value);

RgbColor rgbColor = hsvColor.ToRgb ();
ColorBgra newColor = ColorBgra.FromBgr ((byte) rgbColor.Blue, (byte) rgbColor.Green, (byte) rgbColor.Red);
ColorBgra newColor = (hsvColor with { Hue = newHue }).ToBgra ();
newColor = blend_op.Apply (newColor);
newColor.A = color.A;

Expand Down
Loading

0 comments on commit afff4de

Please sign in to comment.