diff --git a/src/ImageSharp/ColorSpaces/CieLch.cs b/src/ImageSharp/ColorSpaces/CieLch.cs
index 1b9cf9c2b..57ed5f48d 100644
--- a/src/ImageSharp/ColorSpaces/CieLch.cs
+++ b/src/ImageSharp/ColorSpaces/CieLch.cs
@@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// Represents a that has L, C, H values set to zero.
///
- public static readonly CieLch Empty = default(CieLch);
+ public static readonly CieLch Empty = default;
///
/// The backing vector for SIMD support.
diff --git a/src/ImageSharp/ColorSpaces/CieLchuv.cs b/src/ImageSharp/ColorSpaces/CieLchuv.cs
index 7ec27806d..a378aae86 100644
--- a/src/ImageSharp/ColorSpaces/CieLchuv.cs
+++ b/src/ImageSharp/ColorSpaces/CieLchuv.cs
@@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// Represents a that has L, C, H values set to zero.
///
- public static readonly CieLchuv Empty = default(CieLchuv);
+ public static readonly CieLchuv Empty = default;
///
/// The backing vector for SIMD support.
diff --git a/src/ImageSharp/ColorSpaces/CieLuv.cs b/src/ImageSharp/ColorSpaces/CieLuv.cs
index e46b736a7..f93e1fd46 100644
--- a/src/ImageSharp/ColorSpaces/CieLuv.cs
+++ b/src/ImageSharp/ColorSpaces/CieLuv.cs
@@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// Represents a that has L, U, and V values set to zero.
///
- public static readonly CieLuv Empty = default(CieLuv);
+ public static readonly CieLuv Empty = default;
///
/// The backing vector for SIMD support.
diff --git a/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs b/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs
index d54de43bb..6716b1bad 100644
--- a/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs
+++ b/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs
@@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// Represents a that has X, Y values set to zero.
///
- public static readonly CieXyChromaticityCoordinates Empty = default(CieXyChromaticityCoordinates);
+ public static readonly CieXyChromaticityCoordinates Empty = default;
///
/// The backing vector for SIMD support.
diff --git a/src/ImageSharp/ColorSpaces/CieXyy.cs b/src/ImageSharp/ColorSpaces/CieXyy.cs
index 9633f83ad..71ad4701a 100644
--- a/src/ImageSharp/ColorSpaces/CieXyy.cs
+++ b/src/ImageSharp/ColorSpaces/CieXyy.cs
@@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// Represents a that has X, Y, and Y values set to zero.
///
- public static readonly CieXyy Empty = default(CieXyy);
+ public static readonly CieXyy Empty = default;
///
/// The backing vector for SIMD support.
diff --git a/src/ImageSharp/ColorSpaces/CieXyz.cs b/src/ImageSharp/ColorSpaces/CieXyz.cs
index eedfed079..79676bb08 100644
--- a/src/ImageSharp/ColorSpaces/CieXyz.cs
+++ b/src/ImageSharp/ColorSpaces/CieXyz.cs
@@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// Represents a that has X, Y, and Z values set to zero.
///
- public static readonly CieXyz Empty = default(CieXyz);
+ public static readonly CieXyz Empty = default;
///
/// The backing vector for SIMD support.
diff --git a/src/ImageSharp/ColorSpaces/Cmyk.cs b/src/ImageSharp/ColorSpaces/Cmyk.cs
index 2e44ea920..989d512bb 100644
--- a/src/ImageSharp/ColorSpaces/Cmyk.cs
+++ b/src/ImageSharp/ColorSpaces/Cmyk.cs
@@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// Represents a that has C, M, Y, and K values set to zero.
///
- public static readonly Cmyk Empty = default(Cmyk);
+ public static readonly Cmyk Empty = default;
///
/// The backing vector for SIMD support.
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs
index 174da5ad1..8b7c64100 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs
@@ -67,9 +67,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLab ToCieLab(CieLchuv color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLab(xyzColor);
}
@@ -101,9 +100,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLab ToCieLab(CieLuv color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLab(xyzColor);
}
@@ -135,9 +133,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLab ToCieLab(CieXyy color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLab(xyzColor);
}
@@ -243,9 +240,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLab ToCieLab(Hsl color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLab(xyzColor);
}
@@ -311,9 +307,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLab ToCieLab(HunterLab color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLab(xyzColor);
}
@@ -345,9 +340,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLab ToCieLab(Lms color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLab(xyzColor);
}
@@ -379,9 +373,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLab ToCieLab(LinearRgb color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLab(xyzColor);
}
@@ -413,9 +406,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLab ToCieLab(Rgb color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLab(xyzColor);
}
@@ -447,9 +439,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLab ToCieLab(YCbCr color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLab(xyzColor);
}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs
index 8ce8674a6..5e75c29aa 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs
@@ -25,8 +25,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLch ToCieLch(CieLab color)
{
- Guard.NotNull(color, nameof(color));
-
// Adaptation
CieLab adapted = this.IsChromaticAdaptationPerformed ? this.Adapt(color) : color;
@@ -62,9 +60,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLch ToCieLch(CieLchuv color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLch(xyzColor);
}
@@ -96,9 +93,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLch ToCieLch(CieLuv color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLch(xyzColor);
}
@@ -130,9 +126,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLch ToCieLch(CieXyy color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLch(xyzColor);
}
@@ -164,9 +159,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLch ToCieLch(CieXyz color)
{
- Guard.NotNull(color, nameof(color));
-
var labColor = this.ToCieLab(color);
+
return this.ToCieLch(labColor);
}
@@ -232,9 +226,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLch ToCieLch(Hsl color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLch(xyzColor);
}
@@ -266,9 +259,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLch ToCieLch(Hsv color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLch(xyzColor);
}
@@ -300,9 +292,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLch ToCieLch(HunterLab color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLch(xyzColor);
}
@@ -334,9 +325,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLch ToCieLch(LinearRgb color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLch(xyzColor);
}
@@ -368,9 +358,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLch ToCieLch(Lms color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLch(xyzColor);
}
@@ -402,9 +391,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLch ToCieLch(Rgb color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLch(xyzColor);
}
@@ -436,9 +424,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLch ToCieLch(YCbCr color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLch(xyzColor);
}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs
index e4feddc7e..8e47b5581 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs
@@ -25,9 +25,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLchuv ToCieLchuv(CieLab color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLchuv(xyzColor);
}
@@ -59,9 +58,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLchuv ToCieLchuv(CieLch color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLchuv(xyzColor);
}
@@ -93,8 +91,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLchuv ToCieLchuv(CieLuv color)
{
- Guard.NotNull(color, nameof(color));
-
// Adaptation
CieLuv adapted = this.IsChromaticAdaptationPerformed ? this.Adapt(color) : color;
@@ -130,9 +126,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLchuv ToCieLchuv(CieXyy color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLchuv(xyzColor);
}
@@ -164,9 +159,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLchuv ToCieLchuv(CieXyz color)
{
- Guard.NotNull(color, nameof(color));
-
var labColor = this.ToCieLab(color);
+
return this.ToCieLchuv(labColor);
}
@@ -198,9 +192,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLchuv ToCieLchuv(Cmyk color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLchuv(xyzColor);
}
@@ -232,9 +225,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLchuv ToCieLchuv(Hsl color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLchuv(xyzColor);
}
@@ -266,9 +258,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLchuv ToCieLchuv(Hsv color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLchuv(xyzColor);
}
@@ -300,9 +291,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLchuv ToCieLchuv(HunterLab color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLchuv(xyzColor);
}
@@ -334,9 +324,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLchuv ToCieLchuv(LinearRgb color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLchuv(xyzColor);
}
@@ -368,9 +357,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLchuv ToCieLchuv(Lms color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLchuv(xyzColor);
}
@@ -402,9 +390,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLchuv ToCieLchuv(Rgb color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
+
return this.ToCieLchuv(xyzColor);
}
@@ -436,9 +423,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLchuv ToCieLchuv(YCbCr color)
{
- Guard.NotNull(color, nameof(color));
+ CieXyz xyzColor = this.ToCieXyz(color);
- var xyzColor = this.ToCieXyz(color);
return this.ToCieLchuv(xyzColor);
}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs
index f4b52a49a..b90b01779 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs
@@ -23,8 +23,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLuv ToCieLuv(CieLab color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
}
@@ -57,8 +55,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLuv ToCieLuv(CieLch color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
}
@@ -91,8 +87,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLuv ToCieLuv(CieLchuv color)
{
- Guard.NotNull(color, nameof(color));
-
// Conversion (perserving white point)
CieLuv unadapted = CieLchuvToCieLuvConverter.Convert(color);
@@ -133,8 +127,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLuv ToCieLuv(CieXyy color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
}
@@ -167,8 +159,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLuv ToCieLuv(CieXyz color)
{
- Guard.NotNull(color, nameof(color));
-
// Adaptation
CieXyz adapted = !this.WhitePoint.Equals(this.TargetLabWhitePoint) && this.IsChromaticAdaptationPerformed
? this.ChromaticAdaptation.Transform(color, this.WhitePoint, this.TargetLabWhitePoint)
@@ -207,8 +197,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLuv ToCieLuv(Cmyk color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
}
@@ -241,8 +229,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLuv ToCieLuv(Hsl color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
}
@@ -275,8 +261,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLuv ToCieLuv(Hsv color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
}
@@ -309,8 +293,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLuv ToCieLuv(HunterLab color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
}
@@ -343,8 +325,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLuv ToCieLuv(Lms color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
}
@@ -377,8 +357,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLuv ToCieLuv(LinearRgb color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
}
@@ -411,8 +389,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLuv ToCieLuv(Rgb color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
}
@@ -445,8 +421,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public CieLuv ToCieLuv(YCbCr color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Cmyk.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Cmyk.cs
index 8cd4a13a7..11cc3f11b 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Cmyk.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Cmyk.cs
@@ -19,8 +19,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Cmyk ToCmyk(CieLab color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToCmyk(xyzColor);
@@ -33,8 +31,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Cmyk ToCmyk(CieLch color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToCmyk(xyzColor);
@@ -47,8 +43,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Cmyk ToCmyk(CieLchuv color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToCmyk(xyzColor);
@@ -61,8 +55,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Cmyk ToCmyk(CieLuv color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToCmyk(xyzColor);
@@ -75,8 +67,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Cmyk ToCmyk(CieXyy color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToCmyk(xyzColor);
@@ -89,8 +79,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Cmyk ToCmyk(CieXyz color)
{
- Guard.NotNull(color, nameof(color));
-
var rgb = this.ToRgb(color);
return CmykAndRgbConverter.Convert(rgb);
@@ -103,8 +91,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Cmyk ToCmyk(Hsl color)
{
- Guard.NotNull(color, nameof(color));
-
var rgb = this.ToRgb(color);
return CmykAndRgbConverter.Convert(rgb);
@@ -117,8 +103,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Cmyk ToCmyk(Hsv color)
{
- Guard.NotNull(color, nameof(color));
-
var rgb = this.ToRgb(color);
return CmykAndRgbConverter.Convert(rgb);
@@ -131,8 +115,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Cmyk ToCmyk(HunterLab color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToCmyk(xyzColor);
@@ -145,8 +127,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Cmyk ToCmyk(LinearRgb color)
{
- Guard.NotNull(color, nameof(color));
-
var rgb = this.ToRgb(color);
return CmykAndRgbConverter.Convert(rgb);
@@ -159,8 +139,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Cmyk ToCmyk(Lms color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToCmyk(xyzColor);
@@ -173,8 +151,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Cmyk ToCmyk(Rgb color)
{
- Guard.NotNull(color, nameof(color));
-
return CmykAndRgbConverter.Convert(color);
}
@@ -185,8 +161,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Cmyk ToCmyk(YCbCr color)
{
- Guard.NotNull(color, nameof(color));
-
var rgb = this.ToRgb(color);
return CmykAndRgbConverter.Convert(rgb);
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsl.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsl.cs
index 7099d98e4..7464a9f1a 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsl.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsl.cs
@@ -19,8 +19,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Hsl ToHsl(CieLab color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToHsl(xyzColor);
@@ -33,8 +31,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Hsl ToHsl(CieLch color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToHsl(xyzColor);
@@ -47,8 +43,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Hsl ToHsl(CieLchuv color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToHsl(xyzColor);
@@ -61,8 +55,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Hsl ToHsl(CieLuv color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToHsl(xyzColor);
@@ -75,8 +67,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Hsl ToHsl(CieXyy color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToHsl(xyzColor);
@@ -89,8 +79,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Hsl ToHsl(CieXyz color)
{
- Guard.NotNull(color, nameof(color));
-
var rgb = this.ToRgb(color);
return HslAndRgbConverter.Convert(rgb);
@@ -103,8 +91,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Hsl ToHsl(Cmyk color)
{
- Guard.NotNull(color, nameof(color));
-
var rgb = this.ToRgb(color);
return HslAndRgbConverter.Convert(rgb);
@@ -117,8 +103,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Hsl ToHsl(Hsv color)
{
- Guard.NotNull(color, nameof(color));
-
var rgb = this.ToRgb(color);
return HslAndRgbConverter.Convert(rgb);
@@ -131,8 +115,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Hsl ToHsl(HunterLab color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToHsl(xyzColor);
@@ -145,8 +127,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Hsl ToHsl(LinearRgb color)
{
- Guard.NotNull(color, nameof(color));
-
var rgb = this.ToRgb(color);
return HslAndRgbConverter.Convert(rgb);
@@ -159,8 +139,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Hsl ToHsl(Lms color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToHsl(xyzColor);
@@ -173,8 +151,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Hsl ToHsl(Rgb color)
{
- Guard.NotNull(color, nameof(color));
-
return HslAndRgbConverter.Convert(color);
}
@@ -185,8 +161,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Hsl ToHsl(YCbCr color)
{
- Guard.NotNull(color, nameof(color));
-
var rgb = this.ToRgb(color);
return HslAndRgbConverter.Convert(rgb);
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.HunterLab.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.HunterLab.cs
index 676139052..167565d3d 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.HunterLab.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.HunterLab.cs
@@ -17,8 +17,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public HunterLab ToHunterLab(CieLab color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToHunterLab(xyzColor);
}
@@ -30,8 +28,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public HunterLab ToHunterLab(CieLch color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToHunterLab(xyzColor);
}
@@ -43,8 +39,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public HunterLab ToHunterLab(CieLchuv color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToHunterLab(xyzColor);
}
@@ -56,8 +50,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public HunterLab ToHunterLab(CieLuv color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToHunterLab(xyzColor);
}
@@ -69,8 +61,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public HunterLab ToHunterLab(CieXyy color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToHunterLab(xyzColor);
}
@@ -82,8 +72,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public HunterLab ToHunterLab(CieXyz color)
{
- Guard.NotNull(color, nameof(color));
-
// Adaptation
CieXyz adapted = !this.WhitePoint.Equals(this.TargetHunterLabWhitePoint) && this.IsChromaticAdaptationPerformed
? this.ChromaticAdaptation.Transform(color, this.WhitePoint, this.TargetHunterLabWhitePoint)
@@ -100,8 +88,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public HunterLab ToHunterLab(Cmyk color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToHunterLab(xyzColor);
}
@@ -113,8 +99,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public HunterLab ToHunterLab(Hsl color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToHunterLab(xyzColor);
}
@@ -126,8 +110,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public HunterLab ToHunterLab(Hsv color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToHunterLab(xyzColor);
}
@@ -139,8 +121,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public HunterLab ToHunterLab(LinearRgb color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToHunterLab(xyzColor);
}
@@ -152,8 +132,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public HunterLab ToHunterLab(Lms color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToHunterLab(xyzColor);
}
@@ -165,8 +143,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public HunterLab ToHunterLab(Rgb color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToHunterLab(xyzColor);
}
@@ -178,8 +154,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public HunterLab ToHunterLab(YCbCr color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToHunterLab(xyzColor);
}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs
index 6258e6e18..ed386db2d 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs
@@ -21,8 +21,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public LinearRgb ToLinearRgb(CieLab color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToLinearRgb(xyzColor);
}
@@ -34,8 +32,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public LinearRgb ToLinearRgb(CieLch color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToLinearRgb(xyzColor);
}
@@ -47,8 +43,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public LinearRgb ToLinearRgb(CieLchuv color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToLinearRgb(xyzColor);
}
@@ -60,8 +54,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public LinearRgb ToLinearRgb(CieLuv color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToLinearRgb(xyzColor);
}
@@ -73,8 +65,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public LinearRgb ToLinearRgb(CieXyy color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToLinearRgb(xyzColor);
}
@@ -86,8 +76,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public LinearRgb ToLinearRgb(CieXyz color)
{
- Guard.NotNull(color, nameof(color));
-
// Adaptation
CieXyz adapted = this.TargetRgbWorkingSpace.WhitePoint.Equals(this.WhitePoint) || !this.IsChromaticAdaptationPerformed
? color
@@ -105,8 +93,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public LinearRgb ToLinearRgb(Cmyk color)
{
- Guard.NotNull(color, nameof(color));
-
var rgb = this.ToRgb(color);
return this.ToLinearRgb(rgb);
}
@@ -118,8 +104,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public LinearRgb ToLinearRgb(Hsl color)
{
- Guard.NotNull(color, nameof(color));
-
var rgb = this.ToRgb(color);
return this.ToLinearRgb(rgb);
}
@@ -144,8 +128,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public LinearRgb ToLinearRgb(HunterLab color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToLinearRgb(xyzColor);
}
@@ -157,8 +139,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public LinearRgb ToLinearRgb(Lms color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToLinearRgb(xyzColor);
}
@@ -170,8 +150,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public LinearRgb ToLinearRgb(Rgb color)
{
- Guard.NotNull(color, nameof(color));
-
// Conversion
return RgbToLinearRgbConverter.Convert(color);
}
@@ -183,8 +161,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public LinearRgb ToLinearRgb(YCbCr color)
{
- Guard.NotNull(color, nameof(color));
-
var rgb = this.ToRgb(color);
return this.ToLinearRgb(rgb);
}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Lms.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Lms.cs
index 872b79296..23b8592f2 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Lms.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Lms.cs
@@ -15,8 +15,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Lms ToLms(CieLab color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToLms(xyzColor);
}
@@ -28,8 +26,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Lms ToLms(CieLch color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToLms(xyzColor);
}
@@ -41,8 +37,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Lms ToLms(CieLchuv color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToLms(xyzColor);
}
@@ -54,8 +48,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Lms ToLms(CieLuv color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToLms(xyzColor);
}
@@ -67,8 +59,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Lms ToLms(CieXyy color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToLms(xyzColor);
}
@@ -80,9 +70,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Lms ToLms(CieXyz color)
{
- Guard.NotNull(color, nameof(color));
-
- // Conversion
return this.cachedCieXyzAndLmsConverter.Convert(color);
}
@@ -93,8 +80,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Lms ToLms(Cmyk color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToLms(xyzColor);
}
@@ -106,8 +91,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Lms ToLms(Hsl color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToLms(xyzColor);
}
@@ -119,8 +102,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Lms ToLms(Hsv color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToLms(xyzColor);
}
@@ -132,8 +113,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Lms ToLms(HunterLab color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToLms(xyzColor);
}
@@ -145,8 +124,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Lms ToLms(LinearRgb color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToLms(xyzColor);
}
@@ -158,8 +135,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Lms ToLms(Rgb color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToLms(xyzColor);
}
@@ -171,8 +146,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Lms ToLms(YCbCr color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToLms(xyzColor);
}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs
index fa8750d34..ef78c1ec2 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs
@@ -19,8 +19,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Rgb ToRgb(CieLab color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToRgb(xyzColor);
}
@@ -32,8 +30,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Rgb ToRgb(CieLch color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToRgb(xyzColor);
}
@@ -45,8 +41,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Rgb ToRgb(CieLchuv color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToRgb(xyzColor);
}
@@ -58,8 +52,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Rgb ToRgb(CieLuv color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToRgb(xyzColor);
}
@@ -71,8 +63,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Rgb ToRgb(CieXyy color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToRgb(xyzColor);
}
@@ -84,8 +74,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Rgb ToRgb(CieXyz color)
{
- Guard.NotNull(color, nameof(color));
-
// Conversion
var linear = this.ToLinearRgb(color);
@@ -100,8 +88,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Rgb ToRgb(Cmyk color)
{
- Guard.NotNull(color, nameof(color));
-
// Conversion
return CmykAndRgbConverter.Convert(color);
}
@@ -113,8 +99,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Rgb ToRgb(Hsv color)
{
- Guard.NotNull(color, nameof(color));
-
// Conversion
return HsvAndRgbConverter.Convert(color);
}
@@ -139,8 +123,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Rgb ToRgb(HunterLab color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToRgb(xyzColor);
}
@@ -152,8 +134,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Rgb ToRgb(LinearRgb color)
{
- Guard.NotNull(color, nameof(color));
-
// Conversion
return LinearRgbToRgbConverter.Convert(color);
}
@@ -165,8 +145,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Rgb ToRgb(Lms color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToRgb(xyzColor);
}
@@ -178,8 +156,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public Rgb ToRgb(YCbCr color)
{
- Guard.NotNull(color, nameof(color));
-
// Conversion
Rgb rgb = YCbCrAndRgbConverter.Convert(color);
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.YCbCr.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.YCbCr.cs
index 67b4472ab..d97c8e4bb 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.YCbCr.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.YCbCr.cs
@@ -1,7 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using SixLabors.ImageSharp.ColorSpaces;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
@@ -20,8 +19,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public YCbCr ToYCbCr(CieLab color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToYCbCr(xyzColor);
@@ -34,8 +31,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public YCbCr ToYCbCr(CieLch color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToYCbCr(xyzColor);
@@ -48,8 +43,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public YCbCr ToYCbCr(CieLchuv color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToYCbCr(xyzColor);
@@ -62,8 +55,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public YCbCr ToYCbCr(CieLuv color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToYCbCr(xyzColor);
@@ -76,8 +67,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public YCbCr ToYCbCr(CieXyy color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToYCbCr(xyzColor);
@@ -90,8 +79,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public YCbCr ToYCbCr(CieXyz color)
{
- Guard.NotNull(color, nameof(color));
-
var rgb = this.ToRgb(color);
return YCbCrAndRgbConverter.Convert(rgb);
@@ -104,8 +91,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public YCbCr ToYCbCr(Cmyk color)
{
- Guard.NotNull(color, nameof(color));
-
var rgb = this.ToRgb(color);
return YCbCrAndRgbConverter.Convert(rgb);
@@ -118,8 +103,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public YCbCr ToYCbCr(Hsl color)
{
- Guard.NotNull(color, nameof(color));
-
var rgb = this.ToRgb(color);
return YCbCrAndRgbConverter.Convert(rgb);
@@ -132,8 +115,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public YCbCr ToYCbCr(Hsv color)
{
- Guard.NotNull(color, nameof(color));
-
var rgb = this.ToRgb(color);
return YCbCrAndRgbConverter.Convert(rgb);
@@ -146,8 +127,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public YCbCr ToYCbCr(HunterLab color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToYCbCr(xyzColor);
@@ -160,8 +139,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public YCbCr ToYCbCr(LinearRgb color)
{
- Guard.NotNull(color, nameof(color));
-
var rgb = this.ToRgb(color);
return YCbCrAndRgbConverter.Convert(rgb);
@@ -174,8 +151,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public YCbCr ToYCbCr(Lms color)
{
- Guard.NotNull(color, nameof(color));
-
var xyzColor = this.ToCieXyz(color);
return this.ToYCbCr(xyzColor);
@@ -188,8 +163,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// The
public YCbCr ToYCbCr(Rgb color)
{
- Guard.NotNull(color, nameof(color));
-
return YCbCrAndRgbConverter.Convert(color);
}
}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyzAndHunterLabConverterBase.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyzAndHunterLabConverterBase.cs
index cc2068ffa..77929bbf2 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyzAndHunterLabConverterBase.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyzAndHunterLabConverterBase.cs
@@ -18,8 +18,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float ComputeKa(CieXyz whitePoint)
{
- DebugGuard.NotNull(whitePoint, nameof(whitePoint));
-
if (whitePoint.Equals(Illuminants.C))
{
return 175F;
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyzAndLmsConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyzAndLmsConverter.cs
index e0d22a631..8754c0b8b 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyzAndLmsConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyzAndLmsConverter.cs
@@ -63,9 +63,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Lms Convert(CieXyz input)
{
- DebugGuard.NotNull(input, nameof(input));
-
var vector = Vector3.Transform(input.Vector, this.transformationMatrix);
+
return new Lms(vector);
}
@@ -73,9 +72,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public CieXyz Convert(Lms input)
{
- DebugGuard.NotNull(input, nameof(input));
-
var vector = Vector3.Transform(input.Vector, this.inverseTransformationMatrix);
+
return new CieXyz(vector);
}
}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CmykAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CmykAndRgbConverter.cs
index f674d9444..506fdffa3 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CmykAndRgbConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CmykAndRgbConverter.cs
@@ -4,7 +4,6 @@
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
-using SixLabors.ImageSharp.ColorSpaces;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
{
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/HsvAndRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/HsvAndRgbConverter.cs
index 953795a52..a6a6317ec 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/HsvAndRgbConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/HsvAndRgbConverter.cs
@@ -3,7 +3,6 @@
using System;
using System.Runtime.CompilerServices;
-using SixLabors.ImageSharp.ColorSpaces;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
{
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLabToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLabToCieXyzConverter.cs
index 9eeffd309..d40b11310 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLabToCieXyzConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLabToCieXyzConverter.cs
@@ -15,8 +15,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public CieXyz Convert(HunterLab input)
{
- DebugGuard.NotNull(input, nameof(input));
-
// Conversion algorithm described here: http://en.wikipedia.org/wiki/Lab_color_space#Hunter_Lab
float l = input.L, a = input.A, b = input.B;
float xn = input.WhitePoint.X, yn = input.WhitePoint.Y, zn = input.WhitePoint.Z;
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/LCompanding.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/LCompanding.cs
index cb002dd9a..bded652b4 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/LCompanding.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/LCompanding.cs
@@ -32,4 +32,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
: MathF.Pow(1.16F * channel, 0.3333333F) - 0.16F;
}
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/RgbToLinearRgbConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/RgbToLinearRgbConverter.cs
index 3bc906ced..f8a7824fa 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/RgbToLinearRgbConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/RgbToLinearRgbConverter.cs
@@ -13,8 +13,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
///
public LinearRgb Convert(Rgb input)
{
- Guard.NotNull(input, nameof(input));
-
Vector3 vector = input.Vector;
vector.X = input.WorkingSpace.Companding.Expand(vector.X);
vector.Y = input.WorkingSpace.Companding.Expand(vector.Y);
diff --git a/src/ImageSharp/ColorSpaces/Conversion/VonKriesChromaticAdaptation.cs b/src/ImageSharp/ColorSpaces/Conversion/VonKriesChromaticAdaptation.cs
index 20f75f1ae..162411c69 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/VonKriesChromaticAdaptation.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/VonKriesChromaticAdaptation.cs
@@ -49,10 +49,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
///
public CieXyz Transform(CieXyz sourceColor, CieXyz sourceWhitePoint, CieXyz targetWhitePoint)
{
- Guard.NotNull(sourceColor, nameof(sourceColor));
- Guard.NotNull(sourceWhitePoint, nameof(sourceWhitePoint));
- Guard.NotNull(targetWhitePoint, nameof(targetWhitePoint));
-
if (sourceWhitePoint.Equals(targetWhitePoint))
{
return sourceColor;
diff --git a/src/ImageSharp/ColorSpaces/Hsl.cs b/src/ImageSharp/ColorSpaces/Hsl.cs
index 3b2ceae27..88b14fa97 100644
--- a/src/ImageSharp/ColorSpaces/Hsl.cs
+++ b/src/ImageSharp/ColorSpaces/Hsl.cs
@@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// Represents a that has H, S, and L values set to zero.
///
- public static readonly Hsl Empty = default(Hsl);
+ public static readonly Hsl Empty = default;
///
/// Max range used for clamping
diff --git a/src/ImageSharp/ColorSpaces/Hsv.cs b/src/ImageSharp/ColorSpaces/Hsv.cs
index f646eb29d..1f6c8d5eb 100644
--- a/src/ImageSharp/ColorSpaces/Hsv.cs
+++ b/src/ImageSharp/ColorSpaces/Hsv.cs
@@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// Represents a that has H, S, and V values set to zero.
///
- public static readonly Hsv Empty = default(Hsv);
+ public static readonly Hsv Empty = default;
///
/// Max range used for clamping
diff --git a/src/ImageSharp/ColorSpaces/HunterLab.cs b/src/ImageSharp/ColorSpaces/HunterLab.cs
index 4ace27def..4395d9d7c 100644
--- a/src/ImageSharp/ColorSpaces/HunterLab.cs
+++ b/src/ImageSharp/ColorSpaces/HunterLab.cs
@@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// Represents a that has L, A, B values set to zero.
///
- public static readonly HunterLab Empty = default(HunterLab);
+ public static readonly HunterLab Empty = default;
///
/// The backing vector for SIMD support.
diff --git a/src/ImageSharp/ColorSpaces/LinearRgb.cs b/src/ImageSharp/ColorSpaces/LinearRgb.cs
index f2dc297a0..c721347be 100644
--- a/src/ImageSharp/ColorSpaces/LinearRgb.cs
+++ b/src/ImageSharp/ColorSpaces/LinearRgb.cs
@@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// Represents a that has R, G, and B values set to zero.
///
- public static readonly LinearRgb Empty = default(LinearRgb);
+ public static readonly LinearRgb Empty = default;
///
/// The default LinearRgb working space
diff --git a/src/ImageSharp/ColorSpaces/Lms.cs b/src/ImageSharp/ColorSpaces/Lms.cs
index 09c20269a..e46249569 100644
--- a/src/ImageSharp/ColorSpaces/Lms.cs
+++ b/src/ImageSharp/ColorSpaces/Lms.cs
@@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// Represents a that has L, M, and S values set to zero.
///
- public static readonly Lms Empty = default(Lms);
+ public static readonly Lms Empty = default;
///
/// The backing vector for SIMD support.
diff --git a/src/ImageSharp/ColorSpaces/Rgb.cs b/src/ImageSharp/ColorSpaces/Rgb.cs
index 128239467..8cdf54ace 100644
--- a/src/ImageSharp/ColorSpaces/Rgb.cs
+++ b/src/ImageSharp/ColorSpaces/Rgb.cs
@@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// Represents a that has R, G, and B values set to zero.
///
- public static readonly Rgb Empty = default(Rgb);
+ public static readonly Rgb Empty = default;
///
/// The default rgb working space
diff --git a/src/ImageSharp/ColorSpaces/YCbCr.cs b/src/ImageSharp/ColorSpaces/YCbCr.cs
index a6e27de94..2c3feffa9 100644
--- a/src/ImageSharp/ColorSpaces/YCbCr.cs
+++ b/src/ImageSharp/ColorSpaces/YCbCr.cs
@@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// Represents a that has Y, Cb, and Cr values set to zero.
///
- public static readonly YCbCr Empty = default(YCbCr);
+ public static readonly YCbCr Empty = default;
///
/// Vector which is used in clamping to the max value
diff --git a/src/ImageSharp/Common/Exceptions/ImageFormatException.cs b/src/ImageSharp/Common/Exceptions/ImageFormatException.cs
index 7a91756b6..89877b1b6 100644
--- a/src/ImageSharp/Common/Exceptions/ImageFormatException.cs
+++ b/src/ImageSharp/Common/Exceptions/ImageFormatException.cs
@@ -11,13 +11,6 @@ namespace SixLabors.ImageSharp
///
public sealed class ImageFormatException : Exception
{
- ///
- /// Initializes a new instance of the class.
- ///
- public ImageFormatException()
- {
- }
-
///
/// Initializes a new instance of the class with the name of the
/// parameter that causes this exception.
diff --git a/src/ImageSharp/Common/Exceptions/ImageProcessingException.cs b/src/ImageSharp/Common/Exceptions/ImageProcessingException.cs
index eb50d0b65..3c75a6418 100644
--- a/src/ImageSharp/Common/Exceptions/ImageProcessingException.cs
+++ b/src/ImageSharp/Common/Exceptions/ImageProcessingException.cs
@@ -10,13 +10,6 @@ namespace SixLabors.ImageSharp
///
public sealed class ImageProcessingException : Exception
{
- ///
- /// Initializes a new instance of the class.
- ///
- public ImageProcessingException()
- {
- }
-
///
/// Initializes a new instance of the class with the name of the
/// parameter that causes this exception.
@@ -39,4 +32,4 @@ namespace SixLabors.ImageSharp
{
}
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Common/Helpers/ImageMaths.cs b/src/ImageSharp/Common/Helpers/ImageMaths.cs
index 3167a42c8..852122b29 100644
--- a/src/ImageSharp/Common/Helpers/ImageMaths.cs
+++ b/src/ImageSharp/Common/Helpers/ImageMaths.cs
@@ -2,8 +2,6 @@
// Licensed under the Apache License, Version 2.0.
using System;
-using System.Linq;
-using System.Numerics;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;
diff --git a/src/ImageSharp/Formats/Bmp/BmpCompression.cs b/src/ImageSharp/Formats/Bmp/BmpCompression.cs
index 22b12346f..ef063f010 100644
--- a/src/ImageSharp/Formats/Bmp/BmpCompression.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpCompression.cs
@@ -7,7 +7,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// Defines how the compression type of the image data
/// in the bitmap file.
///
- internal enum BmpCompression
+ internal enum BmpCompression : int
{
///
/// Each image row has a multiple of four elements. If the
diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
index dfbd44c04..26bd97b81 100644
--- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
@@ -34,29 +34,29 @@ namespace SixLabors.ImageSharp.Formats.Bmp
private const int Rgb16BMask = 0x1F;
///
- /// RLE8 flag value that indicates following byte has special meaning
+ /// RLE8 flag value that indicates following byte has special meaning.
///
private const int RleCommand = 0x00;
///
- /// RLE8 flag value marking end of a scan line
+ /// RLE8 flag value marking end of a scan line.
///
private const int RleEndOfLine = 0x00;
///
- /// RLE8 flag value marking end of bitmap data
+ /// RLE8 flag value marking end of bitmap data.
///
private const int RleEndOfBitmap = 0x01;
///
- /// RLE8 flag value marking the start of [x,y] offset instruction
+ /// RLE8 flag value marking the start of [x,y] offset instruction.
///
private const int RleDelta = 0x02;
///
/// The stream to decode from.
///
- private Stream currentStream;
+ private Stream stream;
///
/// The file header containing general information.
@@ -163,18 +163,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int Invert(int y, int height, bool inverted)
{
- int row;
-
- if (!inverted)
- {
- row = height - y - 1;
- }
- else
- {
- row = y;
- }
-
- return row;
+ return (!inverted) ? height - y - 1 : y;
}
///
@@ -261,7 +250,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
while (count < buffer.Length)
{
- if (this.currentStream.Read(cmd, 0, cmd.Length) != 2)
+ if (this.stream.Read(cmd, 0, cmd.Length) != 2)
{
throw new Exception("Failed to read 2 bytes from stream");
}
@@ -283,27 +272,29 @@ namespace SixLabors.ImageSharp.Formats.Bmp
break;
case RleDelta:
- int dx = this.currentStream.ReadByte();
- int dy = this.currentStream.ReadByte();
+ int dx = this.stream.ReadByte();
+ int dy = this.stream.ReadByte();
count += (w * dy) + dx;
break;
default:
- // If the second byte > 2, signals 'absolute mode'
+ // If the second byte > 2, we are in 'absolute mode'
// Take this number of bytes from the stream as uncompressed data
int length = cmd[1];
- int copyLength = length;
+
+ byte[] run = new byte[length];
+
+ this.stream.Read(run, 0, run.Length);
+
+ run.AsSpan().CopyTo(buffer.Slice(count));
+
+ count += run.Length;
// Absolute mode data is aligned to two-byte word-boundary
- length += length & 1;
+ int padding = length & 1;
- byte[] run = new byte[length];
- this.currentStream.Read(run, 0, run.Length);
- for (int i = 0; i < copyLength; i++)
- {
- buffer[count++] = run[i];
- }
+ this.stream.Skip(padding);
break;
}
@@ -348,7 +339,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
using (IManagedByteBuffer row = this.memoryManager.AllocateCleanManagedByteBuffer(arrayWidth + padding))
{
- var color = default(TPixel);
+ TPixel color = default;
var rgba = new Rgba32(0, 0, 0, 255);
Span rowSpan = row.Span;
@@ -356,7 +347,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
for (int y = 0; y < height; y++)
{
int newY = Invert(y, height, inverted);
- this.currentStream.Read(row.Array, 0, row.Length());
+ this.stream.Read(row.Array, 0, row.Length());
int offset = 0;
Span pixelRow = pixels.GetRowSpan(newY);
@@ -402,7 +393,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
{
for (int y = 0; y < height; y++)
{
- this.currentStream.Read(buffer.Array, 0, stride);
+ this.stream.Read(buffer.Array, 0, stride);
int newY = Invert(y, height, inverted);
Span pixelRow = pixels.GetRowSpan(newY);
@@ -440,7 +431,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
{
for (int y = 0; y < height; y++)
{
- this.currentStream.Read(row);
+ this.stream.Read(row);
int newY = Invert(y, height, inverted);
Span pixelSpan = pixels.GetRowSpan(newY);
PixelOperations.Instance.PackFromBgr24Bytes(row.Span, pixelSpan, width);
@@ -465,7 +456,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
{
for (int y = 0; y < height; y++)
{
- this.currentStream.Read(row);
+ this.stream.Read(row);
int newY = Invert(y, height, inverted);
Span pixelSpan = pixels.GetRowSpan(newY);
PixelOperations.Instance.PackFromBgra32Bytes(row.Span, pixelSpan, width);
@@ -478,98 +469,44 @@ namespace SixLabors.ImageSharp.Formats.Bmp
///
private void ReadInfoHeader()
{
- byte[] data = new byte[BmpInfoHeader.MaxHeaderSize];
+ byte[] buffer = new byte[BmpInfoHeader.MaxHeaderSize];
// read header size
- this.currentStream.Read(data, 0, BmpInfoHeader.HeaderSizeSize);
- int headerSize = BitConverter.ToInt32(data, 0);
- if (headerSize < BmpInfoHeader.BitmapCoreHeaderSize)
+ this.stream.Read(buffer, 0, BmpInfoHeader.HeaderSizeSize);
+
+ int headerSize = BitConverter.ToInt32(buffer, 0);
+ if (headerSize < BmpInfoHeader.CoreSize)
{
- throw new NotSupportedException($"This kind of bitmap files (header size $headerSize) is not supported.");
+ throw new NotSupportedException($"ImageSharp does not support this BMP file. HeaderSize: {headerSize}.");
}
- int skipAmmount = 0;
+ int skipAmount = 0;
if (headerSize > BmpInfoHeader.MaxHeaderSize)
{
- skipAmmount = headerSize - BmpInfoHeader.MaxHeaderSize;
+ skipAmount = headerSize - BmpInfoHeader.MaxHeaderSize;
headerSize = BmpInfoHeader.MaxHeaderSize;
}
// read the rest of the header
- this.currentStream.Read(data, BmpInfoHeader.HeaderSizeSize, headerSize - BmpInfoHeader.HeaderSizeSize);
+ this.stream.Read(buffer, BmpInfoHeader.HeaderSizeSize, headerSize - BmpInfoHeader.HeaderSizeSize);
- switch (headerSize)
+ if (headerSize == BmpInfoHeader.CoreSize)
{
- case BmpInfoHeader.BitmapCoreHeaderSize:
- this.infoHeader = this.ParseBitmapCoreHeader(data);
- break;
- case BmpInfoHeader.BitmapInfoHeaderSize:
- this.infoHeader = this.ParseBitmapInfoHeader(data);
- break;
- default:
- if (headerSize > BmpInfoHeader.BitmapInfoHeaderSize)
- {
- this.infoHeader = this.ParseBitmapInfoHeader(data);
- break;
- }
- else
- {
- throw new NotSupportedException($"This kind of bitmap files (header size $headerSize) is not supported.");
- }
+ // 12 bytes
+ this.infoHeader = BmpInfoHeader.ParseCore(buffer);
}
-
- // skip the remaining header because we can't read those parts
- this.currentStream.Skip(skipAmmount);
- }
-
- ///
- /// Parses the from the stream, assuming it uses the BITMAPCOREHEADER format.
- ///
- /// Header bytes read from the stream
- /// Parsed header
- ///
- private BmpInfoHeader ParseBitmapCoreHeader(byte[] data)
- {
- return new BmpInfoHeader
+ else if (headerSize >= BmpInfoHeader.Size)
{
- HeaderSize = BitConverter.ToInt32(data, 0),
- Width = BitConverter.ToUInt16(data, 4),
- Height = BitConverter.ToUInt16(data, 6),
- Planes = BitConverter.ToInt16(data, 8),
- BitsPerPixel = BitConverter.ToInt16(data, 10),
-
- // the rest is not present in the core header
- ImageSize = 0,
- XPelsPerMeter = 0,
- YPelsPerMeter = 0,
- ClrUsed = 0,
- ClrImportant = 0,
- Compression = BmpCompression.RGB
- };
- }
-
- ///
- /// Parses the from the stream, assuming it uses the BITMAPINFOHEADER format.
- ///
- /// Header bytes read from the stream
- /// Parsed header
- ///
- private BmpInfoHeader ParseBitmapInfoHeader(byte[] data)
- {
- return new BmpInfoHeader
+ // >= 40 bytes
+ this.infoHeader = BmpInfoHeader.Parse(buffer.AsSpan(0, 40));
+ }
+ else
{
- HeaderSize = BitConverter.ToInt32(data, 0),
- Width = BitConverter.ToInt32(data, 4),
- Height = BitConverter.ToInt32(data, 8),
- Planes = BitConverter.ToInt16(data, 12),
- BitsPerPixel = BitConverter.ToInt16(data, 14),
- ImageSize = BitConverter.ToInt32(data, 20),
- XPelsPerMeter = BitConverter.ToInt32(data, 24),
- YPelsPerMeter = BitConverter.ToInt32(data, 28),
- ClrUsed = BitConverter.ToInt32(data, 32),
- ClrImportant = BitConverter.ToInt32(data, 36),
- Compression = (BmpCompression)BitConverter.ToInt32(data, 16)
- };
+ throw new NotSupportedException($"ImageSharp does not support this BMP file. HeaderSize: {headerSize}.");
+ }
+
+ // skip the remaining header because we can't read those parts
+ this.stream.Skip(skipAmount);
}
///
@@ -577,15 +514,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp
///
private void ReadFileHeader()
{
- byte[] data = new byte[BmpFileHeader.Size];
+ byte[] buffer = new byte[BmpFileHeader.Size];
- this.currentStream.Read(data, 0, BmpFileHeader.Size);
+ this.stream.Read(buffer, 0, BmpFileHeader.Size);
- this.fileHeader = new BmpFileHeader(
- type: BitConverter.ToInt16(data, 0),
- fileSize: BitConverter.ToInt32(data, 2),
- reserved: BitConverter.ToInt32(data, 6),
- offset: BitConverter.ToInt32(data, 10));
+ this.fileHeader = BmpFileHeader.Parse(buffer);
}
///
@@ -593,66 +526,59 @@ namespace SixLabors.ImageSharp.Formats.Bmp
///
private void ReadImageHeaders(Stream stream, out bool inverted, out byte[] palette)
{
- this.currentStream = stream;
-
- try
+ this.stream = stream;
+
+ this.ReadFileHeader();
+ this.ReadInfoHeader();
+
+ // see http://www.drdobbs.com/architecture-and-design/the-bmp-file-format-part-1/184409517
+ // If the height is negative, then this is a Windows bitmap whose origin
+ // is the upper-left corner and not the lower-left. The inverted flag
+ // indicates a lower-left origin.Our code will be outputting an
+ // upper-left origin pixel array.
+ inverted = false;
+ if (this.infoHeader.Height < 0)
{
- this.ReadFileHeader();
- this.ReadInfoHeader();
-
- // see http://www.drdobbs.com/architecture-and-design/the-bmp-file-format-part-1/184409517
- // If the height is negative, then this is a Windows bitmap whose origin
- // is the upper-left corner and not the lower-left.The inverted flag
- // indicates a lower-left origin.Our code will be outputting an
- // upper-left origin pixel array.
- inverted = false;
- if (this.infoHeader.Height < 0)
- {
- inverted = true;
- this.infoHeader.Height = -this.infoHeader.Height;
- }
+ inverted = true;
+ this.infoHeader.Height = -this.infoHeader.Height;
+ }
- int colorMapSize = -1;
+ int colorMapSize = -1;
- if (this.infoHeader.ClrUsed == 0)
- {
- if (this.infoHeader.BitsPerPixel == 1 ||
- this.infoHeader.BitsPerPixel == 4 ||
- this.infoHeader.BitsPerPixel == 8)
- {
- colorMapSize = (int)Math.Pow(2, this.infoHeader.BitsPerPixel) * 4;
- }
- }
- else
+ if (this.infoHeader.ClrUsed == 0)
+ {
+ if (this.infoHeader.BitsPerPixel == 1 ||
+ this.infoHeader.BitsPerPixel == 4 ||
+ this.infoHeader.BitsPerPixel == 8)
{
- colorMapSize = this.infoHeader.ClrUsed * 4;
+ colorMapSize = (int)Math.Pow(2, this.infoHeader.BitsPerPixel) * 4;
}
+ }
+ else
+ {
+ colorMapSize = this.infoHeader.ClrUsed * 4;
+ }
- palette = null;
+ palette = null;
- if (colorMapSize > 0)
+ if (colorMapSize > 0)
+ {
+ // 256 * 4
+ if (colorMapSize > 1024)
{
- // 256 * 4
- if (colorMapSize > 1024)
- {
- throw new ImageFormatException($"Invalid bmp colormap size '{colorMapSize}'");
- }
-
- palette = new byte[colorMapSize];
-
- this.currentStream.Read(palette, 0, colorMapSize);
+ throw new ImageFormatException($"Invalid bmp colormap size '{colorMapSize}'");
}
- if (this.infoHeader.Width > int.MaxValue || this.infoHeader.Height > int.MaxValue)
- {
- throw new ArgumentOutOfRangeException(
- $"The input bitmap '{this.infoHeader.Width}x{this.infoHeader.Height}' is "
- + $"bigger then the max allowed size '{int.MaxValue}x{int.MaxValue}'");
- }
+ palette = new byte[colorMapSize];
+
+ this.stream.Read(palette, 0, colorMapSize);
}
- catch (IndexOutOfRangeException e)
+
+ if (this.infoHeader.Width > int.MaxValue || this.infoHeader.Height > int.MaxValue)
{
- throw new ImageFormatException("Bitmap does not have a valid format.", e);
+ throw new ArgumentOutOfRangeException(
+ $"The input bmp '{this.infoHeader.Width}x{this.infoHeader.Height}' is "
+ + $"bigger then the max allowed size '{int.MaxValue}x{int.MaxValue}'");
}
}
}
diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
index be7c1d2e5..2b0c90733 100644
--- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
@@ -3,7 +3,6 @@
using System;
using System.IO;
-using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
@@ -19,9 +18,6 @@ namespace SixLabors.ImageSharp.Formats.Bmp
///
private int padding;
- ///
- /// Gets or sets the number of bits per pixel.
- ///
private readonly BmpBitsPerPixel bitsPerPixel;
private readonly MemoryManager memoryManager;
@@ -54,20 +50,15 @@ namespace SixLabors.ImageSharp.Formats.Bmp
int bytesPerLine = 4 * (((image.Width * bpp) + 31) / 32);
this.padding = bytesPerLine - (image.Width * (int)this.bitsPerPixel);
- // Do not use IDisposable pattern here as we want to preserve the stream.
- var writer = new EndianBinaryWriter(Endianness.LittleEndian, stream);
-
- var infoHeader = new BmpInfoHeader
- {
- HeaderSize = BmpInfoHeader.BitmapInfoHeaderSize,
- Height = image.Height,
- Width = image.Width,
- BitsPerPixel = bpp,
- Planes = 1,
- ImageSize = image.Height * bytesPerLine,
- ClrUsed = 0,
- ClrImportant = 0
- };
+ var infoHeader = new BmpInfoHeader(
+ headerSize: BmpInfoHeader.Size,
+ height: image.Height,
+ width: image.Width,
+ bitsPerPixel: bpp,
+ planes: 1,
+ imageSize: image.Height * bytesPerLine,
+ clrUsed: 0,
+ clrImportant: 0);
var fileHeader = new BmpFileHeader(
type: 19778, // BM
@@ -75,63 +66,30 @@ namespace SixLabors.ImageSharp.Formats.Bmp
reserved: 0,
fileSize: 54 + infoHeader.ImageSize);
- WriteHeader(writer, fileHeader);
- this.WriteInfo(writer, infoHeader);
- this.WriteImage(writer, image.Frames.RootFrame);
+ byte[] buffer = new byte[40]; // TODO: stackalloc
- writer.Flush();
- }
+ fileHeader.WriteTo(buffer);
- ///
- /// Writes the bitmap header data to the binary stream.
- ///
- ///
- /// The containing the stream to write to.
- ///
- ///
- /// The containing the header data.
- ///
- private static void WriteHeader(EndianBinaryWriter writer, in BmpFileHeader fileHeader)
- {
- writer.Write(fileHeader.Type);
- writer.Write(fileHeader.FileSize);
- writer.Write(fileHeader.Reserved);
- writer.Write(fileHeader.Offset);
- }
+ stream.Write(buffer, 0, BmpFileHeader.Size);
- ///
- /// Writes the bitmap information to the binary stream.
- ///
- ///
- /// The containing the stream to write to.
- ///
- ///
- /// The containing the detailed information about the image.
- ///
- private void WriteInfo(EndianBinaryWriter writer, BmpInfoHeader infoHeader)
- {
- writer.Write(infoHeader.HeaderSize);
- writer.Write(infoHeader.Width);
- writer.Write(infoHeader.Height);
- writer.Write(infoHeader.Planes);
- writer.Write(infoHeader.BitsPerPixel);
- writer.Write((int)infoHeader.Compression);
- writer.Write(infoHeader.ImageSize);
- writer.Write(infoHeader.XPelsPerMeter);
- writer.Write(infoHeader.YPelsPerMeter);
- writer.Write(infoHeader.ClrUsed);
- writer.Write(infoHeader.ClrImportant);
+ infoHeader.WriteTo(buffer);
+
+ stream.Write(buffer, 0, 40);
+
+ this.WriteImage(stream, image.Frames.RootFrame);
+
+ stream.Flush();
}
///
/// Writes the pixel data to the binary stream.
///
/// The pixel format.
- /// The containing the stream to write to.
+ /// The to write to.
///
/// The containing pixel data.
///
- private void WriteImage(EndianBinaryWriter writer, ImageFrame image)
+ private void WriteImage(Stream stream, ImageFrame image)
where TPixel : struct, IPixel
{
using (PixelAccessor pixels = image.Lock())
@@ -139,11 +97,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp
switch (this.bitsPerPixel)
{
case BmpBitsPerPixel.Pixel32:
- this.Write32Bit(writer, pixels);
+ this.Write32Bit(stream, pixels);
break;
case BmpBitsPerPixel.Pixel24:
- this.Write24Bit(writer, pixels);
+ this.Write24Bit(stream, pixels);
break;
}
}
@@ -158,9 +116,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// Writes the 32bit color palette to the stream.
///
/// The pixel format.
- /// The containing the stream to write to.
+ /// The to write to.
/// The containing pixel data.
- private void Write32Bit(EndianBinaryWriter writer, PixelAccessor pixels)
+ private void Write32Bit(Stream stream, PixelAccessor pixels)
where TPixel : struct, IPixel
{
using (IManagedByteBuffer row = this.AllocateRow(pixels.Width, 4))
@@ -169,7 +127,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
{
Span pixelSpan = pixels.GetRowSpan(y);
PixelOperations.Instance.ToBgra32Bytes(pixelSpan, row.Span, pixelSpan.Length);
- writer.Write(row.Array, 0, row.Length());
+ stream.Write(row.Array, 0, row.Length());
}
}
}
@@ -178,9 +136,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// Writes the 24bit color palette to the stream.
///
/// The pixel format.
- /// The containing the stream to write to.
+ /// The to write to.
/// The containing pixel data.
- private void Write24Bit(EndianBinaryWriter writer, PixelAccessor pixels)
+ private void Write24Bit(Stream stream, PixelAccessor pixels)
where TPixel : struct, IPixel
{
using (IManagedByteBuffer row = this.AllocateRow(pixels.Width, 3))
@@ -189,7 +147,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
{
Span pixelSpan = pixels.GetRowSpan(y);
PixelOperations.Instance.ToBgr24Bytes(pixelSpan, row.Span, pixelSpan.Length);
- writer.Write(row.Array, 0, row.Length());
+ stream.Write(row.Array, 0, row.Length());
}
}
}
diff --git a/src/ImageSharp/Formats/Bmp/BmpFileHeader.cs b/src/ImageSharp/Formats/Bmp/BmpFileHeader.cs
index ed17164a2..e39a2af0e 100644
--- a/src/ImageSharp/Formats/Bmp/BmpFileHeader.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpFileHeader.cs
@@ -1,6 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
namespace SixLabors.ImageSharp.Formats.Bmp
{
///
@@ -13,6 +17,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// All of the other integer values are stored in little-endian format
/// (i.e. least-significant byte first).
///
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
internal readonly struct BmpFileHeader
{
///
@@ -44,12 +49,24 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// Gets any reserved data; actual value depends on the application
/// that creates the image.
///
- public int Reserved { get; }
+ public int Reserved { get; }
///
/// Gets the offset, i.e. starting address, of the byte where
/// the bitmap data can be found.
///
public int Offset { get; }
+
+ public static BmpFileHeader Parse(Span data)
+ {
+ return MemoryMarshal.Cast(data)[0];
+ }
+
+ public unsafe void WriteTo(Span buffer)
+ {
+ ref BmpFileHeader dest = ref Unsafe.As(ref MemoryMarshal.GetReference(buffer));
+
+ dest = this;
+ }
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs b/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs
index b24404cac..a088a9b13 100644
--- a/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs
@@ -1,5 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
+using System;
+using System.Buffers.Binary;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
namespace SixLabors.ImageSharp.Formats.Bmp
{
///
@@ -8,28 +13,55 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// the screen.
///
///
- internal sealed class BmpInfoHeader
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal struct BmpInfoHeader
{
///
/// Defines the size of the BITMAPINFOHEADER data structure in the bitmap file.
///
- public const int BitmapInfoHeaderSize = 40;
+ public const int Size = 40;
///
/// Defines the size of the BITMAPCOREHEADER data structure in the bitmap file.
///
- public const int BitmapCoreHeaderSize = 12;
+ public const int CoreSize = 12;
///
/// Defines the size of the biggest supported header data structure in the bitmap file.
///
- public const int MaxHeaderSize = BitmapInfoHeaderSize;
+ public const int MaxHeaderSize = Size;
///
/// Defines the size of the field.
///
public const int HeaderSizeSize = 4;
+ public BmpInfoHeader(
+ int headerSize,
+ int width,
+ int height,
+ short planes,
+ short bitsPerPixel,
+ BmpCompression compression = default,
+ int imageSize = 0,
+ int xPelsPerMeter = 0,
+ int yPelsPerMeter = 0,
+ int clrUsed = 0,
+ int clrImportant = 0)
+ {
+ this.HeaderSize = headerSize;
+ this.Width = width;
+ this.Height = height;
+ this.Planes = planes;
+ this.BitsPerPixel = bitsPerPixel;
+ this.Compression = compression;
+ this.ImageSize = imageSize;
+ this.XPelsPerMeter = xPelsPerMeter;
+ this.YPelsPerMeter = yPelsPerMeter;
+ this.ClrUsed = clrUsed;
+ this.ClrImportant = clrImportant;
+ }
+
///
/// Gets or sets the size of this header
///
@@ -91,5 +123,39 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// or 0 when every color is important{ get; set; } generally ignored.
///
public int ClrImportant { get; set; }
+
+ ///
+ /// Parses the full BITMAPINFOHEADER header (40 bytes).
+ ///
+ /// The data to parse.
+ /// Parsed header
+ ///
+ public static BmpInfoHeader Parse(ReadOnlySpan data)
+ {
+ return MemoryMarshal.Cast(data)[0];
+ }
+
+ ///
+ /// Parses the BITMAPCOREHEADER consisting of the headerSize, width, height, planes, and bitsPerPixel fields (12 bytes).
+ ///
+ /// The data to parse,
+ /// Parsed header
+ ///
+ public static BmpInfoHeader ParseCore(ReadOnlySpan data)
+ {
+ return new BmpInfoHeader(
+ headerSize: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4)),
+ width: BinaryPrimitives.ReadUInt16LittleEndian(data.Slice(4, 2)),
+ height: BinaryPrimitives.ReadUInt16LittleEndian(data.Slice(6, 2)),
+ planes: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(8, 2)),
+ bitsPerPixel: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(10, 2)));
+ }
+
+ public unsafe void WriteTo(Span buffer)
+ {
+ ref BmpInfoHeader dest = ref Unsafe.As(ref MemoryMarshal.GetReference(buffer));
+
+ dest = this;
+ }
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Bmp/IBmpDecoderOptions.cs b/src/ImageSharp/Formats/Bmp/IBmpDecoderOptions.cs
index 920c9ce02..c44ca73f2 100644
--- a/src/ImageSharp/Formats/Bmp/IBmpDecoderOptions.cs
+++ b/src/ImageSharp/Formats/Bmp/IBmpDecoderOptions.cs
@@ -1,11 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using System;
-using System.Collections.Generic;
-using System.IO;
-using SixLabors.ImageSharp.PixelFormats;
-
namespace SixLabors.ImageSharp.Formats.Bmp
{
///
@@ -15,4 +10,4 @@ namespace SixLabors.ImageSharp.Formats.Bmp
{
// added this for consistancy so we can add stuff as required, no options currently availible
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs b/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs
index c4e219889..0bfd6980b 100644
--- a/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs
+++ b/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs
@@ -1,11 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using System;
-using System.Collections.Generic;
-using System.IO;
-using SixLabors.ImageSharp.PixelFormats;
-
namespace SixLabors.ImageSharp.Formats.Bmp
{
///
diff --git a/src/ImageSharp/Formats/Bmp/ImageExtensions.cs b/src/ImageSharp/Formats/Bmp/ImageExtensions.cs
index 35e168e27..57e4615ba 100644
--- a/src/ImageSharp/Formats/Bmp/ImageExtensions.cs
+++ b/src/ImageSharp/Formats/Bmp/ImageExtensions.cs
@@ -1,10 +1,8 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using System;
using System.IO;
using SixLabors.ImageSharp.Advanced;
-using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Bmp;
using SixLabors.ImageSharp.PixelFormats;
diff --git a/src/ImageSharp/Formats/Gif/DisposalMethod.cs b/src/ImageSharp/Formats/Gif/DisposalMethod.cs
index f553c204b..5371fc0fa 100644
--- a/src/ImageSharp/Formats/Gif/DisposalMethod.cs
+++ b/src/ImageSharp/Formats/Gif/DisposalMethod.cs
@@ -11,23 +11,26 @@ namespace SixLabors.ImageSharp.Formats.Gif
public enum DisposalMethod
{
///
- /// No disposal specified. The decoder is not required to take any action.
+ /// No disposal specified.
+ /// The decoder is not required to take any action.
///
Unspecified = 0,
///
- /// Do not dispose. The graphic is to be left in place.
+ /// Do not dispose.
+ /// The graphic is to be left in place.
///
NotDispose = 1,
///
- /// Restore to background color. The area used by the graphic must be restored to
- /// the background color.
+ /// Restore to background color.
+ /// The area used by the graphic must be restored to the background color.
///
RestoreToBackground = 2,
///
- /// Restore to previous. The decoder is required to restore the area overwritten by the
+ /// Restore to previous.
+ /// The decoder is required to restore the area overwritten by the
/// graphic with what was there prior to rendering the graphic.
///
RestoreToPrevious = 3
diff --git a/src/ImageSharp/Formats/Gif/GifConstants.cs b/src/ImageSharp/Formats/Gif/GifConstants.cs
index ffab45a56..0dbd39b99 100644
--- a/src/ImageSharp/Formats/Gif/GifConstants.cs
+++ b/src/ImageSharp/Formats/Gif/GifConstants.cs
@@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
/// The application block size.
///
- public const byte ApplicationBlockSize = 0x0b;
+ public const byte ApplicationBlockSize = 11;
///
/// The comment label.
diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
index 118ec2954..1900d0df0 100644
--- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
+++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
@@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0.
using System;
-using System.Buffers;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -33,7 +32,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
/// The currently loaded stream.
///
- private Stream currentStream;
+ private Stream stream;
///
/// The global color table.
@@ -58,7 +57,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
/// The graphics control extension.
///
- private GifGraphicsControlExtension graphicsControlExtension;
+ private GifGraphicControlExtension graphicsControlExtension;
///
/// The metadata
@@ -237,17 +236,9 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
private void ReadGraphicalControlExtension()
{
- this.currentStream.Read(this.buffer, 0, 6);
+ this.stream.Read(this.buffer, 0, 6);
- byte packed = this.buffer[1];
-
- this.graphicsControlExtension = new GifGraphicsControlExtension
- {
- DelayTime = BitConverter.ToInt16(this.buffer, 2),
- TransparencyIndex = this.buffer[4],
- TransparencyFlag = (packed & 0x01) == 1,
- DisposalMethod = (DisposalMethod)((packed & 0x1C) >> 2)
- };
+ this.graphicsControlExtension = GifGraphicControlExtension.Parse(this.buffer);
}
///
@@ -256,22 +247,9 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
private GifImageDescriptor ReadImageDescriptor()
{
- this.currentStream.Read(this.buffer, 0, 9);
-
- byte packed = this.buffer[8];
+ this.stream.Read(this.buffer, 0, 9);
- var imageDescriptor = new GifImageDescriptor
- {
- Left = BitConverter.ToInt16(this.buffer, 0),
- Top = BitConverter.ToInt16(this.buffer, 2),
- Width = BitConverter.ToInt16(this.buffer, 4),
- Height = BitConverter.ToInt16(this.buffer, 6),
- LocalColorTableFlag = ((packed & 0x80) >> 7) == 1,
- LocalColorTableSize = 2 << (packed & 0x07),
- InterlaceFlag = ((packed & 0x40) >> 6) == 1
- };
-
- return imageDescriptor;
+ return GifImageDescriptor.Parse(this.buffer);
}
///
@@ -279,25 +257,9 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
private void ReadLogicalScreenDescriptor()
{
- this.currentStream.Read(this.buffer, 0, 7);
-
- byte packed = this.buffer[4];
+ this.stream.Read(this.buffer, 0, 7);
- this.logicalScreenDescriptor = new GifLogicalScreenDescriptor
- {
- Width = BitConverter.ToInt16(this.buffer, 0),
- Height = BitConverter.ToInt16(this.buffer, 2),
- BitsPerPixel = (this.buffer[4] & 0x07) + 1, // The lowest 3 bits represent the bit depth minus 1
- BackgroundColorIndex = this.buffer[5],
- PixelAspectRatio = this.buffer[6],
- GlobalColorTableFlag = ((packed & 0x80) >> 7) == 1,
- GlobalColorTableSize = 2 << (packed & 0x07)
- };
-
- if (this.logicalScreenDescriptor.GlobalColorTableSize > 255 * 4)
- {
- throw new ImageFormatException($"Invalid gif colormap size '{this.logicalScreenDescriptor.GlobalColorTableSize}'");
- }
+ this.logicalScreenDescriptor = GifLogicalScreenDescriptor.Parse(this.buffer);
}
///
@@ -306,13 +268,13 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// The number of bytes to skip.
private void Skip(int length)
{
- this.currentStream.Skip(length);
+ this.stream.Skip(length);
int flag;
- while ((flag = this.currentStream.ReadByte()) != 0)
+ while ((flag = this.stream.ReadByte()) != 0)
{
- this.currentStream.Skip(flag);
+ this.stream.Skip(flag);
}
}
@@ -323,7 +285,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
{
int length;
- while ((length = this.currentStream.ReadByte()) != 0)
+ while ((length = this.stream.ReadByte()) != 0)
{
if (length > GifConstants.MaxCommentLength)
{
@@ -332,13 +294,13 @@ namespace SixLabors.ImageSharp.Formats.Gif
if (this.IgnoreMetadata)
{
- this.currentStream.Seek(length, SeekOrigin.Current);
+ this.stream.Seek(length, SeekOrigin.Current);
continue;
}
using (IManagedByteBuffer commentsBuffer = this.MemoryManager.AllocateManagedByteBuffer(length))
{
- this.currentStream.Read(commentsBuffer.Array, 0, length);
+ this.stream.Read(commentsBuffer.Array, 0, length);
string comments = this.TextEncoding.GetString(commentsBuffer.Array, 0, length);
this.metaData.Properties.Add(new ImageProperty(GifConstants.Comments, comments));
}
@@ -365,7 +327,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
{
int length = imageDescriptor.LocalColorTableSize * 3;
localColorTable = this.configuration.MemoryManager.AllocateManagedByteBuffer(length, true);
- this.currentStream.Read(localColorTable.Array, 0, length);
+ this.stream.Read(localColorTable.Array, 0, length);
}
indices = this.configuration.MemoryManager.AllocateManagedByteBuffer(imageDescriptor.Width * imageDescriptor.Height, true);
@@ -390,10 +352,10 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// The .
/// The pixel array to write to.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void ReadFrameIndices(GifImageDescriptor imageDescriptor, Span indices)
+ private void ReadFrameIndices(in GifImageDescriptor imageDescriptor, Span indices)
{
- int dataSize = this.currentStream.ReadByte();
- using (var lzwDecoder = new LzwDecoder(this.configuration.MemoryManager, this.currentStream))
+ int dataSize = this.stream.ReadByte();
+ using (var lzwDecoder = new LzwDecoder(this.configuration.MemoryManager, this.stream))
{
lzwDecoder.DecodePixels(imageDescriptor.Width, imageDescriptor.Height, dataSize, indices);
}
@@ -408,7 +370,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// The indexed pixels.
/// The color table containing the available colors.
/// The
- private void ReadFrameColors(ref Image image, ref ImageFrame previousFrame, Span indices, Span colorTable, GifImageDescriptor descriptor)
+ private void ReadFrameColors(ref Image image, ref ImageFrame previousFrame, Span indices, Span colorTable, in GifImageDescriptor descriptor)
where TPixel : struct, IPixel
{
ref byte indicesRef = ref MemoryMarshal.GetReference(indices);
@@ -430,8 +392,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
}
else
{
- if (this.graphicsControlExtension != null &&
- this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToPrevious)
+ if (this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToPrevious)
{
prevFrame = previousFrame;
}
@@ -494,8 +455,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
{
int index = Unsafe.Add(ref indicesRef, i);
- if (this.graphicsControlExtension == null ||
- this.graphicsControlExtension.TransparencyFlag == false ||
+ if (this.graphicsControlExtension.TransparencyFlag == false ||
this.graphicsControlExtension.TransparencyIndex != index)
{
int indexOffset = index * 3;
@@ -518,8 +478,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
previousFrame = currentFrame ?? image.Frames.RootFrame;
- if (this.graphicsControlExtension != null &&
- this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToBackground)
+ if (this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToBackground)
{
this.restoreArea = new Rectangle(descriptor.Left, descriptor.Top, descriptor.Width, descriptor.Height);
}
@@ -551,15 +510,12 @@ namespace SixLabors.ImageSharp.Formats.Gif
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void SetFrameMetaData(ImageFrameMetaData meta)
{
- if (this.graphicsControlExtension != null)
+ if (this.graphicsControlExtension.DelayTime > 0)
{
- if (this.graphicsControlExtension.DelayTime > 0)
- {
- meta.FrameDelay = this.graphicsControlExtension.DelayTime;
- }
-
- meta.DisposalMethod = this.graphicsControlExtension.DisposalMethod;
+ meta.FrameDelay = this.graphicsControlExtension.DelayTime;
}
+
+ meta.DisposalMethod = this.graphicsControlExtension.DisposalMethod;
}
///
@@ -570,10 +526,10 @@ namespace SixLabors.ImageSharp.Formats.Gif
{
this.metaData = new ImageMetaData();
- this.currentStream = stream;
+ this.stream = stream;
// Skip the identifier
- this.currentStream.Skip(6);
+ this.stream.Skip(6);
this.ReadLogicalScreenDescriptor();
if (this.logicalScreenDescriptor.GlobalColorTableFlag)
diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
index cb865e95d..747867c80 100644
--- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
+++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
@@ -2,51 +2,47 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers.Binary;
using System.IO;
-using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
-using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing.Quantization;
-// TODO: This is causing more GC collections than I'm happy with.
-// This is likely due to the number of short writes to the stream we are doing.
-// We should investigate reducing them since we know the length of the byte array we require for multiple parts.
namespace SixLabors.ImageSharp.Formats.Gif
{
///
- /// Performs the gif encoding operation.
+ /// Implements the GIF encoding protocol.
///
internal sealed class GifEncoderCore
{
private readonly MemoryManager memoryManager;
///
- /// The temp buffer used to reduce allocations.
+ /// A reusable buffer used to reduce allocations.
///
- private readonly byte[] buffer = new byte[16];
+ private readonly byte[] buffer = new byte[20];
///
- /// Gets the TextEncoding
+ /// Gets the text encoding used to write comments.
///
private readonly Encoding textEncoding;
///
- /// Gets or sets the quantizer for reducing the color count.
+ /// Gets or sets the quantizer used to generate the color palette.
///
private readonly IQuantizer quantizer;
///
- /// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
+ /// A flag indicating whether to ingore the metadata when writing the image.
///
private readonly bool ignoreMetadata;
///
- /// The number of bits requires to store the image palette.
+ /// The number of bits requires to store the color palette.
///
private int bitDepth;
@@ -75,9 +71,6 @@ namespace SixLabors.ImageSharp.Formats.Gif
Guard.NotNull(image, nameof(image));
Guard.NotNull(stream, nameof(stream));
- // Do not use IDisposable pattern here as we want to preserve the stream.
- var writer = new EndianBinaryWriter(Endianness.LittleEndian, stream);
-
// Quantize the image returning a palette.
QuantizedFrame quantized = this.quantizer.CreateFrameQuantizer().QuantizeFrame(image.Frames.RootFrame);
@@ -87,18 +80,18 @@ namespace SixLabors.ImageSharp.Formats.Gif
int index = this.GetTransparentIndex(quantized);
// Write the header.
- this.WriteHeader(writer);
+ this.WriteHeader(stream);
// Write the LSD. We'll use local color tables for now.
- this.WriteLogicalScreenDescriptor(image, writer, index);
+ this.WriteLogicalScreenDescriptor(image, stream, index);
// Write the first frame.
- this.WriteComments(image, writer);
+ this.WriteComments(image.MetaData, stream);
// Write additional frames.
if (image.Frames.Count > 1)
{
- this.WriteApplicationExtension(writer, image.MetaData.RepeatCount);
+ this.WriteApplicationExtension(stream, image.MetaData.RepeatCount);
}
foreach (ImageFrame frame in image.Frames)
@@ -108,16 +101,16 @@ namespace SixLabors.ImageSharp.Formats.Gif
quantized = this.quantizer.CreateFrameQuantizer().QuantizeFrame(frame);
}
- this.WriteGraphicalControlExtension(frame.MetaData, writer, this.GetTransparentIndex(quantized));
- this.WriteImageDescriptor(frame, writer);
- this.WriteColorTable(quantized, writer);
- this.WriteImageData(quantized, writer);
+ this.WriteGraphicalControlExtension(frame.MetaData, stream, this.GetTransparentIndex(quantized));
+ this.WriteImageDescriptor(frame, stream);
+ this.WriteColorTable(quantized, stream);
+ this.WriteImageData(quantized, stream);
quantized = null; // So next frame can regenerate it
}
// TODO: Write extension etc
- writer.Write(GifConstants.EndIntroducer);
+ stream.WriteByte(GifConstants.EndIntroducer);
}
///
@@ -135,7 +128,8 @@ namespace SixLabors.ImageSharp.Formats.Gif
{
// Transparent pixels are much more likely to be found at the end of a palette
int index = -1;
- var trans = default(Rgba32);
+ Rgba32 trans = default;
+
ref TPixel paletteRef = ref MemoryMarshal.GetReference(quantized.Palette.AsSpan());
for (int i = quantized.Palette.Length - 1; i >= 0; i--)
{
@@ -153,11 +147,11 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
/// Writes the file header signature and version to the stream.
///
- /// The writer to write to the stream with.
+ /// The stream to write to.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void WriteHeader(EndianBinaryWriter writer)
+ private void WriteHeader(Stream stream)
{
- writer.Write(GifConstants.MagicNumber);
+ stream.Write(GifConstants.MagicNumber, 0, GifConstants.MagicNumber.Length);
}
///
@@ -165,43 +159,30 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
/// The pixel format.
/// The image to encode.
- /// The writer to write to the stream with.
+ /// The stream to write to.
/// The transparency index to set the default background index to.
- private void WriteLogicalScreenDescriptor(Image image, EndianBinaryWriter writer, int transparencyIndex)
+ private void WriteLogicalScreenDescriptor(Image image, Stream stream, int transparencyIndex)
where TPixel : struct, IPixel
{
- var descriptor = new GifLogicalScreenDescriptor
- {
- Width = (short)image.Width,
- Height = (short)image.Height,
- GlobalColorTableFlag = false, // TODO: Always false for now.
- GlobalColorTableSize = this.bitDepth - 1,
- BackgroundColorIndex = unchecked((byte)transparencyIndex)
- };
-
- writer.Write((ushort)descriptor.Width);
- writer.Write((ushort)descriptor.Height);
-
- var field = default(PackedField);
- field.SetBit(0, descriptor.GlobalColorTableFlag); // 1 : Global color table flag = 1 || 0 (GCT used/ not used)
- field.SetBits(1, 3, descriptor.GlobalColorTableSize); // 2-4 : color resolution
- field.SetBit(4, false); // 5 : GCT sort flag = 0
- field.SetBits(5, 3, descriptor.GlobalColorTableSize); // 6-8 : GCT size. 2^(N+1)
-
- // Reduce the number of writes
- this.buffer[0] = field.Byte;
- this.buffer[1] = descriptor.BackgroundColorIndex; // Background Color Index
- this.buffer[2] = descriptor.PixelAspectRatio; // Pixel aspect ratio. Assume 1:1
-
- writer.Write(this.buffer, 0, 3);
+ byte packedValue = GifLogicalScreenDescriptor.GetPackedValue(false, this.bitDepth - 1, false, this.bitDepth - 1);
+
+ var descriptor = new GifLogicalScreenDescriptor(
+ width: (ushort)image.Width,
+ height: (ushort)image.Height,
+ packed: packedValue,
+ backgroundColorIndex: unchecked((byte)transparencyIndex));
+
+ descriptor.WriteTo(this.buffer);
+
+ stream.Write(this.buffer, 0, GifLogicalScreenDescriptor.Size);
}
///
/// Writes the application extension to the stream.
///
- /// The writer to write to the stream with.
+ /// The stream to write to.
/// The animated image repeat count.
- private void WriteApplicationExtension(EndianBinaryWriter writer, ushort repeatCount)
+ private void WriteApplicationExtension(Stream stream, ushort repeatCount)
{
// Application Extension Header
if (repeatCount != 1)
@@ -210,36 +191,37 @@ namespace SixLabors.ImageSharp.Formats.Gif
this.buffer[1] = GifConstants.ApplicationExtensionLabel;
this.buffer[2] = GifConstants.ApplicationBlockSize;
- writer.Write(this.buffer, 0, 3);
+ // Write NETSCAPE2.0
+ GifConstants.ApplicationIdentificationBytes.AsSpan().CopyTo(this.buffer.AsSpan(3, 11));
- writer.Write(GifConstants.ApplicationIdentificationBytes); // NETSCAPE2.0
- writer.Write((byte)3); // Application block length
- writer.Write((byte)1); // Data sub-block index (always 1)
+ // Application Data ----
+ this.buffer[14] = 3; // Application block length
+ this.buffer[15] = 1; // Data sub-block index (always 1)
// 0 means loop indefinitely. Count is set as play n + 1 times.
repeatCount = (ushort)Math.Max(0, repeatCount - 1);
- writer.Write(repeatCount); // Repeat count for images.
- writer.Write(GifConstants.Terminator); // Terminator
+ BinaryPrimitives.WriteUInt16LittleEndian(this.buffer.AsSpan(16, 2), repeatCount); // Repeat count for images.
+
+ this.buffer[18] = GifConstants.Terminator; // Terminator
+
+ stream.Write(this.buffer, 0, 19);
}
}
///
/// Writes the image comments to the stream.
///
- /// The pixel format.
- /// The to be encoded.
- /// The stream to write to.
- private void WriteComments(Image image, EndianBinaryWriter writer)
- where TPixel : struct, IPixel
+ /// The metadata to be extract the comment data.
+ /// The stream to write to.
+ private void WriteComments(ImageMetaData metadata, Stream stream)
{
if (this.ignoreMetadata)
{
return;
}
- ImageProperty property = image.MetaData.Properties.FirstOrDefault(p => p.Name == GifConstants.Comments);
- if (property == null || string.IsNullOrEmpty(property.Value))
+ if (!metadata.TryGetProperty(GifConstants.Comments, out ImageProperty property) || string.IsNullOrEmpty(property.Value))
{
return;
}
@@ -252,44 +234,46 @@ namespace SixLabors.ImageSharp.Formats.Gif
this.buffer[1] = GifConstants.CommentLabel;
this.buffer[2] = (byte)count;
- writer.Write(this.buffer, 0, 3);
- writer.Write(comments, 0, count);
- writer.Write(GifConstants.Terminator);
+ stream.Write(this.buffer, 0, 3);
+ stream.Write(comments, 0, count);
+ stream.WriteByte(GifConstants.Terminator);
}
///
/// Writes the graphics control extension to the stream.
///
/// The metadata of the image or frame.
- /// The stream to write to.
+ /// The stream to write to.
/// The index of the color in the color palette to make transparent.
- private void WriteGraphicalControlExtension(ImageFrameMetaData metaData, EndianBinaryWriter writer, int transparencyIndex)
+ private void WriteGraphicalControlExtension(ImageFrameMetaData metaData, Stream stream, int transparencyIndex)
{
- var extension = new GifGraphicsControlExtension
- {
- DisposalMethod = metaData.DisposalMethod,
- TransparencyFlag = transparencyIndex > -1,
- TransparencyIndex = unchecked((byte)transparencyIndex),
- DelayTime = metaData.FrameDelay
- };
+ byte packedValue = GifGraphicControlExtension.GetPackedValue(
+ disposalMethod: metaData.DisposalMethod,
+ transparencyFlag: transparencyIndex > -1);
- // Write the intro.
+ var extension = new GifGraphicControlExtension(
+ packed: packedValue,
+ transparencyIndex: unchecked((byte)transparencyIndex),
+ delayTime: (ushort)metaData.FrameDelay);
+
+ this.WriteExtension(extension, stream);
+ }
+
+ ///
+ /// Writes the provided extension to the stream.
+ ///
+ /// The extension to write to the stream.
+ /// The stream to write to.
+ public void WriteExtension(IGifExtension extension, Stream stream)
+ {
this.buffer[0] = GifConstants.ExtensionIntroducer;
- this.buffer[1] = GifConstants.GraphicControlLabel;
- this.buffer[2] = 4;
- writer.Write(this.buffer, 0, 3);
+ this.buffer[1] = extension.Label;
- var field = default(PackedField);
- field.SetBits(3, 3, (int)extension.DisposalMethod); // 1-3 : Reserved, 4-6 : Disposal
+ int extensionSize = extension.WriteTo(this.buffer.AsSpan(2));
- // TODO: Allow this as an option.
- field.SetBit(6, false); // 7 : User input - 0 = none
- field.SetBit(7, extension.TransparencyFlag); // 8: Has transparent.
+ this.buffer[extensionSize + 2] = GifConstants.Terminator;
- writer.Write(field.Byte);
- writer.Write((ushort)extension.DelayTime);
- writer.Write(extension.TransparencyIndex);
- writer.Write(GifConstants.Terminator);
+ stream.Write(this.buffer, 0, extensionSize + 3);
}
///
@@ -297,25 +281,26 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
/// The pixel format.
/// The to be encoded.
- /// The stream to write to.
- private void WriteImageDescriptor(ImageFrame image, EndianBinaryWriter writer)
+ /// The stream to write to.
+ private void WriteImageDescriptor(ImageFrame image, Stream stream)
where TPixel : struct, IPixel
{
- writer.Write(GifConstants.ImageDescriptorLabel); // 2c
-
- // TODO: Can we capture this?
- writer.Write((ushort)0); // Left position
- writer.Write((ushort)0); // Top position
- writer.Write((ushort)image.Width);
- writer.Write((ushort)image.Height);
-
- var field = default(PackedField);
- field.SetBit(0, true); // 1: Local color table flag = 1 (LCT used)
- field.SetBit(1, false); // 2: Interlace flag 0
- field.SetBit(2, false); // 3: Sort flag 0
- field.SetBits(5, 3, this.bitDepth - 1); // 4-5: Reserved, 6-8 : LCT size. 2^(N+1)
-
- writer.Write(field.Byte);
+ byte packedValue = GifImageDescriptor.GetPackedValue(
+ localColorTableFlag: true,
+ interfaceFlag: false,
+ sortFlag: false,
+ localColorTableSize: (byte)this.bitDepth); // Note: we subtract 1 from the colorTableSize writing
+
+ var descriptor = new GifImageDescriptor(
+ left: 0,
+ top: 0,
+ width: (ushort)image.Width,
+ height: (ushort)image.Height,
+ packed: packedValue);
+
+ descriptor.WriteTo(this.buffer);
+
+ stream.Write(this.buffer, 0, GifImageDescriptor.Size);
}
///
@@ -323,21 +308,19 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
/// The pixel format.
/// The to encode.
- /// The writer to write to the stream with.
- private void WriteColorTable(QuantizedFrame image, EndianBinaryWriter writer)
+ /// The stream to write to.
+ private void WriteColorTable(QuantizedFrame image, Stream stream)
where TPixel : struct, IPixel
{
- // Grab the palette and write it to the stream.
int pixelCount = image.Palette.Length;
- // Get max colors for bit depth.
- int colorTableLength = (int)Math.Pow(2, this.bitDepth) * 3;
- var rgb = default(Rgb24);
+ int colorTableLength = (int)Math.Pow(2, this.bitDepth) * 3; // The maximium number of colors for the bit depth
+ Rgb24 rgb = default;
+
using (IManagedByteBuffer colorTable = this.memoryManager.AllocateManagedByteBuffer(colorTableLength))
{
ref TPixel paletteRef = ref MemoryMarshal.GetReference(image.Palette.AsSpan());
ref Rgb24 rgb24Ref = ref Unsafe.As(ref MemoryMarshal.GetReference(colorTable.Span));
-
for (int i = 0; i < pixelCount; i++)
{
ref TPixel entry = ref Unsafe.Add(ref paletteRef, i);
@@ -345,7 +328,8 @@ namespace SixLabors.ImageSharp.Formats.Gif
Unsafe.Add(ref rgb24Ref, i) = rgb;
}
- writer.Write(colorTable.Array, 0, colorTableLength);
+ // Write the palette to the stream
+ stream.Write(colorTable.Array, 0, colorTableLength);
}
}
@@ -354,13 +338,13 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
/// The pixel format.
/// The containing indexed pixels.
- /// The stream to write to.
- private void WriteImageData(QuantizedFrame image, EndianBinaryWriter writer)
+ /// The stream to write to.
+ private void WriteImageData(QuantizedFrame image, Stream stream)
where TPixel : struct, IPixel
{
using (var encoder = new LzwEncoder(this.memoryManager, image.Pixels, (byte)this.bitDepth))
{
- encoder.Encode(writer.BaseStream);
+ encoder.Encode(stream);
}
}
}
diff --git a/src/ImageSharp/Formats/Gif/GifImageFormatDetector.cs b/src/ImageSharp/Formats/Gif/GifImageFormatDetector.cs
index 36346f606..bfbd334b0 100644
--- a/src/ImageSharp/Formats/Gif/GifImageFormatDetector.cs
+++ b/src/ImageSharp/Formats/Gif/GifImageFormatDetector.cs
@@ -16,17 +16,11 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
public IImageFormat DetectFormat(ReadOnlySpan header)
{
- if (this.IsSupportedFileFormat(header))
- {
- return ImageFormats.Gif;
- }
-
- return null;
+ return this.IsSupportedFileFormat(header) ? ImageFormats.Gif : null;
}
private bool IsSupportedFileFormat(ReadOnlySpan header)
{
- // TODO: This should be in constants
return header.Length >= this.HeaderSize &&
header[0] == 0x47 && // G
header[1] == 0x49 && // I
diff --git a/src/ImageSharp/Formats/Gif/IGifDecoderOptions.cs b/src/ImageSharp/Formats/Gif/IGifDecoderOptions.cs
index a2288f30a..e99f09add 100644
--- a/src/ImageSharp/Formats/Gif/IGifDecoderOptions.cs
+++ b/src/ImageSharp/Formats/Gif/IGifDecoderOptions.cs
@@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
bool IgnoreMetadata { get; }
///
- /// Gets the encoding that should be used when reading comments.
+ /// Gets the text encoding that should be used when reading comments.
///
Encoding TextEncoding { get; }
diff --git a/src/ImageSharp/Formats/Gif/IGifEncoderOptions.cs b/src/ImageSharp/Formats/Gif/IGifEncoderOptions.cs
index 1f1875789..44dd19db6 100644
--- a/src/ImageSharp/Formats/Gif/IGifEncoderOptions.cs
+++ b/src/ImageSharp/Formats/Gif/IGifEncoderOptions.cs
@@ -7,7 +7,7 @@ using SixLabors.ImageSharp.Processing.Quantization;
namespace SixLabors.ImageSharp.Formats.Gif
{
///
- /// The configuration options used for encoding gifs
+ /// The configuration options used for encoding gifs.
///
internal interface IGifEncoderOptions
{
@@ -17,12 +17,12 @@ namespace SixLabors.ImageSharp.Formats.Gif
bool IgnoreMetadata { get; }
///
- /// Gets the encoding that should be used when writing comments.
+ /// Gets the text encoding used to write comments.
///
Encoding TextEncoding { get; }
///
- /// Gets the quantizer for reducing the color count.
+ /// Gets the quantizer used to generate the color palette.
///
IQuantizer Quantizer { get; }
}
diff --git a/src/ImageSharp/Formats/Gif/ImageExtensions.cs b/src/ImageSharp/Formats/Gif/ImageExtensions.cs
index 78acadb4b..1c41285a9 100644
--- a/src/ImageSharp/Formats/Gif/ImageExtensions.cs
+++ b/src/ImageSharp/Formats/Gif/ImageExtensions.cs
@@ -1,10 +1,8 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using System;
using System.IO;
using SixLabors.ImageSharp.Advanced;
-using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Gif;
using SixLabors.ImageSharp.PixelFormats;
@@ -16,7 +14,7 @@ namespace SixLabors.ImageSharp
public static partial class ImageExtensions
{
///
- /// Saves the image to the given stream with the gif format.
+ /// Saves the image to the given stream in the gif format.
///
/// The pixel format.
/// The image this method extends.
@@ -27,7 +25,7 @@ namespace SixLabors.ImageSharp
=> source.SaveAsGif(stream, null);
///
- /// Saves the image to the given stream with the gif format.
+ /// Saves the image to the given stream in the gif format.
///
/// The pixel format.
/// The image this method extends.
diff --git a/src/ImageSharp/Formats/Gif/LzwDecoder.cs b/src/ImageSharp/Formats/Gif/LzwDecoder.cs
index 37daa6de5..9f9e070e2 100644
--- a/src/ImageSharp/Formats/Gif/LzwDecoder.cs
+++ b/src/ImageSharp/Formats/Gif/LzwDecoder.cs
@@ -44,19 +44,6 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
private readonly IBuffer pixelStack;
- ///
- /// A value indicating whether this instance of the given entity has been disposed.
- ///
- /// if this instance has been disposed; otherwise, .
- ///
- /// If the entity is disposed, it must not be disposed a second
- /// time. The isDisposed field is set the first time the entity
- /// is disposed. If the isDisposed field is true, then the Dispose()
- /// method will not dispose again. This help not to prolong the entity's
- /// life in the Garbage Collector.
- ///
- private bool isDisposed;
-
///
/// Initializes a new instance of the class
/// and sets the stream, where the compressed data should be read from.
@@ -225,13 +212,6 @@ namespace SixLabors.ImageSharp.Formats.Gif
}
}
- ///
- public void Dispose()
- {
- // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
- this.Dispose(true);
- }
-
///
/// Reads the next data block from the stream. A data block begins with a byte,
/// which defines the size of the block, followed by the block itself.
@@ -253,25 +233,12 @@ namespace SixLabors.ImageSharp.Formats.Gif
return count != bufferSize ? 0 : bufferSize;
}
- ///
- /// Disposes the object and frees resources for the Garbage Collector.
- ///
- /// If true, the object gets disposed.
- private void Dispose(bool disposing)
+ ///
+ public void Dispose()
{
- if (this.isDisposed)
- {
- return;
- }
-
- if (disposing)
- {
- this.prefix?.Dispose();
- this.suffix?.Dispose();
- this.pixelStack?.Dispose();
- }
-
- this.isDisposed = true;
+ this.prefix.Dispose();
+ this.suffix.Dispose();
+ this.pixelStack.Dispose();
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Gif/LzwEncoder.cs b/src/ImageSharp/Formats/Gif/LzwEncoder.cs
index 60bc56dc5..1dc7e99e8 100644
--- a/src/ImageSharp/Formats/Gif/LzwEncoder.cs
+++ b/src/ImageSharp/Formats/Gif/LzwEncoder.cs
@@ -34,16 +34,6 @@ namespace SixLabors.ImageSharp.Formats.Gif
///
internal sealed class LzwEncoder : IDisposable
{
- ///
- /// The end-of-file marker
- ///
- private const int Eof = -1;
-
- ///
- /// The maximum number of bits.
- ///
- private const int Bits = 12;
-
///
/// 80% occupancy
///
@@ -59,7 +49,17 @@ namespace SixLabors.ImageSharp.Formats.Gif
};
///
- /// The working pixel array
+ /// The maximium number of bits/code.
+ ///
+ private const int MaxBits = 12;
+
+ ///
+ /// Should NEVER generate this code.
+ ///
+ private const int MaxMaxCode = 1 << MaxBits;
+
+ ///
+ /// The working pixel array.
///
private readonly byte[] pixelArray;
@@ -84,42 +84,19 @@ namespace SixLabors.ImageSharp.Formats.Gif
private readonly byte[] accumulators = new byte[256];
///
- /// A value indicating whether this instance of the given entity has been disposed.
+ /// The current position within the pixelArray.
///
- /// if this instance has been disposed; otherwise, .
- ///
- /// If the entity is disposed, it must not be disposed a second
- /// time. The isDisposed field is set the first time the entity
- /// is disposed. If the isDisposed field is true, then the Dispose()
- /// method will not dispose again. This help not to prolong the entity's
- /// life in the Garbage Collector.
- ///
- private bool isDisposed;
-
- ///
- /// The current pixel
- ///
- private int currentPixel;
+ private int position;
///
/// Number of bits/code
///
private int bitCount;
- ///
- /// User settable max # bits/code
- ///
- private int maxbits = Bits;
-
///
/// maximum code, given bitCount
///
- private int maxcode;
-
- ///
- /// should NEVER generate this code
- ///
- private int maxmaxcode = 1 << Bits;
+ private int maxCode;
///
/// For dynamic table sizing
@@ -212,7 +189,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
// Write "initial code size" byte
stream.WriteByte((byte)this.initialCodeSize);
- this.currentPixel = 0;
+ this.position = 0;
// Compress and write the pixel data
this.Compress(this.initialCodeSize + 1, stream);
@@ -221,15 +198,8 @@ namespace SixLabors.ImageSharp.Formats.Gif
stream.WriteByte(GifConstants.Terminator);
}
- ///
- public void Dispose()
- {
- // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
- this.Dispose(true);
- }
-
///
- /// Gets the maximum code value
+ /// Gets the maximum code value.
///
/// The number of bits
/// See
@@ -257,7 +227,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
}
///
- /// Table clear for block compress
+ /// Table clear for block compress.
///
/// The output stream.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -292,13 +262,13 @@ namespace SixLabors.ImageSharp.Formats.Gif
int hsizeReg;
int hshift;
- // Set up the globals: globalInitialBits - initial number of bits
+ // Set up the globals: globalInitialBits - initial number of bits
this.globalInitialBits = intialBits;
// Set up the necessary values
this.clearFlag = false;
this.bitCount = this.globalInitialBits;
- this.maxcode = GetMaxcode(this.bitCount);
+ this.maxCode = GetMaxcode(this.bitCount);
this.clearCode = 1 << (intialBits - 1);
this.eofCode = this.clearCode + 1;
@@ -326,9 +296,11 @@ namespace SixLabors.ImageSharp.Formats.Gif
ref int hashTableRef = ref MemoryMarshal.GetReference(this.hashTable.Span);
ref int codeTableRef = ref MemoryMarshal.GetReference(this.codeTable.Span);
- while ((c = this.NextPixel()) != Eof)
+ while (this.position < this.pixelArray.Length)
{
- fcode = (c << this.maxbits) + ent;
+ c = this.NextPixel();
+
+ fcode = (c << MaxBits) + ent;
int i = (c << hshift) ^ ent /* = 0 */;
if (Unsafe.Add(ref hashTableRef, i) == fcode)
@@ -369,7 +341,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
this.Output(ent, stream);
ent = c;
- if (this.freeEntry < this.maxmaxcode)
+ if (this.freeEntry < MaxMaxCode)
{
Unsafe.Add(ref codeTableRef, i) = this.freeEntry++; // code -> hashtable
Unsafe.Add(ref hashTableRef, i) = fcode;
@@ -387,7 +359,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
}
///
- /// Flush the packet to disk, and reset the accumulator.
+ /// Flush the packet to disk and reset the accumulator.
///
/// The output stream.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -399,20 +371,15 @@ namespace SixLabors.ImageSharp.Formats.Gif
}
///
- /// Return the next pixel from the image
+ /// Reads the next pixel from the image.
///
///
/// The
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
private int NextPixel()
{
- if (this.currentPixel == this.pixelArray.Length)
- {
- return Eof;
- }
-
- this.currentPixel++;
- return this.pixelArray[this.currentPixel - 1] & 0xff;
+ return this.pixelArray[this.position++] & 0xff;
}
///
@@ -445,18 +412,18 @@ namespace SixLabors.ImageSharp.Formats.Gif
// If the next entry is going to be too big for the code size,
// then increase it, if possible.
- if (this.freeEntry > this.maxcode || this.clearFlag)
+ if (this.freeEntry > this.maxCode || this.clearFlag)
{
if (this.clearFlag)
{
- this.maxcode = GetMaxcode(this.bitCount = this.globalInitialBits);
+ this.maxCode = GetMaxcode(this.bitCount = this.globalInitialBits);
this.clearFlag = false;
}
else
{
++this.bitCount;
- this.maxcode = this.bitCount == this.maxbits
- ? this.maxmaxcode
+ this.maxCode = this.bitCount == MaxBits
+ ? MaxMaxCode
: GetMaxcode(this.bitCount);
}
}
@@ -478,24 +445,11 @@ namespace SixLabors.ImageSharp.Formats.Gif
}
}
- ///
- /// Disposes the object and frees resources for the Garbage Collector.
- ///
- /// If true, the object gets disposed.
- private void Dispose(bool disposing)
+ ///
+ public void Dispose()
{
- if (this.isDisposed)
- {
- return;
- }
-
- if (disposing)
- {
- this.hashTable?.Dispose();
- this.codeTable?.Dispose();
- }
-
- this.isDisposed = true;
+ this.hashTable?.Dispose();
+ this.codeTable?.Dispose();
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Gif/PackedField.cs b/src/ImageSharp/Formats/Gif/PackedField.cs
deleted file mode 100644
index 0d3b1539c..000000000
--- a/src/ImageSharp/Formats/Gif/PackedField.cs
+++ /dev/null
@@ -1,177 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Diagnostics;
-using System.Runtime.CompilerServices;
-
-namespace SixLabors.ImageSharp.Formats.Gif
-{
- ///
- /// Represents a byte of data in a GIF data stream which contains a number
- /// of data items.
- ///
- internal readonly struct PackedField : IEquatable
- {
- ///
- /// The individual bits representing the packed byte.
- ///
- private static readonly bool[] Bits = new bool[8];
-
- ///
- /// Gets the byte which represents the data items held in this instance.
- ///
- public byte Byte
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get
- {
- int returnValue = 0;
- int bitShift = 7;
- foreach (bool bit in Bits)
- {
- int bitValue;
- if (bit)
- {
- bitValue = 1 << bitShift;
- }
- else
- {
- bitValue = 0;
- }
-
- returnValue |= bitValue;
- bitShift--;
- }
-
- return Convert.ToByte(returnValue & 0xFF);
- }
- }
-
- ///
- /// Returns a new with the bits in the packed fields to
- /// the corresponding bits from the supplied byte.
- ///
- /// The value to pack.
- /// The
- public static PackedField FromInt(byte value)
- {
- PackedField packed = default;
- packed.SetBits(0, 8, value);
- return packed;
- }
-
- ///
- /// Sets the specified bit within the packed fields to the supplied
- /// value.
- ///
- ///
- /// The zero-based index within the packed fields of the bit to set.
- ///
- ///
- /// The value to set the bit to.
- ///
- public void SetBit(int index, bool valueToSet)
- {
- DebugGuard.MustBeBetweenOrEqualTo(index, 0, 7, nameof(index));
- Bits[index] = valueToSet;
- }
-
- ///
- /// Sets the specified bits within the packed fields to the supplied
- /// value.
- ///
- /// The zero-based index within the packed fields of the first bit to set.
- /// The number of bits to set.
- /// The value to set the bits to.
- public void SetBits(int startIndex, int length, int valueToSet)
- {
- DebugGuard.MustBeBetweenOrEqualTo(startIndex, 0, 7, nameof(startIndex));
- DebugCheckLength(startIndex, length);
-
- int bitShift = length - 1;
- for (int i = startIndex; i < startIndex + length; i++)
- {
- int bitValueIfSet = 1 << bitShift;
- int bitValue = valueToSet & bitValueIfSet;
- int bitIsSet = bitValue >> bitShift;
- Bits[i] = bitIsSet == 1;
- bitShift--;
- }
- }
-
- ///
- /// Gets the value of the specified bit within the byte.
- ///
- /// The zero-based index of the bit to get.
- ///
- /// The value of the specified bit within the byte.
- ///
- public bool GetBit(int index)
- {
- DebugGuard.MustBeBetweenOrEqualTo(index, 0, 7, nameof(index));
- return Bits[index];
- }
-
- ///
- /// Gets the value of the specified bits within the byte.
- ///
- /// The zero-based index of the first bit to get.
- /// The number of bits to get.
- ///
- /// The value of the specified bits within the byte.
- ///
- public int GetBits(int startIndex, int length)
- {
- DebugGuard.MustBeBetweenOrEqualTo(startIndex, 1, 8, nameof(startIndex));
- DebugCheckLength(startIndex, length);
-
- int returnValue = 0;
- int bitShift = length - 1;
- for (int i = startIndex; i < startIndex + length; i++)
- {
- int bitValue = (Bits[i] ? 1 : 0) << bitShift;
- returnValue += bitValue;
- bitShift--;
- }
-
- return returnValue;
- }
-
- ///
- public override bool Equals(object obj)
- {
- return obj is PackedField other && this.Equals(other);
- }
-
- ///
- public bool Equals(PackedField other)
- {
- return this.Byte.Equals(other.Byte);
- }
-
- ///
- public override string ToString()
- {
- return $"PackedField [ Byte={this.Byte} ]";
- }
-
- ///
- public override int GetHashCode()
- {
- return this.Byte.GetHashCode();
- }
-
- [Conditional("DEBUG")]
- private static void DebugCheckLength(int startIndex, int length)
- {
- if (length < 1 || startIndex + length > 8)
- {
- string message = "Length must be greater than zero and the sum of length and start index must be less than 8. "
- + $"Supplied length: {length}. Supplied start index: {startIndex}";
-
- throw new ArgumentOutOfRangeException(nameof(length), message);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Gif/Sections/GifGraphicControlExtension.cs b/src/ImageSharp/Formats/Gif/Sections/GifGraphicControlExtension.cs
new file mode 100644
index 000000000..7ec5f2030
--- /dev/null
+++ b/src/ImageSharp/Formats/Gif/Sections/GifGraphicControlExtension.cs
@@ -0,0 +1,106 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace SixLabors.ImageSharp.Formats.Gif
+{
+ ///
+ /// The Graphic Control Extension contains parameters used when
+ /// processing a graphic rendering block.
+ ///
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal readonly struct GifGraphicControlExtension : IGifExtension
+ {
+ public GifGraphicControlExtension(
+ byte packed,
+ ushort delayTime,
+ byte transparencyIndex)
+ {
+ this.BlockSize = 4;
+ this.Packed = packed;
+ this.DelayTime = delayTime;
+ this.TransparencyIndex = transparencyIndex;
+ }
+
+ ///
+ /// Gets the size of the block.
+ ///
+ public byte BlockSize { get; }
+
+ ///
+ /// Gets the packed disposalMethod and transparencyFlag value.
+ ///
+ public byte Packed { get; }
+
+ ///
+ /// Gets the delay time in of hundredths (1/100) of a second
+ /// to wait before continuing with the processing of the Data Stream.
+ /// The clock starts ticking immediately after the graphic is rendered.
+ ///
+ public ushort DelayTime { get; }
+
+ ///
+ /// Gets the transparency index.
+ /// The Transparency Index is such that when encountered, the corresponding pixel
+ /// of the display device is not modified and processing goes on to the next pixel.
+ ///
+ public byte TransparencyIndex { get; }
+
+ ///
+ /// Gets the disposal method which indicates the way in which the
+ /// graphic is to be treated after being displayed.
+ ///
+ public DisposalMethod DisposalMethod => (DisposalMethod)((this.Packed & 0x1C) >> 2);
+
+ ///
+ /// Gets a value indicating whether transparency flag is to be set.
+ /// This indicates whether a transparency index is given in the Transparent Index field.
+ ///
+ public bool TransparencyFlag => (this.Packed & 0x01) == 1;
+
+ byte IGifExtension.Label => GifConstants.GraphicControlLabel;
+
+ public int WriteTo(Span buffer)
+ {
+ ref GifGraphicControlExtension dest = ref Unsafe.As(ref MemoryMarshal.GetReference(buffer));
+
+ dest = this;
+
+ return 5;
+ }
+
+ public static GifGraphicControlExtension Parse(ReadOnlySpan buffer)
+ {
+ return MemoryMarshal.Cast(buffer)[0];
+ }
+
+ public static byte GetPackedValue(DisposalMethod disposalMethod, bool userInputFlag = false, bool transparencyFlag = false)
+ {
+ /*
+ Reserved | 3 Bits
+ Disposal Method | 3 Bits
+ User Input Flag | 1 Bit
+ Transparent Color Flag | 1 Bit
+ */
+
+ byte value = 0;
+
+ value |= (byte)((int)disposalMethod << 2);
+
+ if (userInputFlag)
+ {
+ value |= 1 << 1;
+ }
+
+ if (transparencyFlag)
+ {
+ value |= 1;
+ }
+
+ return value;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Gif/Sections/GifGraphicsControlExtension.cs b/src/ImageSharp/Formats/Gif/Sections/GifGraphicsControlExtension.cs
deleted file mode 100644
index 8cdd309d3..000000000
--- a/src/ImageSharp/Formats/Gif/Sections/GifGraphicsControlExtension.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-namespace SixLabors.ImageSharp.Formats.Gif
-{
- ///
- /// The Graphic Control Extension contains parameters used when
- /// processing a graphic rendering block.
- ///
- internal sealed class GifGraphicsControlExtension
- {
- ///
- /// Gets or sets the disposal method which indicates the way in which the
- /// graphic is to be treated after being displayed.
- ///
- public DisposalMethod DisposalMethod { get; set; }
-
- ///
- /// Gets or sets a value indicating whether transparency flag is to be set.
- /// This indicates whether a transparency index is given in the Transparent Index field.
- /// (This field is the least significant bit of the byte.)
- ///
- public bool TransparencyFlag { get; set; }
-
- ///
- /// Gets or sets the transparency index.
- /// The Transparency Index is such that when encountered, the corresponding pixel
- /// of the display device is not modified and processing goes on to the next pixel.
- ///
- public byte TransparencyIndex { get; set; }
-
- ///
- /// Gets or sets the delay time.
- /// If not 0, this field specifies the number of hundredths (1/100) of a second to
- /// wait before continuing with the processing of the Data Stream.
- /// The clock starts ticking immediately after the graphic is rendered.
- ///
- public int DelayTime { get; set; }
- }
-}
diff --git a/src/ImageSharp/Formats/Gif/Sections/GifImageDescriptor.cs b/src/ImageSharp/Formats/Gif/Sections/GifImageDescriptor.cs
index 2ed9e4747..c5360729e 100644
--- a/src/ImageSharp/Formats/Gif/Sections/GifImageDescriptor.cs
+++ b/src/ImageSharp/Formats/Gif/Sections/GifImageDescriptor.cs
@@ -1,6 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
namespace SixLabors.ImageSharp.Formats.Gif
{
///
@@ -9,49 +13,104 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// Each image must fit within the boundaries of the
/// Logical Screen, as defined in the Logical Screen Descriptor.
///
- internal sealed class GifImageDescriptor
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal readonly struct GifImageDescriptor
{
+ public const int Size = 10;
+
+ public GifImageDescriptor(
+ ushort left,
+ ushort top,
+ ushort width,
+ ushort height,
+ byte packed)
+ {
+ this.Left = left;
+ this.Top = top;
+ this.Width = width;
+ this.Height = height;
+ this.Packed = packed;
+ }
+
///
- /// Gets or sets the column number, in pixels, of the left edge of the image,
+ /// Gets the column number, in pixels, of the left edge of the image,
/// with respect to the left edge of the Logical Screen.
/// Leftmost column of the Logical Screen is 0.
///
- public short Left { get; set; }
+ public ushort Left { get; }
///
- /// Gets or sets the row number, in pixels, of the top edge of the image with
+ /// Gets the row number, in pixels, of the top edge of the image with
/// respect to the top edge of the Logical Screen.
/// Top row of the Logical Screen is 0.
///
- public short Top { get; set; }
+ public ushort Top { get; }
///
- /// Gets or sets the width of the image in pixels.
+ /// Gets the width of the image in pixels.
///
- public short Width { get; set; }
+ public ushort Width { get; }
///
- /// Gets or sets the height of the image in pixels.
+ /// Gets the height of the image in pixels.
///
- public short Height { get; set; }
+ public ushort Height { get; }
///
- /// Gets or sets a value indicating whether the presence of a Local Color Table immediately
- /// follows this Image Descriptor.
+ /// Gets the packed value of localColorTableFlag, interlaceFlag, sortFlag, and localColorTableSize.
///
- public bool LocalColorTableFlag { get; set; }
+ public byte Packed { get; }
- ///
- /// Gets or sets the local color table size.
- /// If the Local Color Table Flag is set to 1, the value in this field
- /// is used to calculate the number of bytes contained in the Local Color Table.
- ///
- public int LocalColorTableSize { get; set; }
+ public bool LocalColorTableFlag => ((this.Packed & 0x80) >> 7) == 1;
- ///
- /// Gets or sets a value indicating whether the image is to be interlaced.
- /// An image is interlaced in a four-pass interlace pattern.
- ///
- public bool InterlaceFlag { get; set; }
+ public int LocalColorTableSize => 2 << (this.Packed & 0x07);
+
+ public bool InterlaceFlag => ((this.Packed & 0x40) >> 6) == 1;
+
+ public void WriteTo(Span buffer)
+ {
+ buffer[0] = GifConstants.ImageDescriptorLabel;
+
+ ref GifImageDescriptor dest = ref Unsafe.As(ref MemoryMarshal.GetReference(buffer.Slice(1)));
+
+ dest = this;
+ }
+
+ public static GifImageDescriptor Parse(ReadOnlySpan buffer)
+ {
+ return MemoryMarshal.Cast(buffer)[0];
+ }
+
+ public static byte GetPackedValue(bool localColorTableFlag, bool interfaceFlag, bool sortFlag, byte localColorTableSize)
+ {
+ /*
+ Local Color Table Flag | 1 Bit
+ Interlace Flag | 1 Bit
+ Sort Flag | 1 Bit
+ Reserved | 2 Bits
+ Size of Local Color Table | 3 Bits
+ */
+
+ byte value = 0;
+
+ if (localColorTableFlag)
+ {
+ value |= 1 << 7;
+ }
+
+ if (interfaceFlag)
+ {
+ value |= 1 << 6;
+ }
+
+ if (sortFlag)
+ {
+ value |= 1 << 5;
+ }
+
+ value |= (byte)(localColorTableSize - 1);
+
+ return value;
+ }
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Gif/Sections/GifLogicalScreenDescriptor.cs b/src/ImageSharp/Formats/Gif/Sections/GifLogicalScreenDescriptor.cs
index 05f232a4b..1cfec4763 100644
--- a/src/ImageSharp/Formats/Gif/Sections/GifLogicalScreenDescriptor.cs
+++ b/src/ImageSharp/Formats/Gif/Sections/GifLogicalScreenDescriptor.cs
@@ -1,6 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
namespace SixLabors.ImageSharp.Formats.Gif
{
///
@@ -8,51 +12,122 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// necessary to define the area of the display device
/// within which the images will be rendered
///
- internal sealed class GifLogicalScreenDescriptor
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
+ internal readonly struct GifLogicalScreenDescriptor
{
+ public const int Size = 7;
+
+ public GifLogicalScreenDescriptor(
+ ushort width,
+ ushort height,
+ byte packed,
+ byte backgroundColorIndex,
+ byte pixelAspectRatio = 0)
+ {
+ this.Width = width;
+ this.Height = height;
+ this.Packed = packed;
+ this.BackgroundColorIndex = backgroundColorIndex;
+ this.PixelAspectRatio = pixelAspectRatio;
+ }
+
///
- /// Gets or sets the width, in pixels, of the Logical Screen where the images will
+ /// Gets the width, in pixels, of the Logical Screen where the images will
/// be rendered in the displaying device.
///
- public short Width { get; set; }
+ public ushort Width { get; }
///
- /// Gets or sets the height, in pixels, of the Logical Screen where the images will be
+ /// Gets the height, in pixels, of the Logical Screen where the images will be
/// rendered in the displaying device.
///
- public short Height { get; set; }
+ public ushort Height { get; }
///
- /// Gets or sets the color depth, in number of bits per pixel.
+ /// Gets the packed value consisting of:
+ /// globalColorTableFlag, colorResolution, sortFlag, and sizeOfGlobalColorTable.
///
- public int BitsPerPixel { get; set; }
+ public byte Packed { get; }
///
- /// Gets or sets the index at the Global Color Table for the Background Color.
+ /// Gets the index at the Global Color Table for the Background Color.
/// The Background Color is the color used for those
/// pixels on the screen that are not covered by an image.
///
- public byte BackgroundColorIndex { get; set; }
+ public byte BackgroundColorIndex { get; }
///
- /// Gets or sets the pixel aspect ratio. Default to 0.
+ /// Gets the pixel aspect ratio.
///
- public byte PixelAspectRatio { get; set; }
+ public byte PixelAspectRatio { get; }
///
- /// Gets or sets a value indicating whether a flag denoting the presence of a Global Color Table
+ /// Gets a value indicating whether a flag denoting the presence of a Global Color Table
/// should be set.
- /// If the flag is set, the Global Color Table will immediately
- /// follow the Logical Screen Descriptor.
+ /// If the flag is set, the Global Color Table will included after
+ /// the Logical Screen Descriptor.
///
- public bool GlobalColorTableFlag { get; set; }
+ public bool GlobalColorTableFlag => ((this.Packed & 0x80) >> 7) == 1;
///
- /// Gets or sets the global color table size.
- /// If the Global Color Table Flag is set to 1,
+ /// Gets the global color table size.
+ /// If the Global Color Table Flag is set,
/// the value in this field is used to calculate the number of
/// bytes contained in the Global Color Table.
///
- public int GlobalColorTableSize { get; set; }
+ public int GlobalColorTableSize => 2 << (this.Packed & 0x07);
+
+ ///
+ /// Gets the color depth, in number of bits per pixel.
+ /// The lowest 3 packed bits represent the bit depth minus 1.
+ ///
+ public int BitsPerPixel => (this.Packed & 0x07) + 1;
+
+ public void WriteTo(Span buffer)
+ {
+ ref GifLogicalScreenDescriptor dest = ref Unsafe.As(ref MemoryMarshal.GetReference(buffer));
+
+ dest = this;
+ }
+
+ public static GifLogicalScreenDescriptor Parse(ReadOnlySpan buffer)
+ {
+ GifLogicalScreenDescriptor result = MemoryMarshal.Cast(buffer)[0];
+
+ if (result.GlobalColorTableSize > 255 * 4)
+ {
+ throw new ImageFormatException($"Invalid gif colormap size '{result.GlobalColorTableSize}'");
+ }
+
+ return result;
+ }
+
+ public static byte GetPackedValue(bool globalColorTableFlag, int colorResolution, bool sortFlag, int globalColorTableSize)
+ {
+ /*
+ Global Color Table Flag | 1 Bit
+ Color Resolution | 3 Bits
+ Sort Flag | 1 Bit
+ Size of Global Color Table | 3 Bits
+ */
+
+ byte value = 0;
+
+ if (globalColorTableFlag)
+ {
+ value |= 1 << 7;
+ }
+
+ value |= (byte)(colorResolution << 4);
+
+ if (sortFlag)
+ {
+ value |= 1 << 3;
+ }
+
+ value |= (byte)globalColorTableSize;
+
+ return value;
+ }
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Gif/Sections/IGifExtension.cs b/src/ImageSharp/Formats/Gif/Sections/IGifExtension.cs
new file mode 100644
index 000000000..2fdc233b0
--- /dev/null
+++ b/src/ImageSharp/Formats/Gif/Sections/IGifExtension.cs
@@ -0,0 +1,22 @@
+using System;
+
+namespace SixLabors.ImageSharp.Formats.Gif
+{
+ ///
+ /// A base interface for GIF extensions.
+ ///
+ public interface IGifExtension
+ {
+ ///
+ /// Gets the label identifying the extensions.
+ ///
+ byte Label { get; }
+
+ ///
+ /// Writes the extension data to the buffer.
+ ///
+ /// The buffer to write the extension to.
+ /// The number of bytes written to the buffer.
+ int WriteTo(Span buffer);
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs b/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs
index 3f71c498b..53297ab55 100644
--- a/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs
+++ b/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs
@@ -353,13 +353,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
/// Qt pointer
/// Unzig pointer
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static unsafe void DequantizeBlock(Block8x8F* blockPtr, Block8x8F* qtPtr, int* unzigPtr)
+ public static unsafe void DequantizeBlock(Block8x8F* blockPtr, Block8x8F* qtPtr, byte* unzigPtr)
{
float* b = (float*)blockPtr;
float* qtp = (float*)qtPtr;
for (int qtIndex = 0; qtIndex < Size; qtIndex++)
{
- int blockIndex = unzigPtr[qtIndex];
+ byte blockIndex = unzigPtr[qtIndex];
float* unzigPos = b + blockIndex;
float val = *unzigPos;
@@ -381,7 +381,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
Block8x8F* block,
Block8x8F* dest,
Block8x8F* qt,
- int* unzigPtr)
+ byte* unzigPtr)
{
float* s = (float*)block;
float* d = (float*)dest;
diff --git a/src/ImageSharp/Formats/Jpeg/Common/Decoder/ComponentUtils.cs b/src/ImageSharp/Formats/Jpeg/Common/Decoder/ComponentUtils.cs
deleted file mode 100644
index da97f9e2a..000000000
--- a/src/ImageSharp/Formats/Jpeg/Common/Decoder/ComponentUtils.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
-{
- ///
- /// Various utilities for .
- ///
- internal static class ComponentUtils
- {
- ///
- /// Gets a reference to the at the given row and column index from
- ///
- public static ref Block8x8 GetBlockReference(this IJpegComponent component, int bx, int by)
- {
- return ref component.SpectralBlocks[bx, by];
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/Common/Decoder/IJpegComponent.cs b/src/ImageSharp/Formats/Jpeg/Common/Decoder/IJpegComponent.cs
index 4109fc10e..de9f75dc1 100644
--- a/src/ImageSharp/Formats/Jpeg/Common/Decoder/IJpegComponent.cs
+++ b/src/ImageSharp/Formats/Jpeg/Common/Decoder/IJpegComponent.cs
@@ -42,5 +42,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
/// We need to apply IDCT and dequantiazition to transform them into color-space blocks.
///
Buffer2D SpectralBlocks { get; }
+
+ ///
+ /// Gets a reference to the at the given row and column index from
+ ///
+ /// The column
+ /// The row
+ /// The
+ ref Block8x8 GetBlockReference(int column, int row);
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegBlockPostProcessor.cs b/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegBlockPostProcessor.cs
index 5e8e8fa2c..2f59bcb82 100644
--- a/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegBlockPostProcessor.cs
+++ b/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegBlockPostProcessor.cs
@@ -47,9 +47,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
this.DequantiazationTable = ZigZag.CreateDequantizationTable(ref decoder.QuantizationTables[qtIndex]);
this.subSamplingDivisors = component.SubSamplingDivisors;
- this.SourceBlock = default(Block8x8F);
- this.WorkspaceBlock1 = default(Block8x8F);
- this.WorkspaceBlock2 = default(Block8x8F);
+ this.SourceBlock = default;
+ this.WorkspaceBlock1 = default;
+ this.WorkspaceBlock2 = default;
}
///
diff --git a/src/ImageSharp/Formats/Jpeg/Common/Decoder/ProfileResolver.cs b/src/ImageSharp/Formats/Jpeg/Common/Decoder/ProfileResolver.cs
index 7ea0f9215..2030ad71b 100644
--- a/src/ImageSharp/Formats/Jpeg/Common/Decoder/ProfileResolver.cs
+++ b/src/ImageSharp/Formats/Jpeg/Common/Decoder/ProfileResolver.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Text;
namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
{
@@ -13,22 +14,22 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
///
/// Describes the EXIF specific markers
///
- public static readonly byte[] JFifMarker = ToAsciiBytes("JFIF\0");
+ public static readonly byte[] JFifMarker = Encoding.UTF8.GetBytes("JFIF\0");
///
/// Describes the EXIF specific markers
///
- public static readonly byte[] IccMarker = ToAsciiBytes("ICC_PROFILE\0");
+ public static readonly byte[] IccMarker = Encoding.UTF8.GetBytes("ICC_PROFILE\0");
///
/// Describes the ICC specific markers
///
- public static readonly byte[] ExifMarker = ToAsciiBytes("Exif\0\0");
+ public static readonly byte[] ExifMarker = Encoding.UTF8.GetBytes("Exif\0\0");
///
/// Describes Adobe specific markers
///
- public static readonly byte[] AdobeMarker = ToAsciiBytes("Adobe");
+ public static readonly byte[] AdobeMarker = Encoding.UTF8.GetBytes("Adobe");
///
/// Returns a value indicating whether the passed bytes are a match to the profile identifer
@@ -41,19 +42,5 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
return bytesToCheck.Length >= profileIdentifier.Length
&& bytesToCheck.Slice(0, profileIdentifier.Length).SequenceEqual(profileIdentifier);
}
-
- // No Encoding.ASCII nor Linq.Select on NetStandard 1.1
- private static byte[] ToAsciiBytes(string str)
- {
- int length = str.Length;
- byte[] bytes = new byte[length];
- char[] chars = str.ToCharArray();
- for (int i = 0; i < length; i++)
- {
- bytes[i] = (byte)chars[i];
- }
-
- return bytes;
- }
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/Common/ZigZag.cs b/src/ImageSharp/Formats/Jpeg/Common/ZigZag.cs
index 18270f5ba..cb035a8d3 100644
--- a/src/ImageSharp/Formats/Jpeg/Common/ZigZag.cs
+++ b/src/ImageSharp/Formats/Jpeg/Common/ZigZag.cs
@@ -1,6 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace SixLabors.ImageSharp.Formats.Jpeg.Common
@@ -11,25 +12,52 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
/// unzig[3] is the column and row of the fourth element in zigzag order. The
/// value is 16, which means first column (16%8 == 0) and third row (16/8 == 2).
///
+ [StructLayout(LayoutKind.Sequential)]
internal unsafe struct ZigZag
{
///
/// Copy of in a value type
///
- public fixed int Data[64];
+ public fixed byte Data[64];
///
/// Unzig maps from the zigzag ordering to the natural ordering. For example,
/// unzig[3] is the column and row of the fourth element in zigzag order. The
/// value is 16, which means first column (16%8 == 0) and third row (16/8 == 2).
///
- private static readonly int[] Unzig =
+ private static readonly byte[] Unzig =
+ {
+ 0,
+ 1, 8,
+ 16, 9, 2,
+ 3, 10, 17, 24,
+ 32, 25, 18, 11, 4,
+ 5, 12, 19, 26, 33, 40,
+ 48, 41, 34, 27, 20, 13, 6,
+ 7, 14, 21, 28, 35, 42, 49, 56,
+ 57, 50, 43, 36, 29, 22, 15,
+ 23, 30, 37, 44, 51, 58,
+ 59, 52, 45, 38, 31,
+ 39, 46, 53, 60,
+ 61, 54, 47,
+ 55, 62,
+ 63
+ };
+
+ ///
+ /// Returns the value at the given index
+ ///
+ /// The index
+ /// The
+ public byte this[int idx]
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
{
- 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33,
- 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50,
- 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46,
- 53, 60, 61, 54, 47, 55, 62, 63,
- };
+ ref byte self = ref Unsafe.As(ref this);
+ return Unsafe.Add(ref self, idx);
+ }
+ }
///
/// Creates and fills an instance of with Jpeg unzig indices
@@ -37,8 +65,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
/// The new instance
public static ZigZag CreateUnzigTable()
{
- ZigZag result = default(ZigZag);
- int* unzigPtr = result.Data;
+ ZigZag result = default;
+ byte* unzigPtr = result.Data;
Marshal.Copy(Unzig, 0, (IntPtr)unzigPtr, 64);
return result;
}
@@ -48,7 +76,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
///
public static Block8x8F CreateDequantizationTable(ref Block8x8F qt)
{
- Block8x8F result = default(Block8x8F);
+ Block8x8F result = default;
for (int i = 0; i < 64; i++)
{
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigComponent.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigComponent.cs
index e83dd75a5..e2f21bd1c 100644
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigComponent.cs
+++ b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigComponent.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Formats.Jpeg.Common;
using SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder;
using SixLabors.ImageSharp.Memory;
@@ -237,6 +238,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
this.SamplingFactors = new Size(h, v);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public ref Block8x8 GetBlockReference(int column, int row)
+ {
+ return ref this.SpectralBlocks[column, row];
+ }
+
public void Dispose()
{
this.SpectralBlocks.Dispose();
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.DataPointers.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.DataPointers.cs
index 0098b4a4e..0207280e3 100644
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.DataPointers.cs
+++ b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegScanDecoder.DataPointers.cs
@@ -21,9 +21,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
public Block8x8* Block;
///
- /// Pointer to as int*
+ /// Pointer to as byte*
///
- public int* Unzig;
+ public byte* Unzig;
///
/// Pointer to as Scan*
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/JpegEncoderCore.cs
index ba40ef72b..4fbb20ee8 100644
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/JpegEncoderCore.cs
+++ b/src/ImageSharp/Formats/Jpeg/GolangPort/JpegEncoderCore.cs
@@ -489,7 +489,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
Block8x8F* tempDest1,
Block8x8F* tempDest2,
Block8x8F* quant,
- int* unzigPtr)
+ byte* unzigPtr)
{
FastFloatingPointDCT.TransformFDCT(ref *src, ref *tempDest1, ref *tempDest2);
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoder.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoder.cs
index ecebe9480..bf2f64b34 100644
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoder.cs
+++ b/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoder.cs
@@ -31,7 +31,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
///
public IImageInfo Identify(Configuration configuration, Stream stream)
{
- Guard.NotNull(stream, "stream");
+ Guard.NotNull(stream, nameof(stream));
using (var decoder = new OrigJpegDecoderCore(configuration, this))
{
diff --git a/src/ImageSharp/Formats/Jpeg/IJpegDecoderOptions.cs b/src/ImageSharp/Formats/Jpeg/IJpegDecoderOptions.cs
index 880a7f7a3..ef7b377d2 100644
--- a/src/ImageSharp/Formats/Jpeg/IJpegDecoderOptions.cs
+++ b/src/ImageSharp/Formats/Jpeg/IJpegDecoderOptions.cs
@@ -1,11 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using System;
-using System.Collections.Generic;
-using System.IO;
-using SixLabors.ImageSharp.PixelFormats;
-
namespace SixLabors.ImageSharp.Formats.Jpeg
{
///
@@ -18,4 +13,4 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
///
bool IgnoreMetadata { get; }
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/IJpegEncoderOptions.cs b/src/ImageSharp/Formats/Jpeg/IJpegEncoderOptions.cs
index a84652cef..4076b7da8 100644
--- a/src/ImageSharp/Formats/Jpeg/IJpegEncoderOptions.cs
+++ b/src/ImageSharp/Formats/Jpeg/IJpegEncoderOptions.cs
@@ -1,11 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using System;
-using System.Collections.Generic;
-using System.IO;
-using SixLabors.ImageSharp.PixelFormats;
-
namespace SixLabors.ImageSharp.Formats.Jpeg
{
///
@@ -31,4 +26,4 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// The subsample ratio of the jpg image.
JpegSubsample? Subsample { get; }
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs b/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs
index d3f95e40c..1d3be063d 100644
--- a/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs
+++ b/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs
@@ -1,10 +1,8 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using System;
using System.IO;
using SixLabors.ImageSharp.Advanced;
-using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.PixelFormats;
diff --git a/src/ImageSharp/Formats/Jpeg/JpegConfigurationModule.cs b/src/ImageSharp/Formats/Jpeg/JpegConfigurationModule.cs
index 23cef5927..c3bf801ac 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegConfigurationModule.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegConfigurationModule.cs
@@ -17,4 +17,4 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
config.ImageFormatsManager.AddImageFormatDetector(new JpegImageFormatDetector());
}
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/JpegImageFormatDetector.cs b/src/ImageSharp/Formats/Jpeg/JpegImageFormatDetector.cs
index d888986f3..e25957efc 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegImageFormatDetector.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegImageFormatDetector.cs
@@ -16,12 +16,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
///
public IImageFormat DetectFormat(ReadOnlySpan header)
{
- if (this.IsSupportedFileFormat(header))
- {
- return ImageFormats.Jpeg;
- }
-
- return null;
+ return this.IsSupportedFileFormat(header) ? ImageFormats.Jpeg : null;
}
private bool IsSupportedFileFormat(ReadOnlySpan header)
@@ -35,36 +30,24 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
///
/// The bytes representing the file header.
/// The
- private bool IsJfif(ReadOnlySpan header)
- {
- // TODO: This should be in constants
- bool isJfif =
- header[6] == 0x4A && // J
- header[7] == 0x46 && // F
- header[8] == 0x49 && // I
- header[9] == 0x46 && // F
- header[10] == 0x00;
-
- return isJfif;
- }
+ private bool IsJfif(ReadOnlySpan header) =>
+ header[6] == 0x4A && // J
+ header[7] == 0x46 && // F
+ header[8] == 0x49 && // I
+ header[9] == 0x46 && // F
+ header[10] == 0x00;
///
/// Returns a value indicating whether the given bytes identify EXIF data.
///
/// The bytes representing the file header.
/// The
- private bool IsExif(ReadOnlySpan header)
- {
- // TODO: This should be in constants
- bool isExif =
- header[6] == 0x45 && // E
- header[7] == 0x78 && // X
- header[8] == 0x69 && // I
- header[9] == 0x66 && // F
- header[10] == 0x00;
-
- return isExif;
- }
+ private bool IsExif(ReadOnlySpan header) =>
+ header[6] == 0x45 && // E
+ header[7] == 0x78 && // X
+ header[8] == 0x69 && // I
+ header[9] == 0x66 && // F
+ header[10] == 0x00;
///
/// Returns a value indicating whether the given bytes identify Jpeg data.
@@ -72,14 +55,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
///
/// The bytes representing the file header.
/// The
- private bool IsJpeg(ReadOnlySpan header)
- {
- // TODO: This should be in constants
- bool isJpg =
- header[0] == 0xFF && // 255
- header[1] == 0xD8; // 216
-
- return isJpg;
- }
+ private bool IsJpeg(ReadOnlySpan header) =>
+ header[0] == 0xFF && // 255
+ header[1] == 0xD8; // 216
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedByteBuffer256.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedByteBuffer256.cs
new file mode 100644
index 000000000..5870e3da8
--- /dev/null
+++ b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedByteBuffer256.cs
@@ -0,0 +1,24 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
+{
+ [StructLayout(LayoutKind.Sequential)]
+ internal unsafe struct FixedByteBuffer256
+ {
+ public fixed byte Data[256];
+
+ public byte this[int idx]
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ ref byte self = ref Unsafe.As(ref this);
+ return Unsafe.Add(ref self, idx);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedInt16Buffer18.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedInt16Buffer18.cs
new file mode 100644
index 000000000..20d4b7733
--- /dev/null
+++ b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedInt16Buffer18.cs
@@ -0,0 +1,24 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
+{
+ [StructLayout(LayoutKind.Sequential)]
+ internal unsafe struct FixedInt16Buffer18
+ {
+ public fixed short Data[18];
+
+ public short this[int idx]
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ ref short self = ref Unsafe.As(ref this);
+ return Unsafe.Add(ref self, idx);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedInt16Buffer256.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedInt16Buffer256.cs
new file mode 100644
index 000000000..2c16a918f
--- /dev/null
+++ b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedInt16Buffer256.cs
@@ -0,0 +1,24 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
+{
+ [StructLayout(LayoutKind.Sequential)]
+ internal unsafe struct FixedInt16Buffer256
+ {
+ public fixed short Data[256];
+
+ public short this[int idx]
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ ref short self = ref Unsafe.As(ref this);
+ return Unsafe.Add(ref self, idx);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedInt64Buffer18.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedInt64Buffer18.cs
new file mode 100644
index 000000000..51381cb27
--- /dev/null
+++ b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedInt64Buffer18.cs
@@ -0,0 +1,24 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
+{
+ [StructLayout(LayoutKind.Sequential)]
+ internal unsafe struct FixedInt64Buffer18
+ {
+ public fixed long Data[18];
+
+ public long this[int idx]
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ ref long self = ref Unsafe.As(ref this);
+ return Unsafe.Add(ref self, idx);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsComponent.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsComponent.cs
deleted file mode 100644
index 0742293c7..000000000
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsComponent.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Numerics;
-using SixLabors.ImageSharp.Memory;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
-{
- ///
- /// Represents a component block
- ///
- internal class PdfJsComponent : IDisposable
- {
-#pragma warning disable SA1401
- ///
- /// Gets or sets the output
- ///
- public IBuffer Output;
-
- ///
- /// Gets or sets the scaling factors
- ///
- public Vector2 Scale;
-
- ///
- /// Gets or sets the number of blocks per line
- ///
- public int BlocksPerLine;
-
- ///
- /// Gets or sets the number of blocks per column
- ///
- public int BlocksPerColumn;
-
- ///
- public void Dispose()
- {
- this.Output?.Dispose();
- this.Output = null;
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsComponentBlocks.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsComponentBlocks.cs
deleted file mode 100644
index 86a0c6b31..000000000
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsComponentBlocks.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
-{
- ///
- /// Contains all the decoded component blocks
- ///
- internal sealed class PdfJsComponentBlocks : IDisposable
- {
- ///
- /// Gets or sets the component blocks
- ///
- public PdfJsComponent[] Components { get; set; }
-
- ///
- public void Dispose()
- {
- if (this.Components != null)
- {
- for (int i = 0; i < this.Components.Length; i++)
- {
- this.Components[i].Dispose();
- }
-
- this.Components = null;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsFrameComponent.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsFrameComponent.cs
index 2442c3998..7f50a8529 100644
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsFrameComponent.cs
+++ b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsFrameComponent.cs
@@ -3,6 +3,7 @@
using System;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Formats.Jpeg.Common;
using SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder;
using SixLabors.ImageSharp.Memory;
@@ -16,7 +17,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
internal class PdfJsFrameComponent : IDisposable, IJpegComponent
{
private readonly MemoryManager memoryManager;
-#pragma warning disable SA1401 // Fields should be private
public PdfJsFrameComponent(MemoryManager memoryManager, PdfJsFrame frame, byte id, int horizontalFactor, int verticalFactor, byte quantizationTableIndex, int index)
{
@@ -25,6 +25,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
this.Id = id;
this.HorizontalSamplingFactor = horizontalFactor;
this.VerticalSamplingFactor = verticalFactor;
+ this.SamplingFactors = new Size(this.HorizontalSamplingFactor, this.VerticalSamplingFactor);
this.QuantizationTableIndex = quantizationTableIndex;
this.Index = index;
}
@@ -49,25 +50,23 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
///
public int VerticalSamplingFactor { get; }
- Buffer2D IJpegComponent.SpectralBlocks => throw new NotImplementedException();
+ ///
+ public Buffer2D SpectralBlocks { get; private set; }
- // TODO: Should be derived from PdfJsComponent.Scale
- public Size SubSamplingDivisors => throw new NotImplementedException();
+ ///
+ public Size SubSamplingDivisors { get; private set; }
///
public int QuantizationTableIndex { get; }
- ///
- /// Gets the block data
- ///
- public IBuffer BlockData { get; private set; }
-
///
public int Index { get; }
- public Size SizeInBlocks => new Size(this.WidthInBlocks, this.HeightInBlocks);
+ ///
+ public Size SizeInBlocks { get; private set; }
- public Size SamplingFactors => new Size(this.HorizontalSamplingFactor, this.VerticalSamplingFactor);
+ ///
+ public Size SamplingFactors { get; set; }
///
/// Gets the number of blocks per line
@@ -89,17 +88,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
///
public int ACHuffmanTableId { get; set; }
- internal int BlocksPerLineForMcu { get; private set; }
-
- internal int BlocksPerColumnForMcu { get; private set; }
-
public PdfJsFrame Frame { get; }
///
public void Dispose()
{
- this.BlockData?.Dispose();
- this.BlockData = null;
+ this.SpectralBlocks?.Dispose();
+ this.SpectralBlocks = null;
}
public void Init()
@@ -110,25 +105,43 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
this.HeightInBlocks = (int)MathF.Ceiling(
MathF.Ceiling(this.Frame.Scanlines / 8F) * this.VerticalSamplingFactor / this.Frame.MaxVerticalFactor);
- this.BlocksPerLineForMcu = this.Frame.McusPerLine * this.HorizontalSamplingFactor;
- this.BlocksPerColumnForMcu = this.Frame.McusPerColumn * this.VerticalSamplingFactor;
-
- int blocksBufferSize = 64 * this.BlocksPerColumnForMcu * (this.BlocksPerLineForMcu + 1);
-
- // Pooled. Disposed via frame disposal
- this.BlockData = this.memoryManager.Allocate(blocksBufferSize, true);
+ int blocksPerLineForMcu = this.Frame.McusPerLine * this.HorizontalSamplingFactor;
+ int blocksPerColumnForMcu = this.Frame.McusPerColumn * this.VerticalSamplingFactor;
+ this.SizeInBlocks = new Size(blocksPerLineForMcu, blocksPerColumnForMcu);
+
+ // For 4-component images (either CMYK or YCbCrK), we only support two
+ // hv vectors: [0x11 0x11 0x11 0x11] and [0x22 0x11 0x11 0x22].
+ // Theoretically, 4-component JPEG images could mix and match hv values
+ // but in practice, those two combinations are the only ones in use,
+ // and it simplifies the applyBlack code below if we can assume that:
+ // - for CMYK, the C and K channels have full samples, and if the M
+ // and Y channels subsample, they subsample both horizontally and
+ // vertically.
+ // - for YCbCrK, the Y and K channels have full samples.
+ if (this.Index == 0 || this.Index == 3)
+ {
+ this.SubSamplingDivisors = new Size(1, 1);
+ }
+ else
+ {
+ PdfJsFrameComponent c0 = this.Frame.Components[0];
+ this.SubSamplingDivisors = c0.SamplingFactors.DivideBy(this.SamplingFactors);
+ }
+
+ this.SpectralBlocks = this.memoryManager.Allocate2D(blocksPerColumnForMcu, blocksPerLineForMcu + 1, true);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public int GetBlockBufferOffset(int row, int col)
+ public ref Block8x8 GetBlockReference(int column, int row)
{
- return 64 * (((this.WidthInBlocks + 1) * row) + col);
+ int offset = ((this.WidthInBlocks + 1) * row) + column;
+ return ref Unsafe.Add(ref MemoryMarshal.GetReference(this.SpectralBlocks.Span), offset);
}
- public Span GetBlockBuffer(int row, int col)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public int GetBlockBufferOffset(int row, int col)
{
- int offset = this.GetBlockBufferOffset(row, col);
- return this.BlockData.Span.Slice(offset, 64);
+ return 64 * (((this.WidthInBlocks + 1) * row) + col);
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTable.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTable.cs
index 3c43ba244..875a86263 100644
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTable.cs
+++ b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTable.cs
@@ -3,6 +3,7 @@
using System;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
@@ -10,100 +11,64 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
///
/// Represents a Huffman Table
///
- internal struct PdfJsHuffmanTable : IDisposable
+ [StructLayout(LayoutKind.Sequential)]
+ internal unsafe struct PdfJsHuffmanTable
{
- private BasicArrayBuffer lookahead;
- private BasicArrayBuffer valOffset;
- private BasicArrayBuffer maxcode;
- private IManagedByteBuffer huffval;
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The to use for buffer allocations.
- /// The code lengths
- /// The huffman values
- public PdfJsHuffmanTable(MemoryManager memoryManager, byte[] lengths, byte[] values)
- {
- // TODO: Replace FakeBuffer usages with standard or array orfixed-sized arrays
- this.lookahead = memoryManager.AllocateFake(256);
- this.valOffset = memoryManager.AllocateFake(18);
- this.maxcode = memoryManager.AllocateFake(18);
-
- using (IBuffer huffsize = memoryManager.Allocate(257))
- using (IBuffer huffcode = memoryManager.Allocate(257))
- {
- GenerateSizeTable(lengths, huffsize.Span);
- GenerateCodeTable(huffsize.Span, huffcode.Span);
- GenerateDecoderTables(lengths, huffcode.Span, this.valOffset.Span, this.maxcode.Span);
- GenerateLookaheadTables(lengths, values, this.lookahead.Span);
- }
-
- this.huffval = memoryManager.AllocateManagedByteBuffer(values.Length, true);
- Buffer.BlockCopy(values, 0, this.huffval.Array, 0, values.Length);
-
- this.MaxCode = this.maxcode.Array;
- this.ValOffset = this.valOffset.Array;
- this.HuffVal = this.huffval.Array;
- this.Lookahead = this.lookahead.Array;
- }
-
///
/// Gets the max code array
///
- public long[] MaxCode
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get;
- }
+ public FixedInt64Buffer18 MaxCode;
///
/// Gets the value offset array
///
- public short[] ValOffset
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get;
- }
+ public FixedInt16Buffer18 ValOffset;
///
/// Gets the huffman value array
///
- public byte[] HuffVal
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get;
- }
+ public FixedByteBuffer256 HuffVal;
///
/// Gets the lookahead array
///
- public short[] Lookahead
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get;
- }
+ public FixedInt16Buffer256 Lookahead;
- ///
- public void Dispose()
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// The to use for buffer allocations.
+ /// The code lengths
+ /// The huffman values
+ public PdfJsHuffmanTable(MemoryManager memoryManager, ReadOnlySpan lengths, ReadOnlySpan values)
{
- this.lookahead?.Dispose();
- this.valOffset?.Dispose();
- this.maxcode?.Dispose();
- this.huffval?.Dispose();
-
- this.lookahead = null;
- this.valOffset = null;
- this.maxcode = null;
- this.huffval = null;
+ const int length = 257;
+ using (IBuffer huffsize = memoryManager.Allocate(length))
+ using (IBuffer huffcode = memoryManager.Allocate(length))
+ {
+ ref short huffsizeRef = ref MemoryMarshal.GetReference(huffsize.Span);
+ ref short huffcodeRef = ref MemoryMarshal.GetReference(huffcode.Span);
+
+ GenerateSizeTable(lengths, ref huffsizeRef);
+ GenerateCodeTable(ref huffsizeRef, ref huffcodeRef, length);
+ this.GenerateDecoderTables(lengths, ref huffcodeRef);
+ this.GenerateLookaheadTables(lengths, values, ref huffcodeRef);
+ }
+
+ fixed (byte* huffValRef = this.HuffVal.Data)
+ {
+ var huffValSpan = new Span(huffValRef, 256);
+
+ values.CopyTo(huffValSpan);
+ }
}
///
/// Figure C.1: make table of Huffman code length for each symbol
///
/// The code lengths
- /// The huffman size span
- private static void GenerateSizeTable(byte[] lengths, Span huffsize)
+ /// The huffman size span ref
+ private static void GenerateSizeTable(ReadOnlySpan lengths, ref short huffsizeRef)
{
short index = 0;
for (short l = 1; l <= 16; l++)
@@ -111,29 +76,30 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
byte i = lengths[l];
for (short j = 0; j < i; j++)
{
- huffsize[index] = l;
+ Unsafe.Add(ref huffsizeRef, index) = l;
index++;
}
}
- huffsize[index] = 0;
+ Unsafe.Add(ref huffsizeRef, index) = 0;
}
///
/// Figure C.2: generate the codes themselves
///
- /// The huffman size span
- /// The huffman code span
- private static void GenerateCodeTable(Span huffsize, Span huffcode)
+ /// The huffman size span ref
+ /// The huffman code span ref
+ /// The length of the huffsize span
+ private static void GenerateCodeTable(ref short huffsizeRef, ref short huffcodeRef, int length)
{
short k = 0;
- short si = huffsize[0];
+ short si = huffsizeRef;
short code = 0;
- for (short i = 0; i < huffsize.Length; i++)
+ for (short i = 0; i < length; i++)
{
- while (huffsize[k] == si)
+ while (Unsafe.Add(ref huffsizeRef, k) == si)
{
- huffcode[k] = code;
+ Unsafe.Add(ref huffcodeRef, k) = code;
code++;
k++;
}
@@ -147,30 +113,31 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
/// Figure F.15: generate decoding tables for bit-sequential decoding
///
/// The code lengths
- /// The huffman code span
- /// The value offset span
- /// The max code span
- private static void GenerateDecoderTables(byte[] lengths, Span huffcode, Span valOffset, Span maxcode)
+ /// The huffman code span ref
+ private void GenerateDecoderTables(ReadOnlySpan lengths, ref short huffcodeRef)
{
- short bitcount = 0;
- for (int i = 1; i <= 16; i++)
+ fixed (short* valOffsetRef = this.ValOffset.Data)
+ fixed (long* maxcodeRef = this.MaxCode.Data)
{
- if (lengths[i] != 0)
- {
- // valoffset[l] = huffval[] index of 1st symbol of code length i,
- // minus the minimum code of length i
- valOffset[i] = (short)(bitcount - huffcode[bitcount]);
- bitcount += lengths[i];
- maxcode[i] = huffcode[bitcount - 1]; // maximum code of length i
- }
- else
+ short bitcount = 0;
+ for (int i = 1; i <= 16; i++)
{
- maxcode[i] = -1; // -1 if no codes of this length
+ if (lengths[i] != 0)
+ {
+ // valOffsetRef[l] = huffcodeRef[] index of 1st symbol of code length i, minus the minimum code of length i
+ valOffsetRef[i] = (short)(bitcount - Unsafe.Add(ref huffcodeRef, bitcount));
+ bitcount += lengths[i];
+ maxcodeRef[i] = Unsafe.Add(ref huffcodeRef, bitcount - 1); // maximum code of length i
+ }
+ else
+ {
+ maxcodeRef[i] = -1; // -1 if no codes of this length
+ }
}
- }
- valOffset[17] = 0;
- maxcode[17] = 0xFFFFFL;
+ valOffsetRef[17] = 0;
+ maxcodeRef[17] = 0xFFFFFL;
+ }
}
///
@@ -178,32 +145,33 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
///
/// The code lengths
/// The huffman value array
- /// The lookahead span
- private static void GenerateLookaheadTables(byte[] lengths, byte[] huffval, Span lookahead)
+ /// The huffman code span ref
+ private void GenerateLookaheadTables(ReadOnlySpan lengths, ReadOnlySpan huffval, ref short huffcodeRef)
{
- int x = 0, code = 0;
-
- for (int i = 0; i < 8; i++)
+ // TODO: This generation code matches the libJpeg code but the lookahead table is not actually used yet.
+ // To use it we need to implement fast lookup path in PdfJsScanDecoder.DecodeHuffman
+ // This should yield much faster scan decoding as usually, more than 95% of the Huffman codes
+ // will be 8 or fewer bits long and can be handled without looping.
+ fixed (short* lookaheadRef = this.Lookahead.Data)
{
- code <<= 1;
+ var lookaheadSpan = new Span(lookaheadRef, 256);
- for (int j = 0; j < lengths[i + 1]; j++)
+ lookaheadSpan.Fill(2034); // 9 << 8;
+
+ int p = 0;
+ for (int l = 1; l <= 8; l++)
{
- // The codeLength is 1+i, so shift code by 8-(1+i) to
- // calculate the high bits for every 8-bit sequence
- // whose codeLength's high bits matches code.
- // The high 8 bits of lutValue are the encoded value.
- // The low 8 bits are 1 plus the codeLength.
- byte base2 = (byte)(code << (7 - i));
- short lutValue = (short)((short)(huffval[x] << 8) | (short)(2 + i));
-
- for (int k = 0; k < 1 << (7 - i); k++)
+ for (int i = 1; i <= lengths[l]; i++, p++)
{
- lookahead[base2 | k] = lutValue;
+ // l = current code's length, p = its index in huffcode[] & huffval[].
+ // Generate left-justified code followed by all possible bit sequences
+ int lookBits = Unsafe.Add(ref huffcodeRef, p) << (8 - l);
+ for (int ctr = 1 << (8 - l); ctr > 0; ctr--)
+ {
+ lookaheadRef[lookBits] = (short)((l << 8) | huffval[p]);
+ lookBits++;
+ }
}
-
- code++;
- x++;
}
}
}
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTables.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTables.cs
index 5d59809cc..3a559bb86 100644
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTables.cs
+++ b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTables.cs
@@ -1,16 +1,15 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
{
///
- /// Defines a pair of huffman tables
+ /// Defines a 2 pairs of huffman tables
///
- internal sealed class PdfJsHuffmanTables : IDisposable
+ internal sealed class PdfJsHuffmanTables
{
private readonly PdfJsHuffmanTable[] tables = new PdfJsHuffmanTable[4];
@@ -22,19 +21,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
public ref PdfJsHuffmanTable this[int index]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get
- {
- return ref this.tables[index];
- }
- }
-
- ///
- public void Dispose()
- {
- for (int i = 0; i < this.tables.Length; i++)
- {
- this.tables[i].Dispose();
- }
+ get => ref this.tables[index];
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsIDCT.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsIDCT.cs
deleted file mode 100644
index 00fa1985d..000000000
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsIDCT.cs
+++ /dev/null
@@ -1,513 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Runtime.CompilerServices;
-using SixLabors.ImageSharp.Memory;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
-{
- ///
- /// Performs the inverse Descrete Cosine Transform on each frame component.
- ///
- internal static class PdfJsIDCT
- {
- ///
- /// Precomputed values scaled up by 14 bits
- ///
- public static readonly short[] Aanscales =
- {
- 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, 22725, 31521, 29692, 26722, 22725, 17855,
- 12299, 6270, 21407, 29692, 27969, 25172, 21407, 16819, 11585,
- 5906, 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315,
- 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520, 12873,
- 17855, 16819, 15137, 12873, 10114, 6967, 3552, 8867, 12299,
- 11585, 10426, 8867, 6967, 4799, 2446, 4520, 6270, 5906, 5315,
- 4520, 3552, 2446, 1247
- };
-
- private const int DctCos1 = 4017; // cos(pi/16)
- private const int DctSin1 = 799; // sin(pi/16)
- private const int DctCos3 = 3406; // cos(3*pi/16)
- private const int DctSin3 = 2276; // sin(3*pi/16)
- private const int DctCos6 = 1567; // cos(6*pi/16)
- private const int DctSin6 = 3784; // sin(6*pi/16)
- private const int DctSqrt2 = 5793; // sqrt(2)
- private const int DctSqrt1D2 = 2896; // sqrt(2) / 2
-
-#pragma warning disable SA1310 // Field names must not contain underscore
- private const int FIX_1_082392200 = 277; // FIX(1.082392200)
- private const int FIX_1_414213562 = 362; // FIX(1.414213562)
- private const int FIX_1_847759065 = 473; // FIX(1.847759065)
- private const int FIX_2_613125930 = 669; // FIX(2.613125930)
-#pragma warning restore SA1310 // Field names must not contain underscore
-
- private const int ConstBits = 8;
- private const int Pass1Bits = 2; // Factional bits in scale factors
- private const int MaxJSample = 255;
- private const int CenterJSample = 128;
- private const int RangeCenter = (MaxJSample * 2) + 2;
-
- // First segment of range limit table: limit[x] = 0 for x < 0
- // allow negative subscripts of simple table
- private const int TableOffset = 2 * (MaxJSample + 1);
- private const int LimitOffset = TableOffset - (RangeCenter - CenterJSample);
-
- // Each IDCT routine is responsible for range-limiting its results and
- // converting them to unsigned form (0..MaxJSample). The raw outputs could
- // be quite far out of range if the input data is corrupt, so a bulletproof
- // range-limiting step is required. We use a mask-and-table-lookup method
- // to do the combined operations quickly, assuming that MaxJSample+1
- // is a power of 2.
- private const int RangeMask = (MaxJSample * 4) + 3; // 2 bits wider than legal samples
-
- private static readonly byte[] Limit = new byte[5 * (MaxJSample + 1)];
-
- static PdfJsIDCT()
- {
- // Main part of range limit table: limit[x] = x
- int i;
- for (i = 0; i <= MaxJSample; i++)
- {
- Limit[TableOffset + i] = (byte)i;
- }
-
- // End of range limit table: Limit[x] = MaxJSample for x > MaxJSample
- for (; i < 3 * (MaxJSample + 1); i++)
- {
- Limit[TableOffset + i] = MaxJSample;
- }
- }
-
- ///
- /// A port of Poppler's IDCT method which in turn is taken from:
- /// Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
- /// 'Practical Fast 1-D DCT Algorithms with 11 Multiplications',
- /// IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989, 988-991.
- ///
- /// The fram component
- /// The block buffer offset
- /// The computational buffer for holding temp values
- /// The quantization table
- public static void QuantizeAndInverse(PdfJsFrameComponent component, int blockBufferOffset, ref Span computationBuffer, ref Span quantizationTable)
- {
- Span blockData = component.BlockData.Slice(blockBufferOffset);
- int v0, v1, v2, v3, v4, v5, v6, v7;
- int p0, p1, p2, p3, p4, p5, p6, p7;
- int t;
-
- // inverse DCT on rows
- for (int row = 0; row < 64; row += 8)
- {
- // gather block data
- p0 = blockData[row];
- p1 = blockData[row + 1];
- p2 = blockData[row + 2];
- p3 = blockData[row + 3];
- p4 = blockData[row + 4];
- p5 = blockData[row + 5];
- p6 = blockData[row + 6];
- p7 = blockData[row + 7];
-
- // dequant p0
- p0 *= quantizationTable[row];
-
- // check for all-zero AC coefficients
- if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) == 0)
- {
- t = ((DctSqrt2 * p0) + 512) >> 10;
- short st = (short)t;
- computationBuffer[row] = st;
- computationBuffer[row + 1] = st;
- computationBuffer[row + 2] = st;
- computationBuffer[row + 3] = st;
- computationBuffer[row + 4] = st;
- computationBuffer[row + 5] = st;
- computationBuffer[row + 6] = st;
- computationBuffer[row + 7] = st;
- continue;
- }
-
- // dequant p1 ... p7
- p1 *= quantizationTable[row + 1];
- p2 *= quantizationTable[row + 2];
- p3 *= quantizationTable[row + 3];
- p4 *= quantizationTable[row + 4];
- p5 *= quantizationTable[row + 5];
- p6 *= quantizationTable[row + 6];
- p7 *= quantizationTable[row + 7];
-
- // stage 4
- v0 = ((DctSqrt2 * p0) + 128) >> 8;
- v1 = ((DctSqrt2 * p4) + 128) >> 8;
- v2 = p2;
- v3 = p6;
- v4 = ((DctSqrt1D2 * (p1 - p7)) + 128) >> 8;
- v7 = ((DctSqrt1D2 * (p1 + p7)) + 128) >> 8;
- v5 = p3 << 4;
- v6 = p5 << 4;
-
- // stage 3
- v0 = (v0 + v1 + 1) >> 1;
- v1 = v0 - v1;
- t = ((v2 * DctSin6) + (v3 * DctCos6) + 128) >> 8;
- v2 = ((v2 * DctCos6) - (v3 * DctSin6) + 128) >> 8;
- v3 = t;
- v4 = (v4 + v6 + 1) >> 1;
- v6 = v4 - v6;
- v7 = (v7 + v5 + 1) >> 1;
- v5 = v7 - v5;
-
- // stage 2
- v0 = (v0 + v3 + 1) >> 1;
- v3 = v0 - v3;
- v1 = (v1 + v2 + 1) >> 1;
- v2 = v1 - v2;
- t = ((v4 * DctSin3) + (v7 * DctCos3) + 2048) >> 12;
- v4 = ((v4 * DctCos3) - (v7 * DctSin3) + 2048) >> 12;
- v7 = t;
- t = ((v5 * DctSin1) + (v6 * DctCos1) + 2048) >> 12;
- v5 = ((v5 * DctCos1) - (v6 * DctSin1) + 2048) >> 12;
- v6 = t;
-
- // stage 1
- computationBuffer[row] = (short)(v0 + v7);
- computationBuffer[row + 7] = (short)(v0 - v7);
- computationBuffer[row + 1] = (short)(v1 + v6);
- computationBuffer[row + 6] = (short)(v1 - v6);
- computationBuffer[row + 2] = (short)(v2 + v5);
- computationBuffer[row + 5] = (short)(v2 - v5);
- computationBuffer[row + 3] = (short)(v3 + v4);
- computationBuffer[row + 4] = (short)(v3 - v4);
- }
-
- // inverse DCT on columns
- for (int col = 0; col < 8; ++col)
- {
- p0 = computationBuffer[col];
- p1 = computationBuffer[col + 8];
- p2 = computationBuffer[col + 16];
- p3 = computationBuffer[col + 24];
- p4 = computationBuffer[col + 32];
- p5 = computationBuffer[col + 40];
- p6 = computationBuffer[col + 48];
- p7 = computationBuffer[col + 56];
-
- // check for all-zero AC coefficients
- if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) == 0)
- {
- t = ((DctSqrt2 * p0) + 8192) >> 14;
-
- // convert to 8 bit
- t = (t < -2040) ? 0 : (t >= 2024) ? MaxJSample : (t + 2056) >> 4;
- short st = (short)t;
-
- blockData[col] = st;
- blockData[col + 8] = st;
- blockData[col + 16] = st;
- blockData[col + 24] = st;
- blockData[col + 32] = st;
- blockData[col + 40] = st;
- blockData[col + 48] = st;
- blockData[col + 56] = st;
- continue;
- }
-
- // stage 4
- v0 = ((DctSqrt2 * p0) + 2048) >> 12;
- v1 = ((DctSqrt2 * p4) + 2048) >> 12;
- v2 = p2;
- v3 = p6;
- v4 = ((DctSqrt1D2 * (p1 - p7)) + 2048) >> 12;
- v7 = ((DctSqrt1D2 * (p1 + p7)) + 2048) >> 12;
- v5 = p3;
- v6 = p5;
-
- // stage 3
- // Shift v0 by 128.5 << 5 here, so we don't need to shift p0...p7 when
- // converting to UInt8 range later.
- v0 = ((v0 + v1 + 1) >> 1) + 4112;
- v1 = v0 - v1;
- t = ((v2 * DctSin6) + (v3 * DctCos6) + 2048) >> 12;
- v2 = ((v2 * DctCos6) - (v3 * DctSin6) + 2048) >> 12;
- v3 = t;
- v4 = (v4 + v6 + 1) >> 1;
- v6 = v4 - v6;
- v7 = (v7 + v5 + 1) >> 1;
- v5 = v7 - v5;
-
- // stage 2
- v0 = (v0 + v3 + 1) >> 1;
- v3 = v0 - v3;
- v1 = (v1 + v2 + 1) >> 1;
- v2 = v1 - v2;
- t = ((v4 * DctSin3) + (v7 * DctCos3) + 2048) >> 12;
- v4 = ((v4 * DctCos3) - (v7 * DctSin3) + 2048) >> 12;
- v7 = t;
- t = ((v5 * DctSin1) + (v6 * DctCos1) + 2048) >> 12;
- v5 = ((v5 * DctCos1) - (v6 * DctSin1) + 2048) >> 12;
- v6 = t;
-
- // stage 1
- p0 = v0 + v7;
- p7 = v0 - v7;
- p1 = v1 + v6;
- p6 = v1 - v6;
- p2 = v2 + v5;
- p5 = v2 - v5;
- p3 = v3 + v4;
- p4 = v3 - v4;
-
- // convert to 8-bit integers
- p0 = (p0 < 16) ? 0 : (p0 >= 4080) ? MaxJSample : p0 >> 4;
- p1 = (p1 < 16) ? 0 : (p1 >= 4080) ? MaxJSample : p1 >> 4;
- p2 = (p2 < 16) ? 0 : (p2 >= 4080) ? MaxJSample : p2 >> 4;
- p3 = (p3 < 16) ? 0 : (p3 >= 4080) ? MaxJSample : p3 >> 4;
- p4 = (p4 < 16) ? 0 : (p4 >= 4080) ? MaxJSample : p4 >> 4;
- p5 = (p5 < 16) ? 0 : (p5 >= 4080) ? MaxJSample : p5 >> 4;
- p6 = (p6 < 16) ? 0 : (p6 >= 4080) ? MaxJSample : p6 >> 4;
- p7 = (p7 < 16) ? 0 : (p7 >= 4080) ? MaxJSample : p7 >> 4;
-
- // store block data
- blockData[col] = (short)p0;
- blockData[col + 8] = (short)p1;
- blockData[col + 16] = (short)p2;
- blockData[col + 24] = (short)p3;
- blockData[col + 32] = (short)p4;
- blockData[col + 40] = (short)p5;
- blockData[col + 48] = (short)p6;
- blockData[col + 56] = (short)p7;
- }
- }
-
- ///
- /// A port of
- /// A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT
- /// on each row(or vice versa, but it's more convenient to emit a row at
- /// a time). Direct algorithms are also available, but they are much more
- /// complex and seem not to be any faster when reduced to code.
- ///
- /// This implementation is based on Arai, Agui, and Nakajima's algorithm for
- /// scaled DCT.Their original paper (Trans.IEICE E-71(11):1095) is in
- /// Japanese, but the algorithm is described in the Pennebaker & Mitchell
- /// JPEG textbook(see REFERENCES section in file README.ijg). The following
- /// code is based directly on figure 4-8 in P&M.
- /// While an 8-point DCT cannot be done in less than 11 multiplies, it is
- /// possible to arrange the computation so that many of the multiplies are
- /// simple scalings of the final outputs.These multiplies can then be
- /// folded into the multiplications or divisions by the JPEG quantization
- /// table entries. The AA&N method leaves only 5 multiplies and 29 adds
- /// to be done in the DCT itself.
- /// The primary disadvantage of this method is that with fixed-point math,
- /// accuracy is lost due to imprecise representation of the scaled
- /// quantization values.The smaller the quantization table entry, the less
- /// precise the scaled value, so this implementation does worse with high -
- /// quality - setting files than with low - quality ones.
- ///
- /// The frame component
- /// The block buffer offset
- /// The computational buffer for holding temp values
- /// The multiplier table
- public static void QuantizeAndInverseFast(PdfJsFrameComponent component, int blockBufferOffset, ref Span computationBuffer, ref Span multiplierTable)
- {
- Span blockData = component.BlockData.Slice(blockBufferOffset);
- int p0, p1, p2, p3, p4, p5, p6, p7;
-
- for (int col = 0; col < 8; col++)
- {
- // Gather block data
- p0 = blockData[col];
- p1 = blockData[col + 8];
- p2 = blockData[col + 16];
- p3 = blockData[col + 24];
- p4 = blockData[col + 32];
- p5 = blockData[col + 40];
- p6 = blockData[col + 48];
- p7 = blockData[col + 56];
-
- int tmp0 = p0 * multiplierTable[col];
-
- // Due to quantization, we will usually find that many of the input
- // coefficients are zero, especially the AC terms. We can exploit this
- // by short-circuiting the IDCT calculation for any column in which all
- // the AC terms are zero. In that case each output is equal to the
- // DC coefficient (with scale factor as needed).
- // With typical images and quantization tables, half or more of the
- // column DCT calculations can be simplified this way.
- if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) == 0)
- {
- short dcval = (short)tmp0;
-
- computationBuffer[col] = dcval;
- computationBuffer[col + 8] = dcval;
- computationBuffer[col + 16] = dcval;
- computationBuffer[col + 24] = dcval;
- computationBuffer[col + 32] = dcval;
- computationBuffer[col + 40] = dcval;
- computationBuffer[col + 48] = dcval;
- computationBuffer[col + 56] = dcval;
-
- continue;
- }
-
- // Even part
- int tmp1 = p2 * multiplierTable[col + 16];
- int tmp2 = p4 * multiplierTable[col + 32];
- int tmp3 = p6 * multiplierTable[col + 48];
-
- int tmp10 = tmp0 + tmp2; // Phase 3
- int tmp11 = tmp0 - tmp2;
-
- int tmp13 = tmp1 + tmp3; // Phases 5-3
- int tmp12 = Multiply(tmp1 - tmp3, FIX_1_414213562) - tmp13; // 2*c4
-
- tmp0 = tmp10 + tmp13; // Phase 2
- tmp3 = tmp10 - tmp13;
- tmp1 = tmp11 + tmp12;
- tmp2 = tmp11 - tmp12;
-
- // Odd Part
- int tmp4 = p1 * multiplierTable[col + 8];
- int tmp5 = p3 * multiplierTable[col + 24];
- int tmp6 = p5 * multiplierTable[col + 40];
- int tmp7 = p7 * multiplierTable[col + 56];
-
- int z13 = tmp6 + tmp5; // Phase 6
- int z10 = tmp6 - tmp5;
- int z11 = tmp4 + tmp7;
- int z12 = tmp4 - tmp7;
-
- tmp7 = z11 + z13; // Phase 5
- tmp11 = Multiply(z11 - z13, FIX_1_414213562); // 2*c4
-
- int z5 = Multiply(z10 + z12, FIX_1_847759065); // 2*c2
- tmp10 = z5 - Multiply(z12, FIX_1_082392200); // 2*(c2-c6)
- tmp12 = z5 - Multiply(z10, FIX_2_613125930); // 2*(c2+c6)
-
- tmp6 = tmp12 - tmp7; // Phase 2
- tmp5 = tmp11 - tmp6;
- tmp4 = tmp10 - tmp5;
-
- computationBuffer[col] = (short)(tmp0 + tmp7);
- computationBuffer[col + 56] = (short)(tmp0 - tmp7);
- computationBuffer[col + 8] = (short)(tmp1 + tmp6);
- computationBuffer[col + 48] = (short)(tmp1 - tmp6);
- computationBuffer[col + 16] = (short)(tmp2 + tmp5);
- computationBuffer[col + 40] = (short)(tmp2 - tmp5);
- computationBuffer[col + 24] = (short)(tmp3 + tmp4);
- computationBuffer[col + 32] = (short)(tmp3 - tmp4);
- }
-
- // Pass 2: process rows from work array, store into output array.
- // Note that we must descale the results by a factor of 8 == 2**3,
- // and also undo the pass 1 bits scaling.
- for (int row = 0; row < 64; row += 8)
- {
- p1 = computationBuffer[row + 1];
- p2 = computationBuffer[row + 2];
- p3 = computationBuffer[row + 3];
- p4 = computationBuffer[row + 4];
- p5 = computationBuffer[row + 5];
- p6 = computationBuffer[row + 6];
- p7 = computationBuffer[row + 7];
-
- // Add range center and fudge factor for final descale and range-limit.
- int z5 = computationBuffer[row] + (RangeCenter << (Pass1Bits + 3)) + (1 << (Pass1Bits + 2));
-
- // Check for all-zero AC coefficients
- if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) == 0)
- {
- byte dcval = Limit[LimitOffset + (RightShift(z5, Pass1Bits + 3) & RangeMask)];
-
- blockData[row] = dcval;
- blockData[row + 1] = dcval;
- blockData[row + 2] = dcval;
- blockData[row + 3] = dcval;
- blockData[row + 4] = dcval;
- blockData[row + 5] = dcval;
- blockData[row + 6] = dcval;
- blockData[row + 7] = dcval;
-
- continue;
- }
-
- // Even part
- int tmp10 = z5 + p4;
- int tmp11 = z5 - p4;
-
- int tmp13 = p2 + p6;
- int tmp12 = Multiply(p2 - p6, FIX_1_414213562) - tmp13; // 2*c4
-
- int tmp0 = tmp10 + tmp13;
- int tmp3 = tmp10 - tmp13;
- int tmp1 = tmp11 + tmp12;
- int tmp2 = tmp11 - tmp12;
-
- // Odd part
- int z13 = p5 + p3;
- int z10 = p5 - p3;
- int z11 = p1 + p7;
- int z12 = p1 - p7;
-
- int tmp7 = z11 + z13; // Phase 5
- tmp11 = Multiply(z11 - z13, FIX_1_414213562); // 2*c4
-
- z5 = Multiply(z10 + z12, FIX_1_847759065); // 2*c2
- tmp10 = z5 - Multiply(z12, FIX_1_082392200); // 2*(c2-c6)
- tmp12 = z5 - Multiply(z10, FIX_2_613125930); // 2*(c2+c6)
-
- int tmp6 = tmp12 - tmp7; // Phase 2
- int tmp5 = tmp11 - tmp6;
- int tmp4 = tmp10 - tmp5;
-
- // Final output stage: scale down by a factor of 8, offset, and range-limit
- blockData[row] = Limit[LimitOffset + (RightShift(tmp0 + tmp7, Pass1Bits + 3) & RangeMask)];
- blockData[row + 7] = Limit[LimitOffset + (RightShift(tmp0 - tmp7, Pass1Bits + 3) & RangeMask)];
- blockData[row + 1] = Limit[LimitOffset + (RightShift(tmp1 + tmp6, Pass1Bits + 3) & RangeMask)];
- blockData[row + 6] = Limit[LimitOffset + (RightShift(tmp1 - tmp6, Pass1Bits + 3) & RangeMask)];
- blockData[row + 2] = Limit[LimitOffset + (RightShift(tmp2 + tmp5, Pass1Bits + 3) & RangeMask)];
- blockData[row + 5] = Limit[LimitOffset + (RightShift(tmp2 - tmp5, Pass1Bits + 3) & RangeMask)];
- blockData[row + 3] = Limit[LimitOffset + (RightShift(tmp3 + tmp4, Pass1Bits + 3) & RangeMask)];
- blockData[row + 4] = Limit[LimitOffset + (RightShift(tmp3 - tmp4, Pass1Bits + 3) & RangeMask)];
- }
- }
-
- ///
- /// Descale and correctly round an int value that's scaled by bits.
- /// We assume rounds towards minus infinity, so adding
- /// the fudge factor is correct for either sign of .
- ///
- /// The value
- /// The number of bits
- /// The
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int Descale(int value, int n)
- {
- return RightShift(value + (1 << (n - 1)), n);
- }
-
- ///
- /// Multiply a variable by an int constant, and immediately descale.
- ///
- /// The value
- /// The multiplier
- /// The
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static int Multiply(int val, int c)
- {
- return Descale(val * c, ConstBits);
- }
-
- ///
- /// Right-shifts the value by the given amount
- ///
- /// The value
- /// The amount to shift by
- /// The
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static int RightShift(int value, int shift)
- {
- return value >> shift;
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsJpegPixelArea.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsJpegPixelArea.cs
deleted file mode 100644
index f16fb9a2c..000000000
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsJpegPixelArea.cs
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Diagnostics;
-using System.Numerics;
-using System.Runtime.CompilerServices;
-using SixLabors.ImageSharp.Memory;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
-{
- ///
- /// Represents a section of the jpeg component data laid out in pixel order.
- ///
- internal struct PdfJsJpegPixelArea : IDisposable
- {
- private readonly MemoryManager memoryManager;
-
- private readonly int imageWidth;
-
- private readonly int imageHeight;
-
- private IBuffer componentData;
-
- private int rowStride;
-
- ///
- /// Initializes a new instance of the struct.
- ///
- /// The to use for buffer allocations.
- /// The image width
- /// The image height
- /// The number of components
- public PdfJsJpegPixelArea(MemoryManager memoryManager, int imageWidth, int imageHeight, int numberOfComponents)
- {
- this.memoryManager = memoryManager;
- this.imageWidth = imageWidth;
- this.imageHeight = imageHeight;
- this.Width = 0;
- this.Height = 0;
- this.NumberOfComponents = numberOfComponents;
- this.componentData = null;
- this.rowStride = 0;
- }
-
- ///
- /// Gets the number of components
- ///
- public int NumberOfComponents { get; }
-
- ///
- /// Gets the width
- ///
- public int Width { get; private set; }
-
- ///
- /// Gets the height
- ///
- public int Height { get; private set; }
-
- ///
- /// Organsizes the decoded jpeg components into a linear array ordered by component.
- /// This must be called before attempting to retrieve the data.
- ///
- /// The jpeg component blocks
- /// The pixel area width
- /// The pixel area height
- public void LinearizeBlockData(PdfJsComponentBlocks components, int width, int height)
- {
- this.Width = width;
- this.Height = height;
- int numberOfComponents = this.NumberOfComponents;
- this.rowStride = width * numberOfComponents;
- var scale = new Vector2(this.imageWidth / (float)width, this.imageHeight / (float)height);
-
- this.componentData = this.memoryManager.Allocate(width * height * numberOfComponents);
- Span componentDataSpan = this.componentData.Span;
- const uint Mask3Lsb = 0xFFFFFFF8; // Used to clear the 3 LSBs
-
- using (IBuffer xScaleBlockOffset = this.memoryManager.Allocate(width))
- {
- Span xScaleBlockOffsetSpan = xScaleBlockOffset.Span;
- for (int i = 0; i < numberOfComponents; i++)
- {
- ref PdfJsComponent component = ref components.Components[i];
- Vector2 componentScale = component.Scale * scale;
- int offset = i;
- Span output = component.Output.Span;
- int blocksPerScanline = (component.BlocksPerLine + 1) << 3;
-
- // Precalculate the xScaleBlockOffset
- int j;
- for (int x = 0; x < width; x++)
- {
- j = (int)(x * componentScale.X);
- xScaleBlockOffsetSpan[x] = (int)((j & Mask3Lsb) << 3) | (j & 7);
- }
-
- // Linearize the blocks of the component
- for (int y = 0; y < height; y++)
- {
- j = (int)(y * componentScale.Y);
- int index = blocksPerScanline * (int)(j & Mask3Lsb) | ((j & 7) << 3);
- for (int x = 0; x < width; x++)
- {
- componentDataSpan[offset] = (byte)output[index + xScaleBlockOffsetSpan[x]];
- offset += numberOfComponents;
- }
- }
- }
- }
- }
-
- ///
- /// Gets a representing the row 'y' beginning from the the first byte on that row.
- ///
- /// The y-coordinate of the pixel row. Must be greater than or equal to zero and less than the height of the pixel area.
- /// The
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Span GetRowSpan(int y)
- {
- this.CheckCoordinates(y);
- return this.componentData.Slice(y * this.rowStride, this.rowStride);
- }
-
- ///
- public void Dispose()
- {
- this.componentData?.Dispose();
- this.componentData = null;
- }
-
- ///
- /// Checks the coordinates to ensure they are within bounds.
- ///
- /// The y-coordinate of the row. Must be greater than zero and less than the height of the area.
- ///
- /// Thrown if the coordinates are not within the bounds of the image.
- ///
- [Conditional("DEBUG")]
- private void CheckCoordinates(int y)
- {
- if (y < 0 || y >= this.Height)
- {
- throw new ArgumentOutOfRangeException(nameof(y), y, $"{y} is outwith the area bounds.");
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsQuantizationTables.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsQuantizationTables.cs
deleted file mode 100644
index afe0b3007..000000000
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsQuantizationTables.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Runtime.CompilerServices;
-using SixLabors.ImageSharp.Memory;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
-{
- ///
- /// Contains the quantization tables.
- ///
- internal sealed class PdfJsQuantizationTables : IDisposable
- {
- public PdfJsQuantizationTables(MemoryManager memoryManager)
- {
- this.Tables = memoryManager.Allocate2D(64, 4);
- }
-
- ///
- /// Gets the ZigZag scan table
- ///
- public static byte[] DctZigZag
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get;
- }
-
- =
- {
- 0,
- 1, 8,
- 16, 9, 2,
- 3, 10, 17, 24,
- 32, 25, 18, 11, 4,
- 5, 12, 19, 26, 33, 40,
- 48, 41, 34, 27, 20, 13, 6,
- 7, 14, 21, 28, 35, 42, 49, 56,
- 57, 50, 43, 36, 29, 22, 15,
- 23, 30, 37, 44, 51, 58,
- 59, 52, 45, 38, 31,
- 39, 46, 53, 60,
- 61, 54, 47,
- 55, 62,
- 63
- };
-
- ///
- /// Gets or sets the quantization tables.
- ///
- public Buffer2D Tables
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get; set;
- }
-
- ///
- public void Dispose()
- {
- if (this.Tables != null)
- {
- this.Tables.Dispose();
- this.Tables = null;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsScanDecoder.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsScanDecoder.cs
index c6f6ac270..5fcaa6cea 100644
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsScanDecoder.cs
+++ b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsScanDecoder.cs
@@ -2,9 +2,13 @@
// Licensed under the Apache License, Version 2.0.
using System;
+#if DEBUG
using System.Diagnostics;
+#endif
using System.IO;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using SixLabors.ImageSharp.Formats.Jpeg.Common;
namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
{
@@ -13,18 +17,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
///
internal struct PdfJsScanDecoder
{
+ private ZigZag dctZigZag;
+
private byte[] markerBuffer;
private int bitsData;
private int bitsCount;
-#pragma warning disable 414
- private int bitsUnRead;
-
- private int accumulator;
-#pragma warning restore 414
-
private int specStart;
private int specEnd;
@@ -72,6 +72,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
int successivePrev,
int successive)
{
+ this.dctZigZag = ZigZag.CreateUnzigTable();
this.markerBuffer = new byte[2];
this.compIndex = componentIndex;
this.specStart = spectralStart;
@@ -113,34 +114,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
}
else
{
- if (this.specStart == 0)
- {
- if (successivePrev == 0)
- {
- this.DecodeScanDCFirst(dcHuffmanTables, components, componentsLength, mcusPerLine, mcuToRead, ref mcu, stream);
- }
- else
- {
- this.DecodeScanDCSuccessive(components, componentsLength, mcusPerLine, mcuToRead, ref mcu, stream);
- }
- }
- else
- {
- if (successivePrev == 0)
- {
- this.DecodeScanACFirst(acHuffmanTables, components, componentsLength, mcusPerLine, mcuToRead, ref mcu, stream);
- }
- else
- {
- this.DecodeScanACSuccessive(acHuffmanTables, components, componentsLength, mcusPerLine, mcuToRead, ref mcu, stream);
- }
- }
+ bool isAc = this.specStart != 0;
+ bool isFirst = successivePrev == 0;
+ PdfJsHuffmanTables huffmanTables = isAc ? acHuffmanTables : dcHuffmanTables;
+ this.DecodeScanProgressive(huffmanTables, isAc, isFirst, components, componentsLength, mcusPerLine, mcuToRead, ref mcu, stream);
}
// Find marker
this.bitsCount = 0;
- this.accumulator = 0;
- this.bitsUnRead = 0;
fileMarker = PdfJsJpegDecoderCore.FindNextFileMarker(this.markerBuffer, stream);
// Some bad images seem to pad Scan blocks with e.g. zero bytes, skip past
@@ -172,7 +153,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
fileMarker = PdfJsJpegDecoderCore.FindNextFileMarker(this.markerBuffer, stream);
// Some images include more Scan blocks than expected, skip past those and
- // attempt to find the next valid marker (fixes issue8182.pdf) in original code.
+ // attempt to find the next valid marker (fixes issue8182.pdf) ref original code.
if (fileMarker.Invalid)
{
#if DEBUG
@@ -187,7 +168,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
}
}
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void DecodeScanBaseline(
PdfJsHuffmanTables dcHuffmanTables,
PdfJsHuffmanTables acHuffmanTables,
@@ -201,6 +181,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
if (componentsLength == 1)
{
PdfJsFrameComponent component = components[this.compIndex];
+ ref short blockDataRef = ref MemoryMarshal.GetReference(MemoryMarshal.Cast(component.SpectralBlocks.Span));
ref PdfJsHuffmanTable dcHuffmanTable = ref dcHuffmanTables[component.DCHuffmanTableId];
ref PdfJsHuffmanTable acHuffmanTable = ref acHuffmanTables[component.ACHuffmanTableId];
@@ -211,7 +192,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
continue;
}
- this.DecodeBlockBaseline(ref dcHuffmanTable, ref acHuffmanTable, component, mcu, stream);
+ this.DecodeBlockBaseline(ref dcHuffmanTable, ref acHuffmanTable, component, ref blockDataRef, mcu, stream);
mcu++;
}
}
@@ -222,6 +203,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
for (int i = 0; i < componentsLength; i++)
{
PdfJsFrameComponent component = components[i];
+ ref short blockDataRef = ref MemoryMarshal.GetReference(MemoryMarshal.Cast(component.SpectralBlocks.Span));
ref PdfJsHuffmanTable dcHuffmanTable = ref dcHuffmanTables[component.DCHuffmanTableId];
ref PdfJsHuffmanTable acHuffmanTable = ref acHuffmanTables[component.ACHuffmanTableId];
int h = component.HorizontalSamplingFactor;
@@ -236,7 +218,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
continue;
}
- this.DecodeMcuBaseline(ref dcHuffmanTable, ref acHuffmanTable, component, mcusPerLine, mcu, j, k, stream);
+ this.DecodeMcuBaseline(ref dcHuffmanTable, ref acHuffmanTable, component, ref blockDataRef, mcusPerLine, mcu, j, k, stream);
}
}
}
@@ -246,9 +228,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
}
}
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void DecodeScanDCFirst(
- PdfJsHuffmanTables dcHuffmanTables,
+ private void DecodeScanProgressive(
+ PdfJsHuffmanTables huffmanTables,
+ bool isAC,
+ bool isFirst,
PdfJsFrameComponent[] components,
int componentsLength,
int mcusPerLine,
@@ -259,7 +242,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
if (componentsLength == 1)
{
PdfJsFrameComponent component = components[this.compIndex];
- ref PdfJsHuffmanTable dcHuffmanTable = ref dcHuffmanTables[component.DCHuffmanTableId];
+ ref short blockDataRef = ref MemoryMarshal.GetReference(MemoryMarshal.Cast(component.SpectralBlocks.Span));
+ ref PdfJsHuffmanTable huffmanTable = ref huffmanTables[isAC ? component.ACHuffmanTableId : component.DCHuffmanTableId];
for (int n = 0; n < mcuToRead; n++)
{
@@ -268,173 +252,32 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
continue;
}
- this.DecodeBlockDCFirst(ref dcHuffmanTable, component, mcu, stream);
- mcu++;
- }
- }
- else
- {
- for (int n = 0; n < mcuToRead; n++)
- {
- for (int i = 0; i < componentsLength; i++)
+ if (isAC)
{
- PdfJsFrameComponent component = components[i];
- ref PdfJsHuffmanTable dcHuffmanTable = ref dcHuffmanTables[component.DCHuffmanTableId];
- int h = component.HorizontalSamplingFactor;
- int v = component.VerticalSamplingFactor;
-
- for (int j = 0; j < v; j++)
+ if (isFirst)
{
- for (int k = 0; k < h; k++)
- {
- if (this.endOfStreamReached || this.unexpectedMarkerReached)
- {
- continue;
- }
-
- this.DecodeMcuDCFirst(ref dcHuffmanTable, component, mcusPerLine, mcu, j, k, stream);
- }
+ this.DecodeBlockACFirst(ref huffmanTable, component, ref blockDataRef, mcu, stream);
}
- }
-
- mcu++;
- }
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void DecodeScanDCSuccessive(
- PdfJsFrameComponent[] components,
- int componentsLength,
- int mcusPerLine,
- int mcuToRead,
- ref int mcu,
- Stream stream)
- {
- if (componentsLength == 1)
- {
- PdfJsFrameComponent component = components[this.compIndex];
- for (int n = 0; n < mcuToRead; n++)
- {
- if (this.endOfStreamReached || this.unexpectedMarkerReached)
- {
- continue;
- }
-
- this.DecodeBlockDCSuccessive(component, mcu, stream);
- mcu++;
- }
- }
- else
- {
- for (int n = 0; n < mcuToRead; n++)
- {
- for (int i = 0; i < componentsLength; i++)
- {
- PdfJsFrameComponent component = components[i];
- int h = component.HorizontalSamplingFactor;
- int v = component.VerticalSamplingFactor;
- for (int j = 0; j < v; j++)
+ else
{
- for (int k = 0; k < h; k++)
- {
- if (this.endOfStreamReached || this.unexpectedMarkerReached)
- {
- continue;
- }
-
- this.DecodeMcuDCSuccessive(component, mcusPerLine, mcu, j, k, stream);
- }
+ this.DecodeBlockACSuccessive(ref huffmanTable, component, ref blockDataRef, mcu, stream);
}
}
-
- mcu++;
- }
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void DecodeScanACFirst(
- PdfJsHuffmanTables acHuffmanTables,
- PdfJsFrameComponent[] components,
- int componentsLength,
- int mcusPerLine,
- int mcuToRead,
- ref int mcu,
- Stream stream)
- {
- if (componentsLength == 1)
- {
- PdfJsFrameComponent component = components[this.compIndex];
- ref PdfJsHuffmanTable acHuffmanTable = ref acHuffmanTables[component.ACHuffmanTableId];
-
- for (int n = 0; n < mcuToRead; n++)
- {
- if (this.endOfStreamReached || this.unexpectedMarkerReached)
- {
- continue;
- }
-
- this.DecodeBlockACFirst(ref acHuffmanTable, component, mcu, stream);
- mcu++;
- }
- }
- else
- {
- for (int n = 0; n < mcuToRead; n++)
- {
- for (int i = 0; i < componentsLength; i++)
+ else
{
- PdfJsFrameComponent component = components[i];
- ref PdfJsHuffmanTable acHuffmanTable = ref acHuffmanTables[component.ACHuffmanTableId];
- int h = component.HorizontalSamplingFactor;
- int v = component.VerticalSamplingFactor;
-
- for (int j = 0; j < v; j++)
+ if (isFirst)
{
- for (int k = 0; k < h; k++)
- {
- if (this.endOfStreamReached || this.unexpectedMarkerReached)
- {
- continue;
- }
-
- this.DecodeMcuACFirst(ref acHuffmanTable, component, mcusPerLine, mcu, j, k, stream);
- }
+ this.DecodeBlockDCFirst(ref huffmanTable, component, ref blockDataRef, mcu, stream);
+ }
+ else
+ {
+ this.DecodeBlockDCSuccessive(component, ref blockDataRef, mcu, stream);
}
}
mcu++;
}
}
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void DecodeScanACSuccessive(
- PdfJsHuffmanTables acHuffmanTables,
- PdfJsFrameComponent[] components,
- int componentsLength,
- int mcusPerLine,
- int mcuToRead,
- ref int mcu,
- Stream stream)
- {
- if (componentsLength == 1)
- {
- PdfJsFrameComponent component = components[this.compIndex];
- ref PdfJsHuffmanTable acHuffmanTable = ref acHuffmanTables[component.ACHuffmanTableId];
-
- for (int n = 0; n < mcuToRead; n++)
- {
- if (this.endOfStreamReached || this.unexpectedMarkerReached)
- {
- continue;
- }
-
- this.DecodeBlockACSuccessive(ref acHuffmanTable, component, mcu, stream);
- mcu++;
- }
- }
else
{
for (int n = 0; n < mcuToRead; n++)
@@ -442,7 +285,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
for (int i = 0; i < componentsLength; i++)
{
PdfJsFrameComponent component = components[i];
- ref PdfJsHuffmanTable acHuffmanTable = ref acHuffmanTables[component.ACHuffmanTableId];
+ ref short blockDataRef = ref MemoryMarshal.GetReference(MemoryMarshal.Cast(component.SpectralBlocks.Span));
+ ref PdfJsHuffmanTable huffmanTable = ref huffmanTables[isAC ? component.ACHuffmanTableId : component.DCHuffmanTableId];
int h = component.HorizontalSamplingFactor;
int v = component.VerticalSamplingFactor;
@@ -455,7 +299,28 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
continue;
}
- this.DecodeMcuACSuccessive(ref acHuffmanTable, component, mcusPerLine, mcu, j, k, stream);
+ if (isAC)
+ {
+ if (isFirst)
+ {
+ this.DecodeMcuACFirst(ref huffmanTable, component, ref blockDataRef, mcusPerLine, mcu, j, k, stream);
+ }
+ else
+ {
+ this.DecodeMcuACSuccessive(ref huffmanTable, component, ref blockDataRef, mcusPerLine, mcu, j, k, stream);
+ }
+ }
+ else
+ {
+ if (isFirst)
+ {
+ this.DecodeMcuDCFirst(ref huffmanTable, component, ref blockDataRef, mcusPerLine, mcu, j, k, stream);
+ }
+ else
+ {
+ this.DecodeMcuDCSuccessive(component, ref blockDataRef, mcusPerLine, mcu, j, k, stream);
+ }
+ }
}
}
}
@@ -466,103 +331,103 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void DecodeBlockBaseline(ref PdfJsHuffmanTable dcHuffmanTable, ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, int mcu, Stream stream)
+ private void DecodeBlockBaseline(ref PdfJsHuffmanTable dcHuffmanTable, ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, ref short blockDataRef, int mcu, Stream stream)
{
int blockRow = mcu / component.WidthInBlocks;
int blockCol = mcu % component.WidthInBlocks;
int offset = component.GetBlockBufferOffset(blockRow, blockCol);
- this.DecodeBaseline(component, offset, ref dcHuffmanTable, ref acHuffmanTable, stream);
+ this.DecodeBaseline(component, ref blockDataRef, offset, ref dcHuffmanTable, ref acHuffmanTable, stream);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void DecodeMcuBaseline(ref PdfJsHuffmanTable dcHuffmanTable, ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, int mcusPerLine, int mcu, int row, int col, Stream stream)
+ private void DecodeMcuBaseline(ref PdfJsHuffmanTable dcHuffmanTable, ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, ref short blockDataRef, int mcusPerLine, int mcu, int row, int col, Stream stream)
{
int mcuRow = mcu / mcusPerLine;
int mcuCol = mcu % mcusPerLine;
int blockRow = (mcuRow * component.VerticalSamplingFactor) + row;
int blockCol = (mcuCol * component.HorizontalSamplingFactor) + col;
int offset = component.GetBlockBufferOffset(blockRow, blockCol);
- this.DecodeBaseline(component, offset, ref dcHuffmanTable, ref acHuffmanTable, stream);
+ this.DecodeBaseline(component, ref blockDataRef, offset, ref dcHuffmanTable, ref acHuffmanTable, stream);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void DecodeBlockDCFirst(ref PdfJsHuffmanTable dcHuffmanTable, PdfJsFrameComponent component, int mcu, Stream stream)
+ private void DecodeBlockDCFirst(ref PdfJsHuffmanTable dcHuffmanTable, PdfJsFrameComponent component, ref short blockDataRef, int mcu, Stream stream)
{
int blockRow = mcu / component.WidthInBlocks;
int blockCol = mcu % component.WidthInBlocks;
int offset = component.GetBlockBufferOffset(blockRow, blockCol);
- this.DecodeDCFirst(component, offset, ref dcHuffmanTable, stream);
+ this.DecodeDCFirst(component, ref blockDataRef, offset, ref dcHuffmanTable, stream);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void DecodeMcuDCFirst(ref PdfJsHuffmanTable dcHuffmanTable, PdfJsFrameComponent component, int mcusPerLine, int mcu, int row, int col, Stream stream)
+ private void DecodeMcuDCFirst(ref PdfJsHuffmanTable dcHuffmanTable, PdfJsFrameComponent component, ref short blockDataRef, int mcusPerLine, int mcu, int row, int col, Stream stream)
{
int mcuRow = mcu / mcusPerLine;
int mcuCol = mcu % mcusPerLine;
int blockRow = (mcuRow * component.VerticalSamplingFactor) + row;
int blockCol = (mcuCol * component.HorizontalSamplingFactor) + col;
int offset = component.GetBlockBufferOffset(blockRow, blockCol);
- this.DecodeDCFirst(component, offset, ref dcHuffmanTable, stream);
+ this.DecodeDCFirst(component, ref blockDataRef, offset, ref dcHuffmanTable, stream);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void DecodeBlockDCSuccessive(PdfJsFrameComponent component, int mcu, Stream stream)
+ private void DecodeBlockDCSuccessive(PdfJsFrameComponent component, ref short blockDataRef, int mcu, Stream stream)
{
int blockRow = mcu / component.WidthInBlocks;
int blockCol = mcu % component.WidthInBlocks;
int offset = component.GetBlockBufferOffset(blockRow, blockCol);
- this.DecodeDCSuccessive(component, offset, stream);
+ this.DecodeDCSuccessive(component, ref blockDataRef, offset, stream);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void DecodeMcuDCSuccessive(PdfJsFrameComponent component, int mcusPerLine, int mcu, int row, int col, Stream stream)
+ private void DecodeMcuDCSuccessive(PdfJsFrameComponent component, ref short blockDataRef, int mcusPerLine, int mcu, int row, int col, Stream stream)
{
int mcuRow = mcu / mcusPerLine;
int mcuCol = mcu % mcusPerLine;
int blockRow = (mcuRow * component.VerticalSamplingFactor) + row;
int blockCol = (mcuCol * component.HorizontalSamplingFactor) + col;
int offset = component.GetBlockBufferOffset(blockRow, blockCol);
- this.DecodeDCSuccessive(component, offset, stream);
+ this.DecodeDCSuccessive(component, ref blockDataRef, offset, stream);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void DecodeBlockACFirst(ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, int mcu, Stream stream)
+ private void DecodeBlockACFirst(ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, ref short blockDataRef, int mcu, Stream stream)
{
int blockRow = mcu / component.WidthInBlocks;
int blockCol = mcu % component.WidthInBlocks;
int offset = component.GetBlockBufferOffset(blockRow, blockCol);
- this.DecodeACFirst(component, offset, ref acHuffmanTable, stream);
+ this.DecodeACFirst(component, ref blockDataRef, offset, ref acHuffmanTable, stream);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void DecodeMcuACFirst(ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, int mcusPerLine, int mcu, int row, int col, Stream stream)
+ private void DecodeMcuACFirst(ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, ref short blockDataRef, int mcusPerLine, int mcu, int row, int col, Stream stream)
{
int mcuRow = mcu / mcusPerLine;
int mcuCol = mcu % mcusPerLine;
int blockRow = (mcuRow * component.VerticalSamplingFactor) + row;
int blockCol = (mcuCol * component.HorizontalSamplingFactor) + col;
int offset = component.GetBlockBufferOffset(blockRow, blockCol);
- this.DecodeACFirst(component, offset, ref acHuffmanTable, stream);
+ this.DecodeACFirst(component, ref blockDataRef, offset, ref acHuffmanTable, stream);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void DecodeBlockACSuccessive(ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, int mcu, Stream stream)
+ private void DecodeBlockACSuccessive(ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, ref short blockDataRef, int mcu, Stream stream)
{
int blockRow = mcu / component.WidthInBlocks;
int blockCol = mcu % component.WidthInBlocks;
int offset = component.GetBlockBufferOffset(blockRow, blockCol);
- this.DecodeACSuccessive(component, offset, ref acHuffmanTable, stream);
+ this.DecodeACSuccessive(component, ref blockDataRef, offset, ref acHuffmanTable, stream);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void DecodeMcuACSuccessive(ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, int mcusPerLine, int mcu, int row, int col, Stream stream)
+ private void DecodeMcuACSuccessive(ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, ref short blockDataRef, int mcusPerLine, int mcu, int row, int col, Stream stream)
{
int mcuRow = mcu / mcusPerLine;
int mcuCol = mcu % mcusPerLine;
int blockRow = (mcuRow * component.VerticalSamplingFactor) + row;
int blockCol = (mcuCol * component.HorizontalSamplingFactor) + col;
int offset = component.GetBlockBufferOffset(blockRow, blockCol);
- this.DecodeACSuccessive(component, offset, ref acHuffmanTable, stream);
+ this.DecodeACSuccessive(component, ref blockDataRef, offset, ref acHuffmanTable, stream);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -579,7 +444,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
if (this.bitsData == -0x1)
{
- // We've encountered the end of the file stream which means there's no EOI marker in the image
+ // We've encountered the end of the file stream which means there's no EOI marker ref the image
this.endOfStreamReached = true;
}
@@ -608,44 +473,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private short DecodeHuffman(ref PdfJsHuffmanTable tree, Stream stream)
{
- short code = -1;
-
- // TODO: Adding this code introduces error into the decoder.
+ // TODO: Implement fast Huffman decoding.
// NOTES # During investigation of the libjpeg implementation it appears that they pull 32bits at a time and operate on those bits
- // using 3 methods: FillBits, PeekBits, and ReadBits. We should attempt to do the same.
- // It doesn't appear to speed anything up either.
- // if (this.bitsUnRead < 8)
- // {
- // if (this.bitsCount <= 0)
- // {
- // code = (short)this.ReadBit(stream);
- // if (this.endOfStreamReached || this.unexpectedMarkerReached)
- // {
- // return -1;
- // }
- //
- // this.bitsUnRead += 8;
- // }
- //
- // this.accumulator = (this.accumulator << 8) | this.bitsData;
- // int lutIndex = (this.accumulator >> (8 - this.bitsUnRead)) & 0xFF;
- // int v = tree.Lookahead[lutIndex];
- // if (v != 0)
- // {
- // int nb = (v & 0xFF) - 1;
- // this.bitsCount -= nb - 1;
- // this.bitsUnRead -= nb;
- // v = v >> 8;
- // return (short)v;
- // }
- // }
- if (code == -1)
+ // using 3 methods: FillBits, PeekBits, and ReadBits. We should attempt to do the same.
+ short code = (short)this.ReadBit(stream);
+ if (this.endOfStreamReached || this.unexpectedMarkerReached)
{
- code = (short)this.ReadBit(stream);
- if (this.endOfStreamReached || this.unexpectedMarkerReached)
- {
- return -1;
- }
+ return -1;
}
// "DECODE", section F.2.2.3, figure F.16, page 109 of T.81
@@ -704,24 +538,21 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
return n + (-1 << length) + 1;
}
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void DecodeBaseline(PdfJsFrameComponent component, int offset, ref PdfJsHuffmanTable dcHuffmanTable, ref PdfJsHuffmanTable acHuffmanTable, Stream stream)
+ private void DecodeBaseline(PdfJsFrameComponent component, ref short blockDataRef, int offset, ref PdfJsHuffmanTable dcHuffmanTable, ref PdfJsHuffmanTable acHuffmanTable, Stream stream)
{
- Span blockDataSpan = component.BlockData.Span;
-
- int t = this.DecodeHuffman(ref dcHuffmanTable, stream);
+ short t = this.DecodeHuffman(ref dcHuffmanTable, stream);
if (this.endOfStreamReached || this.unexpectedMarkerReached)
{
return;
}
int diff = t == 0 ? 0 : this.ReceiveAndExtend(t, stream);
- blockDataSpan[offset] = (short)(component.Pred += diff);
+ Unsafe.Add(ref blockDataRef, offset) = (short)(component.Pred += diff);
int k = 1;
while (k < 64)
{
- int rs = this.DecodeHuffman(ref acHuffmanTable, stream);
+ short rs = this.DecodeHuffman(ref acHuffmanTable, stream);
if (this.endOfStreamReached || this.unexpectedMarkerReached)
{
return;
@@ -748,44 +579,39 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
break;
}
- byte z = PdfJsQuantizationTables.DctZigZag[k];
+ byte z = this.dctZigZag[k];
short re = (short)this.ReceiveAndExtend(s, stream);
- blockDataSpan[offset + z] = re;
+ Unsafe.Add(ref blockDataRef, offset + z) = re;
k++;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void DecodeDCFirst(PdfJsFrameComponent component, int offset, ref PdfJsHuffmanTable dcHuffmanTable, Stream stream)
+ private void DecodeDCFirst(PdfJsFrameComponent component, ref short blockDataRef, int offset, ref PdfJsHuffmanTable dcHuffmanTable, Stream stream)
{
- Span blockDataSpan = component.BlockData.Span;
-
- int t = this.DecodeHuffman(ref dcHuffmanTable, stream);
+ short t = this.DecodeHuffman(ref dcHuffmanTable, stream);
if (this.endOfStreamReached || this.unexpectedMarkerReached)
{
return;
}
int diff = t == 0 ? 0 : this.ReceiveAndExtend(t, stream) << this.successiveState;
- blockDataSpan[offset] = (short)(component.Pred += diff);
+ Unsafe.Add(ref blockDataRef, offset) = (short)(component.Pred += diff);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void DecodeDCSuccessive(PdfJsFrameComponent component, int offset, Stream stream)
+ private void DecodeDCSuccessive(PdfJsFrameComponent component, ref short blockDataRef, int offset, Stream stream)
{
- Span blockDataSpan = component.BlockData.Span;
-
int bit = this.ReadBit(stream);
if (this.endOfStreamReached || this.unexpectedMarkerReached)
{
return;
}
- blockDataSpan[offset] |= (short)(bit << this.successiveState);
+ Unsafe.Add(ref blockDataRef, offset) |= (short)(bit << this.successiveState);
}
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void DecodeACFirst(PdfJsFrameComponent component, int offset, ref PdfJsHuffmanTable acHuffmanTable, Stream stream)
+ private void DecodeACFirst(PdfJsFrameComponent component, ref short blockDataRef, int offset, ref PdfJsHuffmanTable acHuffmanTable, Stream stream)
{
if (this.eobrun > 0)
{
@@ -793,7 +619,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
return;
}
- Span componentBlockDataSpan = component.BlockData.Span;
int k = this.specStart;
int e = this.specEnd;
while (k <= e)
@@ -820,22 +645,25 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
}
k += r;
- byte z = PdfJsQuantizationTables.DctZigZag[k];
- componentBlockDataSpan[offset + z] = (short)(this.ReceiveAndExtend(s, stream) * (1 << this.successiveState));
+
+ byte z = this.dctZigZag[k];
+ Unsafe.Add(ref blockDataRef, offset + z) = (short)(this.ReceiveAndExtend(s, stream) * (1 << this.successiveState));
k++;
}
}
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void DecodeACSuccessive(PdfJsFrameComponent component, int offset, ref PdfJsHuffmanTable acHuffmanTable, Stream stream)
+ private void DecodeACSuccessive(PdfJsFrameComponent component, ref short blockDataRef, int offset, ref PdfJsHuffmanTable acHuffmanTable, Stream stream)
{
int k = this.specStart;
int e = this.specEnd;
int r = 0;
- Span componentBlockDataSpan = component.BlockData.Span;
+
while (k <= e)
{
- byte z = PdfJsQuantizationTables.DctZigZag[k];
+ int offsetZ = offset + this.dctZigZag[k];
+ ref short blockOffsetZRef = ref Unsafe.Add(ref blockDataRef, offsetZ);
+ int sign = blockOffsetZRef < 0 ? -1 : 1;
+
switch (this.successiveACState)
{
case 0: // Initial state
@@ -874,7 +702,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
continue;
case 1: // Skipping r zero items
case 2:
- if (componentBlockDataSpan[offset + z] != 0)
+ if (blockOffsetZRef != 0)
{
int bit = this.ReadBit(stream);
if (this.endOfStreamReached || this.unexpectedMarkerReached)
@@ -882,7 +710,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
return;
}
- componentBlockDataSpan[offset + z] += (short)(bit << this.successiveState);
+ blockOffsetZRef += (short)(sign * (bit << this.successiveState));
}
else
{
@@ -895,7 +723,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
break;
case 3: // Set value for a zero item
- if (componentBlockDataSpan[offset + z] != 0)
+ if (blockOffsetZRef != 0)
{
int bit = this.ReadBit(stream);
if (this.endOfStreamReached || this.unexpectedMarkerReached)
@@ -903,17 +731,17 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
return;
}
- componentBlockDataSpan[offset + z] += (short)(bit << this.successiveState);
+ blockOffsetZRef += (short)(sign * (bit << this.successiveState));
}
else
{
- componentBlockDataSpan[offset + z] = (short)(this.successiveACNextValue << this.successiveState);
+ blockOffsetZRef = (short)(this.successiveACNextValue << this.successiveState);
this.successiveACState = 0;
}
break;
case 4: // Eob
- if (componentBlockDataSpan[offset + z] != 0)
+ if (blockOffsetZRef != 0)
{
int bit = this.ReadBit(stream);
if (this.endOfStreamReached || this.unexpectedMarkerReached)
@@ -921,7 +749,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
return;
}
- componentBlockDataSpan[offset + z] += (short)(bit << this.successiveState);
+ blockOffsetZRef += (short)(sign * (bit << this.successiveState));
}
break;
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsYCbCrToRgbTables.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsYCbCrToRgbTables.cs
deleted file mode 100644
index 203a7b1eb..000000000
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsYCbCrToRgbTables.cs
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System.Runtime.CompilerServices;
-using SixLabors.ImageSharp.PixelFormats;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
-{
- ///
- /// Provides 8-bit lookup tables for converting from YCbCr to Rgb colorspace.
- /// Methods to build the tables are based on libjpeg implementation.
- ///
- internal readonly struct PdfJsYCbCrToRgbTables
- {
- ///
- /// The red red-chrominance table
- ///
- public static int[] CrRTable = new int[256];
-
- ///
- /// The blue blue-chrominance table
- ///
- public static int[] CbBTable = new int[256];
-
- ///
- /// The green red-chrominance table
- ///
- public static int[] CrGTable = new int[256];
-
- ///
- /// The green blue-chrominance table
- ///
- public static int[] CbGTable = new int[256];
-
- // Speediest right-shift on some machines and gives us enough accuracy at 4 decimal places.
- private const int ScaleBits = 16;
-
- private const int Half = 1 << (ScaleBits - 1);
-
- private const int MinSample = 0;
-
- private const int HalfSample = 128;
-
- private const int MaxSample = 255;
-
- ///
- /// Initializes the YCbCr tables
- ///
- public static void Create()
- {
- for (int i = 0, x = -128; i <= 255; i++, x++)
- {
- // i is the actual input pixel value, in the range 0..255
- // The Cb or Cr value we are thinking of is x = i - 128
- // Cr=>R value is nearest int to 1.402 * x
- CrRTable[i] = RightShift((Fix(1.402F) * x) + Half);
-
- // Cb=>B value is nearest int to 1.772 * x
- CbBTable[i] = RightShift((Fix(1.772F) * x) + Half);
-
- // Cr=>G value is scaled-up -0.714136286
- CrGTable[i] = (-Fix(0.714136286F)) * x;
-
- // Cb => G value is scaled - up - 0.344136286 * x
- // We also add in Half so that need not do it in inner loop
- CbGTable[i] = ((-Fix(0.344136286F)) * x) + Half;
- }
- }
-
- ///
- /// Optimized method to pack bytes to the image from the YCbCr color space.
- ///
- /// The pixel format.
- /// The packed pixel.
- /// The y luminance component.
- /// The cb chroma component.
- /// The cr chroma component.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void PackYCbCr(ref TPixel packed, byte y, byte cb, byte cr)
- where TPixel : struct, IPixel
- {
- byte r = (byte)(y + CrRTable[cr]).Clamp(0, 255);
-
- // The values for the G calculation are left scaled up, since we must add them together before rounding.
- byte g = (byte)(y + RightShift(CbGTable[cb] + CrGTable[cr])).Clamp(0, 255);
-
- byte b = (byte)(y + CbBTable[cb]).Clamp(0, 255);
-
- packed.PackFromRgba32(new Rgba32(r, g, b, 255));
- }
-
- ///
- /// Optimized method to pack bytes to the image from the YccK color space.
- ///
- /// The pixel format.
- /// The packed pixel.
- /// The y luminance component.
- /// The cb chroma component.
- /// The cr chroma component.
- /// The keyline component.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void PackYccK(ref TPixel packed, byte y, byte cb, byte cr, byte k)
- where TPixel : struct, IPixel
- {
- int c = (MaxSample - (y + CrRTable[cr])).Clamp(0, 255);
-
- // The values for the G calculation are left scaled up, since we must add them together before rounding.
- int m = (MaxSample - (y + RightShift(CbGTable[cb] + CrGTable[cr]))).Clamp(0, 255);
-
- int cy = (MaxSample - (y + CbBTable[cb])).Clamp(0, 255);
-
- byte r = (byte)((c * k) / MaxSample);
- byte g = (byte)((m * k) / MaxSample);
- byte b = (byte)((cy * k) / MaxSample);
-
- packed.PackFromRgba32(new Rgba32(r, g, b, MaxSample));
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static int Fix(float x)
- {
- return (int)((x * (1L << ScaleBits)) + 0.5F);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static int RightShift(int x)
- {
- return x >> ScaleBits;
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegConstants.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegConstants.cs
index 08b42891d..2c369d390 100644
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegConstants.cs
+++ b/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegConstants.cs
@@ -194,62 +194,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
///
public const ushort RST7 = 0xFFD7;
- ///
- /// Contains JFIF specific markers
- ///
- public static class JFif
- {
- ///
- /// Represents J in ASCII
- ///
- public const byte J = 0x4A;
-
- ///
- /// Represents F in ASCII
- ///
- public const byte F = 0x46;
-
- ///
- /// Represents I in ASCII
- ///
- public const byte I = 0x49;
-
- ///
- /// Represents the null "0" marker
- ///
- public const byte Null = 0x0;
- }
-
///
/// Contains Adobe specific markers
///
public static class Adobe
{
- ///
- /// Represents A in ASCII
- ///
- public const byte A = 0x41;
-
- ///
- /// Represents d in ASCII
- ///
- public const byte D = 0x64;
-
- ///
- /// Represents b in ASCII
- ///
- public const byte O = 0x6F;
-
- ///
- /// Represents b in ASCII
- ///
- public const byte B = 0x62;
-
- ///
- /// Represents e in ASCII
- ///
- public const byte E = 0x65;
-
///
/// The color transform is unknown.(RGB or CMYK)
///
@@ -265,93 +214,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
///
public const byte ColorTransformYcck = 2;
}
-
- ///
- /// Contains EXIF specific markers
- ///
- public static class Exif
- {
- ///
- /// Represents E in ASCII
- ///
- public const byte E = 0x45;
-
- ///
- /// Represents x in ASCII
- ///
- public const byte X = 0x78;
-
- ///
- /// Represents i in ASCII
- ///
- public const byte I = 0x69;
-
- ///
- /// Represents f in ASCII
- ///
- public const byte F = 0x66;
-
- ///
- /// Represents the null "0" marker
- ///
- public const byte Null = 0x0;
- }
-
- ///
- /// Contains ICC specific markers
- ///
- public static class ICC
- {
- ///
- /// Represents I in ASCII
- ///
- public const byte I = 0x49;
-
- ///
- /// Represents C in ASCII
- ///
- public const byte C = 0x43;
-
- ///
- /// Represents _ in ASCII
- ///
- public const byte UnderScore = 0x5F;
-
- ///
- /// Represents P in ASCII
- ///
- public const byte P = 0x50;
-
- ///
- /// Represents R in ASCII
- ///
- public const byte R = 0x52;
-
- ///
- /// Represents O in ASCII
- ///
- public const byte O = 0x4F;
-
- ///
- /// Represents F in ASCII
- ///
- public const byte F = 0x46;
-
- ///
- /// Represents L in ASCII
- ///
- public const byte L = 0x4C;
-
- ///
- /// Represents E in ASCII
- ///
- public const byte E = 0x45;
-
- ///
- /// Represents the null "0" marker
- ///
- public const byte Null = 0x0;
- }
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoder.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoder.cs
index 37ce0151f..e12278cc7 100644
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoder.cs
+++ b/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoder.cs
@@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
///
/// Image decoder for generating an image out of a jpg stream.
///
- internal sealed class PdfJsJpegDecoder : IImageDecoder, IJpegDecoderOptions
+ internal sealed class PdfJsJpegDecoder : IImageDecoder, IJpegDecoderOptions, IImageInfoDetector
{
///
/// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
@@ -27,5 +27,16 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
return decoder.Decode(stream);
}
}
+
+ ///
+ public IImageInfo Identify(Configuration configuration, Stream stream)
+ {
+ Guard.NotNull(stream, nameof(stream));
+
+ using (var decoder = new PdfJsJpegDecoderCore(configuration, this))
+ {
+ return decoder.Identify(stream);
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs
index 30b8158e7..244d97fba 100644
--- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs
+++ b/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs
@@ -2,9 +2,12 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers.Binary;
+using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
-using SixLabors.ImageSharp.Advanced;
+using System.Runtime.InteropServices;
+using SixLabors.ImageSharp.Formats.Jpeg.Common;
using SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder;
using SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components;
using SixLabors.ImageSharp.Memory;
@@ -13,6 +16,7 @@ using SixLabors.ImageSharp.MetaData.Profiles.Exif;
using SixLabors.ImageSharp.MetaData.Profiles.Icc;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
+using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
{
@@ -20,8 +24,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
/// Performs the jpeg decoding operation.
/// Ported from with additional fixes to handle common encoding errors
///
- internal sealed class PdfJsJpegDecoderCore : IDisposable
+ internal sealed class PdfJsJpegDecoderCore : IRawJpegData
{
+ ///
+ /// The only supported precision
+ ///
+ public const int SupportedPrecision = 8;
+
#pragma warning disable SA1401 // Fields should be private
///
/// The global configuration
@@ -29,22 +38,28 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
private readonly Configuration configuration;
///
- /// Gets the temporary buffer used to store bytes read from the stream.
+ /// The buffer used to temporarily store bytes read from the stream.
///
private readonly byte[] temp = new byte[2 * 16 * 4];
+ ///
+ /// The buffer used to read markers from the stream.
+ ///
private readonly byte[] markerBuffer = new byte[2];
- private PdfJsQuantizationTables quantizationTables;
-
+ ///
+ /// The DC HUffman tables
+ ///
private PdfJsHuffmanTables dcHuffmanTables;
+ ///
+ /// The AC HUffman tables
+ ///
private PdfJsHuffmanTables acHuffmanTables;
- private PdfJsComponentBlocks components;
-
- private PdfJsJpegPixelArea pixelArea;
-
+ ///
+ /// The reset interval determined by RST markers
+ ///
private ushort resetInterval;
///
@@ -62,14 +77,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
///
private AdobeMarker adobe;
- ///
- /// Initializes static members of the class.
- ///
- static PdfJsJpegDecoderCore()
- {
- PdfJsYCbCrToRgbTables.Create();
- }
-
///
/// Initializes a new instance of the class.
///
@@ -97,9 +104,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
public int ImageHeight { get; private set; }
///
- /// Gets the number of components
+ /// Gets the color depth, in number of bits per pixel.
///
- public int NumberOfComponents { get; private set; }
+ public int BitsPerPixel => this.ComponentCount * SupportedPrecision;
///
/// Gets the input stream.
@@ -111,6 +118,26 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
///
public bool IgnoreMetadata { get; }
+ ///
+ /// Gets the decoded by this decoder instance.
+ ///
+ public ImageMetaData MetaData { get; private set; }
+
+ ///
+ public Size ImageSizeInPixels => new Size(this.ImageWidth, this.ImageHeight);
+
+ ///
+ public int ComponentCount { get; private set; }
+
+ ///
+ public JpegColorSpace ColorSpace { get; private set; }
+
+ ///
+ public IEnumerable Components => this.Frame.Components;
+
+ ///
+ public Block8x8F[] QuantizationTables { get; private set; }
+
///
/// Finds the next file marker within the byte stream.
///
@@ -123,7 +150,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
if (value == 0)
{
- return new PdfJsFileMarker(PdfJsJpegConstants.Markers.EOI, (int)stream.Length - 2);
+ return new PdfJsFileMarker(PdfJsJpegConstants.Markers.EOI, stream.Length - 2);
}
if (marker[0] == PdfJsJpegConstants.Markers.Prefix)
@@ -135,16 +162,16 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
int suffix = stream.ReadByte();
if (suffix == -1)
{
- return new PdfJsFileMarker(PdfJsJpegConstants.Markers.EOI, (int)stream.Length - 2);
+ return new PdfJsFileMarker(PdfJsJpegConstants.Markers.EOI, stream.Length - 2);
}
marker[1] = (byte)suffix;
}
- return new PdfJsFileMarker((ushort)((marker[0] << 8) | marker[1]), (int)(stream.Position - 2));
+ return new PdfJsFileMarker(BinaryPrimitives.ReadUInt16BigEndian(marker), stream.Position - 2);
}
- return new PdfJsFileMarker((ushort)((marker[0] << 8) | marker[1]), (int)(stream.Position - 2), true);
+ return new PdfJsFileMarker(BinaryPrimitives.ReadUInt16BigEndian(marker), stream.Position - 2, true);
}
///
@@ -156,57 +183,31 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
public Image Decode(Stream stream)
where TPixel : struct, IPixel
{
- ImageMetaData metadata = this.ParseStream(stream);
-
- this.QuantizeAndInverseAllComponents();
-
- var image = new Image(this.configuration, this.ImageWidth, this.ImageHeight, metadata);
- this.FillPixelData(image.Frames.RootFrame);
- this.AssignResolution(image);
- return image;
- }
-
- ///
- public void Dispose()
- {
- this.Frame?.Dispose();
- this.components?.Dispose();
- this.quantizationTables?.Dispose();
- this.dcHuffmanTables?.Dispose();
- this.acHuffmanTables?.Dispose();
- this.pixelArea.Dispose();
-
- // Set large fields to null.
- this.Frame = null;
- this.components = null;
- this.quantizationTables = null;
- this.dcHuffmanTables = null;
- this.acHuffmanTables = null;
- }
-
- internal ImageMetaData ParseStream(Stream stream)
- {
- this.InputStream = stream;
-
- var metadata = new ImageMetaData();
- this.ParseStream(metadata, false);
- return metadata;
+ this.ParseStream(stream);
+ return this.PostProcessIntoImage();
}
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static int GetBlockBufferOffset(ref PdfJsComponent component, int row, int col)
+ ///
+ /// Reads the raw image information from the specified stream.
+ ///
+ /// The containing image data.
+ public IImageInfo Identify(Stream stream)
{
- return 64 * (((component.BlocksPerLine + 1) * row) + col);
+ this.ParseStream(stream, true);
+ this.AssignResolution();
+ return new ImageInfo(new PixelTypeInfo(this.BitsPerPixel), this.ImageWidth, this.ImageHeight, this.MetaData);
}
///
/// Parses the input stream for file markers
///
- /// Contains the metadata for an image
+ /// The input stream
/// Whether to decode metadata only.
- private void ParseStream(ImageMetaData metaData, bool metadataOnly)
+ public void ParseStream(Stream stream, bool metadataOnly = false)
{
- // TODO: metadata only logic
+ this.MetaData = new ImageMetaData();
+ this.InputStream = stream;
+
// Check for the Start Of Image marker.
var fileMarker = new PdfJsFileMarker(this.ReadUint16(), 0);
if (fileMarker.Marker != PdfJsJpegConstants.Markers.SOI)
@@ -217,7 +218,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
ushort marker = this.ReadUint16();
fileMarker = new PdfJsFileMarker(marker, (int)this.InputStream.Position - 2);
- this.quantizationTables = new PdfJsQuantizationTables(this.configuration.MemoryManager);
+ this.QuantizationTables = new Block8x8F[4];
+
+ // this.quantizationTables = new PdfJsQuantizationTables(this.configuration.MemoryManager);
this.dcHuffmanTables = new PdfJsHuffmanTables();
this.acHuffmanTables = new PdfJsHuffmanTables();
@@ -233,11 +236,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
break;
case PdfJsJpegConstants.Markers.APP1:
- this.ProcessApp1Marker(remaining, metaData);
+ this.ProcessApp1Marker(remaining);
break;
case PdfJsJpegConstants.Markers.APP2:
- this.ProcessApp2Marker(remaining, metaData);
+ this.ProcessApp2Marker(remaining);
break;
case PdfJsJpegConstants.Markers.APP3:
case PdfJsJpegConstants.Markers.APP4:
@@ -263,25 +266,58 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
break;
case PdfJsJpegConstants.Markers.DQT:
- this.ProcessDefineQuantizationTablesMarker(remaining);
+ if (metadataOnly)
+ {
+ this.InputStream.Skip(remaining);
+ }
+ else
+ {
+ this.ProcessDefineQuantizationTablesMarker(remaining);
+ }
+
break;
case PdfJsJpegConstants.Markers.SOF0:
case PdfJsJpegConstants.Markers.SOF1:
case PdfJsJpegConstants.Markers.SOF2:
this.ProcessStartOfFrameMarker(remaining, fileMarker);
+ if (metadataOnly && !this.jFif.Equals(default))
+ {
+ this.InputStream.Skip(remaining);
+ }
+
break;
case PdfJsJpegConstants.Markers.DHT:
- this.ProcessDefineHuffmanTablesMarker(remaining);
+ if (metadataOnly)
+ {
+ this.InputStream.Skip(remaining);
+ }
+ else
+ {
+ this.ProcessDefineHuffmanTablesMarker(remaining);
+ }
+
break;
case PdfJsJpegConstants.Markers.DRI:
- this.ProcessDefineRestartIntervalMarker(remaining);
+ if (metadataOnly)
+ {
+ this.InputStream.Skip(remaining);
+ }
+ else
+ {
+ this.ProcessDefineRestartIntervalMarker(remaining);
+ }
+
break;
case PdfJsJpegConstants.Markers.SOS:
- this.ProcessStartOfScanMarker();
+ if (!metadataOnly)
+ {
+ this.ProcessStartOfScanMarker();
+ }
+
break;
}
@@ -291,113 +327,78 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
this.ImageWidth = this.Frame.SamplesPerLine;
this.ImageHeight = this.Frame.Scanlines;
- this.components = new PdfJsComponentBlocks { Components = new PdfJsComponent[this.Frame.ComponentCount] };
-
- for (int i = 0; i < this.components.Components.Length; i++)
- {
- PdfJsFrameComponent frameComponent = this.Frame.Components[i];
- var component = new PdfJsComponent
- {
- Scale = new System.Numerics.Vector2(
- frameComponent.HorizontalSamplingFactor / (float)this.Frame.MaxHorizontalFactor,
- frameComponent.VerticalSamplingFactor / (float)this.Frame.MaxVerticalFactor),
- BlocksPerLine = frameComponent.WidthInBlocks,
- BlocksPerColumn = frameComponent.HeightInBlocks
- };
-
- // this.QuantizeAndInverseComponentData(ref component, frameComponent);
- this.components.Components[i] = component;
- }
-
- this.NumberOfComponents = this.components.Components.Length;
+ this.ComponentCount = this.Frame.ComponentCount;
}
- internal void QuantizeAndInverseAllComponents()
+ ///
+ public void Dispose()
{
- for (int i = 0; i < this.components.Components.Length; i++)
- {
- PdfJsFrameComponent frameComponent = this.Frame.Components[i];
- PdfJsComponent component = this.components.Components[i];
+ this.Frame?.Dispose();
- this.QuantizeAndInverseComponentData(component, frameComponent);
- }
+ // Set large fields to null.
+ this.Frame = null;
+ this.dcHuffmanTables = null;
+ this.acHuffmanTables = null;
}
///
- /// Fills the given image with the color data
+ /// Returns the correct colorspace based on the image component count
///
- /// The pixel format.
- /// The image
- private void FillPixelData(ImageFrame image)
- where TPixel : struct, IPixel
+ /// The
+ private JpegColorSpace DeduceJpegColorSpace()
{
- if (this.NumberOfComponents > 4)
+ if (this.ComponentCount == 1)
{
- throw new ImageFormatException($"Unsupported color mode. Max components 4; found {this.NumberOfComponents}");
- }
-
- this.pixelArea = new PdfJsJpegPixelArea(this.configuration.MemoryManager, image.Width, image.Height, this.NumberOfComponents);
- this.pixelArea.LinearizeBlockData(this.components, image.Width, image.Height);
-
- if (this.NumberOfComponents == 1)
- {
- this.FillGrayScaleImage(image);
- return;
+ return JpegColorSpace.Grayscale;
}
- if (this.NumberOfComponents == 3)
+ if (this.ComponentCount == 3)
{
- if (this.adobe.Equals(default(AdobeMarker)) || this.adobe.ColorTransform == PdfJsJpegConstants.Markers.Adobe.ColorTransformYCbCr)
+ if (this.adobe.Equals(default) || this.adobe.ColorTransform == PdfJsJpegConstants.Markers.Adobe.ColorTransformYCbCr)
{
- this.FillYCbCrImage(image);
+ return JpegColorSpace.YCbCr;
}
else if (this.adobe.ColorTransform == PdfJsJpegConstants.Markers.Adobe.ColorTransformUnknown)
{
- this.FillRgbImage(image);
+ return JpegColorSpace.RGB;
}
}
- if (this.NumberOfComponents == 4)
+ if (this.ComponentCount == 4)
{
- if (this.adobe.ColorTransform == PdfJsJpegConstants.Markers.Adobe.ColorTransformYcck)
- {
- this.FillYcckImage(image);
- }
- else
- {
- this.FillCmykImage(image);
- }
+ return this.adobe.ColorTransform == PdfJsJpegConstants.Markers.Adobe.ColorTransformYcck
+ ? JpegColorSpace.Ycck
+ : JpegColorSpace.Cmyk;
}
+
+ throw new ImageFormatException($"Unsupported color mode. Max components 4; found {this.ComponentCount}");
}
///
/// Assigns the horizontal and vertical resolution to the image if it has a JFIF header or EXIF metadata.
///
- /// The pixel format.
- /// The image to assign the resolution to.
- private void AssignResolution(Image image)
- where TPixel : struct, IPixel
+ private void AssignResolution()
{
if (this.isExif)
{
- double horizontalValue = image.MetaData.ExifProfile.TryGetValue(ExifTag.XResolution, out ExifValue horizontalTag)
+ double horizontalValue = this.MetaData.ExifProfile.TryGetValue(ExifTag.XResolution, out ExifValue horizontalTag)
? ((Rational)horizontalTag.Value).ToDouble()
: 0;
- double verticalValue = image.MetaData.ExifProfile.TryGetValue(ExifTag.YResolution, out ExifValue verticalTag)
+ double verticalValue = this.MetaData.ExifProfile.TryGetValue(ExifTag.YResolution, out ExifValue verticalTag)
? ((Rational)verticalTag.Value).ToDouble()
: 0;
if (horizontalValue > 0 && verticalValue > 0)
{
- image.MetaData.HorizontalResolution = horizontalValue;
- image.MetaData.VerticalResolution = verticalValue;
+ this.MetaData.HorizontalResolution = horizontalValue;
+ this.MetaData.VerticalResolution = verticalValue;
}
}
else if (this.jFif.XDensity > 0 && this.jFif.YDensity > 0)
{
- image.MetaData.HorizontalResolution = this.jFif.XDensity;
- image.MetaData.VerticalResolution = this.jFif.YDensity;
+ this.MetaData.HorizontalResolution = this.jFif.XDensity;
+ this.MetaData.VerticalResolution = this.jFif.YDensity;
}
}
@@ -430,8 +431,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
/// Processes the App1 marker retrieving any stored metadata
///
/// The remaining bytes in the segment block.
- /// The image.
- private void ProcessApp1Marker(int remaining, ImageMetaData metadata)
+ private void ProcessApp1Marker(int remaining)
{
if (remaining < 6 || this.IgnoreMetadata)
{
@@ -443,15 +443,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
byte[] profile = new byte[remaining];
this.InputStream.Read(profile, 0, remaining);
- if (profile[0] == PdfJsJpegConstants.Markers.Exif.E &&
- profile[1] == PdfJsJpegConstants.Markers.Exif.X &&
- profile[2] == PdfJsJpegConstants.Markers.Exif.I &&
- profile[3] == PdfJsJpegConstants.Markers.Exif.F &&
- profile[4] == PdfJsJpegConstants.Markers.Exif.Null &&
- profile[5] == PdfJsJpegConstants.Markers.Exif.Null)
+ if (ProfileResolver.IsProfile(profile, ProfileResolver.ExifMarker))
{
this.isExif = true;
- metadata.ExifProfile = new ExifProfile(profile);
+ this.MetaData.ExifProfile = new ExifProfile(profile);
}
}
@@ -459,8 +454,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
/// Processes the App2 marker retrieving any stored ICC profile information
///
/// The remaining bytes in the segment block.
- /// The image.
- private void ProcessApp2Marker(int remaining, ImageMetaData metadata)
+ private void ProcessApp2Marker(int remaining)
{
// Length is 14 though we only need to check 12.
const int Icclength = 14;
@@ -474,29 +468,18 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
this.InputStream.Read(identifier, 0, Icclength);
remaining -= Icclength; // We have read it by this point
- if (identifier[0] == PdfJsJpegConstants.Markers.ICC.I &&
- identifier[1] == PdfJsJpegConstants.Markers.ICC.C &&
- identifier[2] == PdfJsJpegConstants.Markers.ICC.C &&
- identifier[3] == PdfJsJpegConstants.Markers.ICC.UnderScore &&
- identifier[4] == PdfJsJpegConstants.Markers.ICC.P &&
- identifier[5] == PdfJsJpegConstants.Markers.ICC.R &&
- identifier[6] == PdfJsJpegConstants.Markers.ICC.O &&
- identifier[7] == PdfJsJpegConstants.Markers.ICC.F &&
- identifier[8] == PdfJsJpegConstants.Markers.ICC.I &&
- identifier[9] == PdfJsJpegConstants.Markers.ICC.L &&
- identifier[10] == PdfJsJpegConstants.Markers.ICC.E &&
- identifier[11] == PdfJsJpegConstants.Markers.ICC.Null)
+ if (ProfileResolver.IsProfile(identifier, ProfileResolver.IccMarker))
{
byte[] profile = new byte[remaining];
this.InputStream.Read(profile, 0, remaining);
- if (metadata.IccProfile == null)
+ if (this.MetaData.IccProfile == null)
{
- metadata.IccProfile = new IccProfile(profile);
+ this.MetaData.IccProfile = new IccProfile(profile);
}
else
{
- metadata.IccProfile.Extend(profile);
+ this.MetaData.IccProfile.Extend(profile);
}
}
else
@@ -561,10 +544,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
this.InputStream.Read(this.temp, 0, 64);
remaining -= 64;
- Span tableSpan = this.quantizationTables.Tables.GetRowSpan(quantizationTableSpec & 15);
+ ref Block8x8F table = ref this.QuantizationTables[quantizationTableSpec & 15];
for (int j = 0; j < 64; j++)
{
- tableSpan[PdfJsQuantizationTables.DctZigZag[j]] = this.temp[j];
+ table[j] = this.temp[j];
}
}
@@ -581,10 +564,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
this.InputStream.Read(this.temp, 0, 128);
remaining -= 128;
- Span tableSpan = this.quantizationTables.Tables.GetRowSpan(quantizationTableSpec & 15);
+ ref Block8x8F table = ref this.QuantizationTables[quantizationTableSpec & 15];
for (int j = 0; j < 64; j++)
{
- tableSpan[PdfJsQuantizationTables.DctZigZag[j]] = (short)((this.temp[2 * j] << 8) | this.temp[(2 * j) + 1]);
+ table[j] = (this.temp[2 * j] << 8) | this.temp[(2 * j) + 1];
}
}
@@ -619,6 +602,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
this.InputStream.Read(this.temp, 0, remaining);
+ // We only support 8-bit precision.
+ if (this.temp[0] != SupportedPrecision)
+ {
+ throw new ImageFormatException("Only 8-Bit precision supported.");
+ }
+
this.Frame = new PdfJsFrame
{
Extended = frameMarker.Marker == PdfJsJpegConstants.Markers.SOF1,
@@ -639,8 +628,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
for (int i = 0; i < this.Frame.Components.Length; i++)
{
- int h = this.temp[index + 1] >> 4;
- int v = this.temp[index + 1] & 15;
+ byte hv = this.temp[index + 1];
+ int h = hv >> 4;
+ int v = hv & 15;
if (maxH < h)
{
@@ -679,7 +669,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
using (IManagedByteBuffer huffmanData = this.configuration.MemoryManager.AllocateCleanManagedByteBuffer(256))
{
- Span huffmanSpan = huffmanData.Span;
+ ref byte huffmanDataRef = ref MemoryMarshal.GetReference(huffmanData.Span);
for (int i = 2; i < remaining;)
{
byte huffmanTableSpec = (byte)this.InputStream.ReadByte();
@@ -687,12 +677,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
using (IManagedByteBuffer codeLengths = this.configuration.MemoryManager.AllocateCleanManagedByteBuffer(17))
{
- Span codeLengthsSpan = codeLengths.Span;
+ ref byte codeLengthsRef = ref MemoryMarshal.GetReference(codeLengths.Span);
int codeLengthSum = 0;
for (int j = 1; j < 17; j++)
{
- codeLengthSum += codeLengthsSpan[j] = huffmanSpan[j - 1];
+ codeLengthSum += Unsafe.Add(ref codeLengthsRef, j) = Unsafe.Add(ref huffmanDataRef, j - 1);
}
using (IManagedByteBuffer huffmanValues = this.configuration.MemoryManager.AllocateCleanManagedByteBuffer(256))
@@ -704,8 +694,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
this.BuildHuffmanTable(
huffmanTableSpec >> 4 == 0 ? this.dcHuffmanTables : this.acHuffmanTables,
huffmanTableSpec & 15,
- codeLengths.Array,
- huffmanValues.Array);
+ codeLengths.Span,
+ huffmanValues.Span);
}
}
}
@@ -781,45 +771,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
successiveApproximation & 15);
}
- ///
- /// Build the data for the given component
- ///
- /// The component
- /// The frame component
- private void QuantizeAndInverseComponentData(PdfJsComponent component, PdfJsFrameComponent frameComponent)
- {
- int blocksPerLine = component.BlocksPerLine;
- int blocksPerColumn = component.BlocksPerColumn;
- using (IBuffer computationBuffer = this.configuration.MemoryManager.Allocate(64, true))
- using (IBuffer multiplicationBuffer = this.configuration.MemoryManager.Allocate(64, true))
- {
- Span quantizationTable = this.quantizationTables.Tables.GetRowSpan(frameComponent.QuantizationTableIndex);
- Span computationBufferSpan = computationBuffer.Span;
-
- // For AA&N IDCT method, multiplier are equal to quantization
- // coefficients scaled by scalefactor[row]*scalefactor[col], where
- // scalefactor[0] = 1
- // scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
- // For integer operation, the multiplier table is to be scaled by 12.
- Span multiplierSpan = multiplicationBuffer.Span;
-
- // for (int i = 0; i < 64; i++)
- // {
- // multiplierSpan[i] = (short)IDCT.Descale(quantizationTable[i] * IDCT.Aanscales[i], 12);
- // }
- for (int blockRow = 0; blockRow < blocksPerColumn; blockRow++)
- {
- for (int blockCol = 0; blockCol < blocksPerLine; blockCol++)
- {
- int offset = GetBlockBufferOffset(ref component, blockRow, blockCol);
- PdfJsIDCT.QuantizeAndInverse(frameComponent, offset, ref computationBufferSpan, ref quantizationTable);
- }
- }
- }
-
- component.Output = frameComponent.BlockData;
- }
-
///
/// Builds the huffman tables
///
@@ -827,107 +778,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
/// The table index
/// The codelengths
/// The values
- private void BuildHuffmanTable(PdfJsHuffmanTables tables, int index, byte[] codeLengths, byte[] values)
- {
- tables[index] = new PdfJsHuffmanTable(this.configuration.MemoryManager, codeLengths, values);
- }
-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void FillGrayScaleImage(ImageFrame image)
- where TPixel : struct, IPixel
+ private void BuildHuffmanTable(PdfJsHuffmanTables tables, int index, ReadOnlySpan codeLengths, ReadOnlySpan values)
{
- for (int y = 0; y < image.Height; y++)
- {
- Span imageRowSpan = image.GetPixelRowSpan(y);
- Span areaRowSpan = this.pixelArea.GetRowSpan(y);
-
- for (int x = 0; x < image.Width; x++)
- {
- ref byte luminance = ref areaRowSpan[x];
- ref TPixel pixel = ref imageRowSpan[x];
- var rgba = new Rgba32(luminance, luminance, luminance);
- pixel.PackFromRgba32(rgba);
- }
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void FillYCbCrImage(ImageFrame image)
- where TPixel : struct, IPixel
- {
- for (int y = 0; y < image.Height; y++)
- {
- Span imageRowSpan = image.GetPixelRowSpan(y);
- Span areaRowSpan = this.pixelArea.GetRowSpan(y);
- for (int x = 0, o = 0; x < image.Width; x++, o += 3)
- {
- ref byte yy = ref areaRowSpan[o];
- ref byte cb = ref areaRowSpan[o + 1];
- ref byte cr = ref areaRowSpan[o + 2];
- ref TPixel pixel = ref imageRowSpan[x];
- PdfJsYCbCrToRgbTables.PackYCbCr(ref pixel, yy, cb, cr);
- }
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void FillYcckImage(ImageFrame image)
- where TPixel : struct, IPixel
- {
- for (int y = 0; y < image.Height; y++)
- {
- Span imageRowSpan = image.GetPixelRowSpan(y);
- Span areaRowSpan = this.pixelArea.GetRowSpan(y);
- for (int x = 0, o = 0; x < image.Width; x++, o += 4)
- {
- ref byte yy = ref areaRowSpan[o];
- ref byte cb = ref areaRowSpan[o + 1];
- ref byte cr = ref areaRowSpan[o + 2];
- ref byte k = ref areaRowSpan[o + 3];
-
- ref TPixel pixel = ref imageRowSpan[x];
- PdfJsYCbCrToRgbTables.PackYccK(ref pixel, yy, cb, cr, k);
- }
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void FillCmykImage(ImageFrame image)
- where TPixel : struct, IPixel
- {
- for (int y = 0; y < image.Height; y++)
- {
- Span imageRowSpan = image.GetPixelRowSpan(y);
- Span areaRowSpan = this.pixelArea.GetRowSpan(y);
- for (int x = 0, o = 0; x < image.Width; x++, o += 4)
- {
- ref byte c = ref areaRowSpan[o];
- ref byte m = ref areaRowSpan[o + 1];
- ref byte cy = ref areaRowSpan[o + 2];
- ref byte k = ref areaRowSpan[o + 3];
-
- byte r = (byte)((c * k) / 255);
- byte g = (byte)((m * k) / 255);
- byte b = (byte)((cy * k) / 255);
-
- ref TPixel pixel = ref imageRowSpan[x];
- var rgba = new Rgba32(r, g, b);
- pixel.PackFromRgba32(rgba);
- }
- }
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void FillRgbImage(ImageFrame image)
- where TPixel : struct, IPixel
- {
- for (int y = 0; y < image.Height; y++)
- {
- Span imageRowSpan = image.GetPixelRowSpan(y);
- Span areaRowSpan = this.pixelArea.GetRowSpan(y);
-
- PixelOperations.Instance.PackFromRgb24Bytes(areaRowSpan, imageRowSpan, image.Width);
- }
+ tables[index] = new PdfJsHuffmanTable(this.configuration.MemoryManager, codeLengths, values);
}
///
@@ -938,7 +792,20 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
private ushort ReadUint16()
{
this.InputStream.Read(this.markerBuffer, 0, 2);
- return (ushort)((this.markerBuffer[0] << 8) | this.markerBuffer[1]);
+ return BinaryPrimitives.ReadUInt16BigEndian(this.markerBuffer);
+ }
+
+ private Image PostProcessIntoImage()
+ where TPixel : struct, IPixel
+ {
+ this.ColorSpace = this.DeduceJpegColorSpace();
+ this.AssignResolution();
+ using (var postProcessor = new JpegImagePostProcessor(this.configuration.MemoryManager, this))
+ {
+ var image = new Image(this.configuration, this.ImageWidth, this.ImageHeight, this.MetaData);
+ postProcessor.PostProcess(image.Frames.RootFrame);
+ return image;
+ }
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Png/IPngDecoderOptions.cs b/src/ImageSharp/Formats/Png/IPngDecoderOptions.cs
index e51cc084b..bd0b93205 100644
--- a/src/ImageSharp/Formats/Png/IPngDecoderOptions.cs
+++ b/src/ImageSharp/Formats/Png/IPngDecoderOptions.cs
@@ -1,11 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using System;
-using System.Collections.Generic;
-using System.IO;
using System.Text;
-using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Png
{
@@ -24,4 +20,4 @@ namespace SixLabors.ImageSharp.Formats.Png
///
Encoding TextEncoding { get; }
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs b/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs
index 1bfa4b063..3f48c4e26 100644
--- a/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs
+++ b/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs
@@ -45,4 +45,4 @@ namespace SixLabors.ImageSharp.Formats.Png
///
bool WriteGamma { get; }
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Png/ImageExtensions.cs b/src/ImageSharp/Formats/Png/ImageExtensions.cs
index f25d2bffe..a65845e02 100644
--- a/src/ImageSharp/Formats/Png/ImageExtensions.cs
+++ b/src/ImageSharp/Formats/Png/ImageExtensions.cs
@@ -37,4 +37,4 @@ namespace SixLabors.ImageSharp
where TPixel : struct, IPixel
=> source.Save(stream, encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(ImageFormats.Png));
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Png/PngChunk.cs b/src/ImageSharp/Formats/Png/PngChunk.cs
index b944b43a3..c91f39d7f 100644
--- a/src/ImageSharp/Formats/Png/PngChunk.cs
+++ b/src/ImageSharp/Formats/Png/PngChunk.cs
@@ -8,11 +8,14 @@ namespace SixLabors.ImageSharp.Formats.Png
///
/// Stores header information about a chunk.
///
- internal sealed class PngChunk
+ internal readonly struct PngChunk
{
- public PngChunk(int length)
+ public PngChunk(int length, PngChunkType type, IManagedByteBuffer data = null, uint crc = 0)
{
this.Length = length;
+ this.Type = type;
+ this.Data = data;
+ this.Crc = crc;
}
///
@@ -24,21 +27,31 @@ namespace SixLabors.ImageSharp.Formats.Png
public int Length { get; }
///
- /// Gets or sets the chunk type as string with 4 chars.
+ /// Gets the chunk type.
+ /// The value is the equal to the UInt32BigEndian encoding of its 4 ASCII characters.
///
- public string Type { get; set; }
+ public PngChunkType Type { get; }
///
- /// Gets or sets the data bytes appropriate to the chunk type, if any.
- /// This field can be of zero length.
+ /// Gets the data bytes appropriate to the chunk type, if any.
+ /// This field can be of zero length or null.
///
- public IManagedByteBuffer Data { get; set; }
+ public IManagedByteBuffer Data { get; }
///
- /// Gets or sets a CRC (Cyclic Redundancy Check) calculated on the preceding bytes in the chunk,
+ /// Gets a CRC (Cyclic Redundancy Check) calculated on the preceding bytes in the chunk,
/// including the chunk type code and chunk data fields, but not including the length field.
/// The CRC is always present, even for chunks containing no data
///
- public uint Crc { get; set; }
+ public uint Crc { get; }
+
+ ///
+ /// Gets a value indicating whether the given chunk is critical to decoding
+ ///
+ public bool IsCritical =>
+ this.Type == PngChunkType.Header ||
+ this.Type == PngChunkType.Palette ||
+ this.Type == PngChunkType.Data ||
+ this.Type == PngChunkType.End;
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Png/PngChunkTypes.cs b/src/ImageSharp/Formats/Png/PngChunkType.cs
similarity index 79%
rename from src/ImageSharp/Formats/Png/PngChunkTypes.cs
rename to src/ImageSharp/Formats/Png/PngChunkType.cs
index e22f4f0e7..51adc162b 100644
--- a/src/ImageSharp/Formats/Png/PngChunkTypes.cs
+++ b/src/ImageSharp/Formats/Png/PngChunkType.cs
@@ -4,57 +4,57 @@
namespace SixLabors.ImageSharp.Formats.Png
{
///
- /// Contains a list of possible chunk type identifiers.
+ /// Contains a list of of chunk types.
///
- internal static class PngChunkTypes
+ internal enum PngChunkType : uint
{
///
/// The first chunk in a png file. Can only exists once. Contains
/// common information like the width and the height of the image or
/// the used compression method.
///
- public const string Header = "IHDR";
+ Header = 0x49484452U, // IHDR
///
/// The PLTE chunk contains from 1 to 256 palette entries, each a three byte
/// series in the RGB format.
///
- public const string Palette = "PLTE";
+ Palette = 0x504C5445U, // PLTE
///
/// The IDAT chunk contains the actual image data. The image can contains more
/// than one chunk of this type. All chunks together are the whole image.
///
- public const string Data = "IDAT";
+ Data = 0x49444154U, // IDAT
///
/// This chunk must appear last. It marks the end of the PNG data stream.
/// The chunk's data field is empty.
///
- public const string End = "IEND";
+ End = 0x49454E44U, // IEND
///
/// This chunk specifies that the image uses simple transparency:
/// either alpha values associated with palette entries (for indexed-color images)
/// or a single transparent color (for grayscale and true color images).
///
- public const string PaletteAlpha = "tRNS";
+ PaletteAlpha = 0x74524E53U, // tRNS
///
/// Textual information that the encoder wishes to record with the image can be stored in
/// tEXt chunks. Each tEXt chunk contains a keyword and a text string.
///
- public const string Text = "tEXt";
+ Text = 0x74455874U, // tEXt
///
/// This chunk specifies the relationship between the image samples and the desired
/// display output intensity.
///
- public const string Gamma = "gAMA";
+ Gamma = 0x67414D41U, // gAMA
///
/// The pHYs chunk specifies the intended pixel size or aspect ratio for display of the image.
///
- public const string Physical = "pHYs";
+ Physical = 0x70485973U // pHYs
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Png/PngConstants.cs b/src/ImageSharp/Formats/Png/PngConstants.cs
index 8b4ad39f2..ff25e26b7 100644
--- a/src/ImageSharp/Formats/Png/PngConstants.cs
+++ b/src/ImageSharp/Formats/Png/PngConstants.cs
@@ -25,5 +25,21 @@ namespace SixLabors.ImageSharp.Formats.Png
/// The list of file extensions that equate to a png.
///
public static readonly IEnumerable FileExtensions = new[] { "png" };
+
+ public static readonly byte[] HeaderBytes = {
+ 0x89, // Set the high bit.
+ 0x50, // P
+ 0x4E, // N
+ 0x47, // G
+ 0x0D, // Line ending CRLF
+ 0x0A, // Line ending CRLF
+ 0x1A, // EOF
+ 0x0A // LF
+ };
+
+ ///
+ /// The header bytes as a big endian coded ulong.
+ ///
+ public const ulong HeaderValue = 0x89504E470D0A1A0AUL;
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Png/PngDecoder.cs b/src/ImageSharp/Formats/Png/PngDecoder.cs
index 57d45ecdd..39dfb1d0b 100644
--- a/src/ImageSharp/Formats/Png/PngDecoder.cs
+++ b/src/ImageSharp/Formats/Png/PngDecoder.cs
@@ -60,4 +60,4 @@ namespace SixLabors.ImageSharp.Formats.Png
return decoder.Identify(stream);
}
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
index b3904c0a3..8fefcb480 100644
--- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
@@ -71,11 +71,6 @@ namespace SixLabors.ImageSharp.Formats.Png
///
private readonly byte[] crcBuffer = new byte[4];
- ///
- /// Reusable buffer for reading char arrays.
- ///
- private readonly char[] chars = new char[4];
-
///
/// Reusable crc for validating chunks.
///
@@ -224,14 +219,14 @@ namespace SixLabors.ImageSharp.Formats.Png
{
switch (chunk.Type)
{
- case PngChunkTypes.Header:
+ case PngChunkType.Header:
this.ReadHeaderChunk(chunk.Data.Array);
this.ValidateHeader();
break;
- case PngChunkTypes.Physical:
+ case PngChunkType.Physical:
this.ReadPhysicalChunk(metadata, chunk.Data.Array);
break;
- case PngChunkTypes.Data:
+ case PngChunkType.Data:
if (image == null)
{
this.InitializeImage(metadata, out image);
@@ -241,33 +236,28 @@ namespace SixLabors.ImageSharp.Formats.Png
this.ReadScanlines(deframeStream.CompressedStream, image.Frames.RootFrame);
this.currentStream.Read(this.crcBuffer, 0, 4);
break;
- case PngChunkTypes.Palette:
+ case PngChunkType.Palette:
byte[] pal = new byte[chunk.Length];
Buffer.BlockCopy(chunk.Data.Array, 0, pal, 0, chunk.Length);
this.palette = pal;
break;
- case PngChunkTypes.PaletteAlpha:
+ case PngChunkType.PaletteAlpha:
byte[] alpha = new byte[chunk.Length];
Buffer.BlockCopy(chunk.Data.Array, 0, alpha, 0, chunk.Length);
this.paletteAlpha = alpha;
this.AssignTransparentMarkers(alpha);
break;
- case PngChunkTypes.Text:
+ case PngChunkType.Text:
this.ReadTextChunk(metadata, chunk.Data.Array, chunk.Length);
break;
- case PngChunkTypes.End:
+ case PngChunkType.End:
this.isEndChunkReached = true;
break;
}
}
finally
{
- // Data is rented in ReadChunkData()
- if (chunk.Data != null)
- {
- chunk.Data.Dispose();
- chunk.Data = null;
- }
+ chunk.Data?.Dispose(); // Data is rented in ReadChunkData()
}
}
}
@@ -303,31 +293,27 @@ namespace SixLabors.ImageSharp.Formats.Png
{
switch (chunk.Type)
{
- case PngChunkTypes.Header:
+ case PngChunkType.Header:
this.ReadHeaderChunk(chunk.Data.Array);
this.ValidateHeader();
break;
- case PngChunkTypes.Physical:
+ case PngChunkType.Physical:
this.ReadPhysicalChunk(metadata, chunk.Data.Array);
break;
- case PngChunkTypes.Data:
+ case PngChunkType.Data:
this.SkipChunkDataAndCrc(chunk);
break;
- case PngChunkTypes.Text:
+ case PngChunkType.Text:
this.ReadTextChunk(metadata, chunk.Data.Array, chunk.Length);
break;
- case PngChunkTypes.End:
+ case PngChunkType.End:
this.isEndChunkReached = true;
break;
}
}
finally
{
- // Data is rented in ReadChunkData()
- if (chunk.Data != null)
- {
- ArrayPool.Shared.Return(chunk.Data.Array);
- }
+ chunk.Data?.Dispose(); // Data is rented in ReadChunkData()
}
}
}
@@ -383,20 +369,6 @@ namespace SixLabors.ImageSharp.Formats.Png
return result;
}
- ///
- /// Returns a value indicating whether the given chunk is critical to decoding
- ///
- /// The chunk
- /// The
- private static bool IsCriticalChunk(PngChunk chunk)
- {
- return
- chunk.Type == PngChunkTypes.Header ||
- chunk.Type == PngChunkTypes.Palette ||
- chunk.Type == PngChunkTypes.Data ||
- chunk.Type == PngChunkTypes.End;
- }
-
///
/// Reads an integer value from 2 consecutive bytes in LSB order
///
@@ -1217,38 +1189,67 @@ namespace SixLabors.ImageSharp.Formats.Png
return false;
}
- chunk = new PngChunk(length);
-
- if (chunk.Length < 0 || chunk.Length > this.currentStream.Length - this.currentStream.Position)
+ while (length < 0 || length > (this.currentStream.Length - this.currentStream.Position))
{
// Not a valid chunk so we skip back all but one of the four bytes we have just read.
// That lets us read one byte at a time until we reach a known chunk.
this.currentStream.Position -= 3;
- return true;
+ length = this.ReadChunkLength();
+
+ if (length == -1)
+ {
+ chunk = default;
+
+ return false;
+ }
}
- this.ReadChunkType(chunk);
+ PngChunkType type = this.ReadChunkType();
- if (chunk.Type == PngChunkTypes.Data)
+ // NOTE: Reading the chunk data is the responsible of the caller
+ if (type == PngChunkType.Data)
{
+ chunk = new PngChunk(length, type);
+
return true;
}
- this.ReadChunkData(chunk);
- this.ReadChunkCrc(chunk);
+ chunk = new PngChunk(
+ length: length,
+ type: type,
+ data: this.ReadChunkData(length),
+ crc: this.ReadChunkCrc());
+
+ if (chunk.IsCritical)
+ {
+ this.ValidateChunk(chunk);
+ }
return true;
}
+ private void ValidateChunk(in PngChunk chunk)
+ {
+ this.crc.Reset();
+ this.crc.Update(this.chunkTypeBuffer);
+ this.crc.Update(chunk.Data.Span);
+
+ if (this.crc.Value != chunk.Crc)
+ {
+ string chunkTypeName = Encoding.UTF8.GetString(this.chunkTypeBuffer, 0, 4);
+
+ throw new ImageFormatException($"CRC Error. PNG {chunkTypeName} chunk is corrupt!");
+ }
+ }
+
///
/// Reads the cycle redundancy chunk from the data.
///
- /// The chunk.
///
/// Thrown if the input stream is not valid or corrupt.
///
- private void ReadChunkCrc(PngChunk chunk)
+ private uint ReadChunkCrc()
{
int numBytes = this.currentStream.Read(this.crcBuffer, 0, 4);
@@ -1257,22 +1258,13 @@ namespace SixLabors.ImageSharp.Formats.Png
throw new ImageFormatException("Image stream is not valid!");
}
- chunk.Crc = BinaryPrimitives.ReadUInt32BigEndian(this.crcBuffer);
-
- this.crc.Reset();
- this.crc.Update(this.chunkTypeBuffer);
- this.crc.Update(new ReadOnlySpan(chunk.Data.Array, 0, chunk.Length));
-
- if (this.crc.Value != chunk.Crc && IsCriticalChunk(chunk))
- {
- throw new ImageFormatException($"CRC Error. PNG {chunk.Type} chunk is corrupt!");
- }
+ return BinaryPrimitives.ReadUInt32BigEndian(this.crcBuffer);
}
///
/// Skips the chunk data and the cycle redundancy chunk read from the data.
///
- private void SkipChunkDataAndCrc(PngChunk chunk)
+ private void SkipChunkDataAndCrc(in PngChunk chunk)
{
this.currentStream.Skip(chunk.Length);
this.currentStream.Skip(4);
@@ -1281,35 +1273,33 @@ namespace SixLabors.ImageSharp.Formats.Png
///
/// Reads the chunk data from the stream.
///
- /// The chunk.
- private void ReadChunkData(PngChunk chunk)
+ /// The length of the chunk data to read.
+ private IManagedByteBuffer ReadChunkData(int length)
{
// We rent the buffer here to return it afterwards in Decode()
- chunk.Data = this.configuration.MemoryManager.AllocateCleanManagedByteBuffer(chunk.Length);
- this.currentStream.Read(chunk.Data.Array, 0, chunk.Length);
+ IManagedByteBuffer buffer = this.configuration.MemoryManager.AllocateCleanManagedByteBuffer(length);
+
+ this.currentStream.Read(buffer.Array, 0, length);
+
+ return buffer;
}
///
/// Identifies the chunk type from the chunk.
///
- /// The chunk.
///
/// Thrown if the input stream is not valid.
///
- private void ReadChunkType(PngChunk chunk)
+ private PngChunkType ReadChunkType()
{
int numBytes = this.currentStream.Read(this.chunkTypeBuffer, 0, 4);
+
if (numBytes >= 1 && numBytes <= 3)
{
throw new ImageFormatException("Image stream is not valid!");
}
- this.chars[0] = (char)this.chunkTypeBuffer[0];
- this.chars[1] = (char)this.chunkTypeBuffer[1];
- this.chars[2] = (char)this.chunkTypeBuffer[2];
- this.chars[3] = (char)this.chunkTypeBuffer[3];
-
- chunk.Type = new string(this.chars);
+ return (PngChunkType)BinaryPrimitives.ReadUInt32BigEndian(this.chunkTypeBuffer.AsSpan());
}
///
@@ -1359,4 +1349,4 @@ namespace SixLabors.ImageSharp.Formats.Png
this.scanline = temp;
}
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
index 676a93ee0..777ee1f54 100644
--- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
@@ -5,7 +5,6 @@ using System;
using System.Buffers.Binary;
using System.IO;
using System.Linq;
-using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats.Png.Filters;
using SixLabors.ImageSharp.Formats.Png.Zlib;
@@ -28,20 +27,15 @@ namespace SixLabors.ImageSharp.Formats.Png
private const int MaxBlockSize = 65535;
///
- /// Reusable buffer for writing chunk types.
+ /// Reusable buffer for writing general data.
///
- private readonly byte[] chunkTypeBuffer = new byte[4];
+ private readonly byte[] buffer = new byte[8];
///
/// Reusable buffer for writing chunk data.
///
private readonly byte[] chunkDataBuffer = new byte[16];
- ///
- /// Reusable buffer for writing int data.
- ///
- private readonly byte[] intBuffer = new byte[4];
-
///
/// Reusable crc for validating chunks.
///
@@ -173,17 +167,7 @@ namespace SixLabors.ImageSharp.Formats.Png
this.width = image.Width;
this.height = image.Height;
- // Write the png header.
- this.chunkDataBuffer[0] = 0x89; // Set the high bit.
- this.chunkDataBuffer[1] = 0x50; // P
- this.chunkDataBuffer[2] = 0x4E; // N
- this.chunkDataBuffer[3] = 0x47; // G
- this.chunkDataBuffer[4] = 0x0D; // Line ending CRLF
- this.chunkDataBuffer[5] = 0x0A; // Line ending CRLF
- this.chunkDataBuffer[6] = 0x1A; // EOF
- this.chunkDataBuffer[7] = 0x0A; // LF
-
- stream.Write(this.chunkDataBuffer, 0, 8);
+ stream.Write(PngConstants.HeaderBytes, 0, PngConstants.HeaderBytes.Length);
QuantizedFrame quantized = null;
if (this.pngColorType == PngColorType.Palette)
@@ -415,8 +399,8 @@ namespace SixLabors.ImageSharp.Formats.Png
/// The .
private void WriteHeaderChunk(Stream stream, in PngHeader header)
{
- BinaryPrimitives.WriteInt32BigEndian(new Span(this.chunkDataBuffer, 0, 4), header.Width);
- BinaryPrimitives.WriteInt32BigEndian(new Span(this.chunkDataBuffer, 4, 4), header.Height);
+ BinaryPrimitives.WriteInt32BigEndian(this.chunkDataBuffer.AsSpan(0, 4), header.Width);
+ BinaryPrimitives.WriteInt32BigEndian(this.chunkDataBuffer.AsSpan(4, 4), header.Height);
this.chunkDataBuffer[8] = header.BitDepth;
this.chunkDataBuffer[9] = (byte)header.ColorType;
@@ -424,7 +408,7 @@ namespace SixLabors.ImageSharp.Formats.Png
this.chunkDataBuffer[11] = header.FilterMethod;
this.chunkDataBuffer[12] = (byte)header.InterlaceMethod;
- this.WriteChunk(stream, PngChunkTypes.Header, this.chunkDataBuffer, 0, 13);
+ this.WriteChunk(stream, PngChunkType.Header, this.chunkDataBuffer, 0, 13);
}
///
@@ -443,7 +427,7 @@ namespace SixLabors.ImageSharp.Formats.Png
// Get max colors for bit depth.
int colorTableLength = (int)Math.Pow(2, header.BitDepth) * 3;
- var rgba = default(Rgba32);
+ Rgba32 rgba = default;
bool anyAlpha = false;
using (IManagedByteBuffer colorTable = this.memoryManager.AllocateManagedByteBuffer(colorTableLength))
@@ -475,12 +459,12 @@ namespace SixLabors.ImageSharp.Formats.Png
}
}
- this.WriteChunk(stream, PngChunkTypes.Palette, colorTable.Array, 0, colorTableLength);
+ this.WriteChunk(stream, PngChunkType.Palette, colorTable.Array, 0, colorTableLength);
// Write the transparency data
if (anyAlpha)
{
- this.WriteChunk(stream, PngChunkTypes.PaletteAlpha, alphaTable.Array, 0, pixelCount);
+ this.WriteChunk(stream, PngChunkType.PaletteAlpha, alphaTable.Array, 0, pixelCount);
}
}
}
@@ -500,12 +484,12 @@ namespace SixLabors.ImageSharp.Formats.Png
int dpmX = (int)Math.Round(image.MetaData.HorizontalResolution * 39.3700787D);
int dpmY = (int)Math.Round(image.MetaData.VerticalResolution * 39.3700787D);
- BinaryPrimitives.WriteInt32BigEndian(new Span(this.chunkDataBuffer, 0, 4), dpmX);
- BinaryPrimitives.WriteInt32BigEndian(new Span(this.chunkDataBuffer, 4, 4), dpmY);
+ BinaryPrimitives.WriteInt32BigEndian(this.chunkDataBuffer.AsSpan(0, 4), dpmX);
+ BinaryPrimitives.WriteInt32BigEndian(this.chunkDataBuffer.AsSpan(4, 4), dpmY);
this.chunkDataBuffer[8] = 1;
- this.WriteChunk(stream, PngChunkTypes.Physical, this.chunkDataBuffer, 0, 9);
+ this.WriteChunk(stream, PngChunkType.Physical, this.chunkDataBuffer, 0, 9);
}
}
@@ -520,9 +504,9 @@ namespace SixLabors.ImageSharp.Formats.Png
// 4-byte unsigned integer of gamma * 100,000.
uint gammaValue = (uint)(this.gamma * 100_000F);
- BinaryPrimitives.WriteUInt32BigEndian(new Span(this.chunkDataBuffer, 0, 4), gammaValue);
+ BinaryPrimitives.WriteUInt32BigEndian(this.chunkDataBuffer.AsSpan(0, 4), gammaValue);
- this.WriteChunk(stream, PngChunkTypes.Gamma, this.chunkDataBuffer, 0, 4);
+ this.WriteChunk(stream, PngChunkType.Gamma, this.chunkDataBuffer, 0, 4);
}
}
@@ -590,7 +574,7 @@ namespace SixLabors.ImageSharp.Formats.Png
length = MaxBlockSize;
}
- this.WriteChunk(stream, PngChunkTypes.Data, buffer, i * MaxBlockSize, length);
+ this.WriteChunk(stream, PngChunkType.Data, buffer, i * MaxBlockSize, length);
}
}
@@ -600,7 +584,7 @@ namespace SixLabors.ImageSharp.Formats.Png
/// The containing image data.
private void WriteEndChunk(Stream stream)
{
- this.WriteChunk(stream, PngChunkTypes.End, null);
+ this.WriteChunk(stream, PngChunkType.End, null);
}
///
@@ -609,7 +593,7 @@ namespace SixLabors.ImageSharp.Formats.Png
/// The to write to.
/// The type of chunk to write.
/// The containing data.
- private void WriteChunk(Stream stream, string type, byte[] data)
+ private void WriteChunk(Stream stream, PngChunkType type, byte[] data)
{
this.WriteChunk(stream, type, data, 0, data?.Length ?? 0);
}
@@ -622,33 +606,27 @@ namespace SixLabors.ImageSharp.Formats.Png
/// The containing data.
/// The position to offset the data at.
/// The of the data to write.
- private void WriteChunk(Stream stream, string type, byte[] data, int offset, int length)
+ private void WriteChunk(Stream stream, PngChunkType type, byte[] data, int offset, int length)
{
- BinaryPrimitives.WriteInt32BigEndian(this.intBuffer, length);
-
- stream.Write(this.intBuffer, 0, 4); // write the length
-
- this.chunkTypeBuffer[0] = (byte)type[0];
- this.chunkTypeBuffer[1] = (byte)type[1];
- this.chunkTypeBuffer[2] = (byte)type[2];
- this.chunkTypeBuffer[3] = (byte)type[3];
+ BinaryPrimitives.WriteInt32BigEndian(this.buffer, length);
+ BinaryPrimitives.WriteUInt32BigEndian(this.buffer.AsSpan(4, 4), (uint)type);
- stream.Write(this.chunkTypeBuffer, 0, 4);
+ stream.Write(this.buffer, 0, 8);
this.crc.Reset();
- this.crc.Update(this.chunkTypeBuffer);
+ this.crc.Update(this.buffer.AsSpan(4, 4)); // Write the type buffer
if (data != null && length > 0)
{
stream.Write(data, offset, length);
- this.crc.Update(new ReadOnlySpan(data, offset, length));
+ this.crc.Update(data.AsSpan(offset, length));
}
- BinaryPrimitives.WriteUInt32BigEndian(this.intBuffer, (uint)this.crc.Value);
+ BinaryPrimitives.WriteUInt32BigEndian(this.buffer, (uint)this.crc.Value);
- stream.Write(this.intBuffer, 0, 4); // write the crc
+ stream.Write(this.buffer, 0, 4); // write the crc
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Png/PngImageFormatDetector.cs b/src/ImageSharp/Formats/Png/PngImageFormatDetector.cs
index 837a147ed..36b43a470 100644
--- a/src/ImageSharp/Formats/Png/PngImageFormatDetector.cs
+++ b/src/ImageSharp/Formats/Png/PngImageFormatDetector.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers.Binary;
namespace SixLabors.ImageSharp.Formats.Png
{
@@ -26,16 +27,7 @@ namespace SixLabors.ImageSharp.Formats.Png
private bool IsSupportedFileFormat(ReadOnlySpan header)
{
- // TODO: This should be in constants
- return header.Length >= this.HeaderSize &&
- header[0] == 0x89 &&
- header[1] == 0x50 && // P
- header[2] == 0x4E && // N
- header[3] == 0x47 && // G
- header[4] == 0x0D && // CR
- header[5] == 0x0A && // LF
- header[6] == 0x1A && // EOF
- header[7] == 0x0A; // LF
+ return header.Length >= this.HeaderSize && BinaryPrimitives.ReadUInt64BigEndian(header) == PngConstants.HeaderValue;
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Png/Zlib/Adler32.cs b/src/ImageSharp/Formats/Png/Zlib/Adler32.cs
index 9c4e9e4b9..a06983b9e 100644
--- a/src/ImageSharp/Formats/Png/Zlib/Adler32.cs
+++ b/src/ImageSharp/Formats/Png/Zlib/Adler32.cs
@@ -78,10 +78,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
public long Value
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get
- {
- return this.checksum;
- }
+ get => this.checksum;
}
///
diff --git a/src/ImageSharp/Formats/Png/Zlib/IChecksum.cs b/src/ImageSharp/Formats/Png/Zlib/IChecksum.cs
index a2a57332b..da5deb49e 100644
--- a/src/ImageSharp/Formats/Png/Zlib/IChecksum.cs
+++ b/src/ImageSharp/Formats/Png/Zlib/IChecksum.cs
@@ -17,10 +17,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
///
/// Gets the data checksum computed so far.
///
- long Value
- {
- get;
- }
+ long Value { get; }
///
/// Resets the data checksum as if no update was ever called.
diff --git a/src/ImageSharp/Formats/Png/Zlib/ZlibDeflateStream.cs b/src/ImageSharp/Formats/Png/Zlib/ZlibDeflateStream.cs
index 51e6b4859..8e0bac938 100644
--- a/src/ImageSharp/Formats/Png/Zlib/ZlibDeflateStream.cs
+++ b/src/ImageSharp/Formats/Png/Zlib/ZlibDeflateStream.cs
@@ -113,26 +113,13 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
public override bool CanWrite => true;
///
- public override long Length
- {
- get
- {
- throw new NotSupportedException();
- }
- }
+ public override long Length => throw new NotSupportedException();
///
public override long Position
{
- get
- {
- throw new NotSupportedException();
- }
-
- set
- {
- throw new NotSupportedException();
- }
+ get => throw new NotSupportedException();
+ set => throw new NotSupportedException();
}
///
@@ -163,7 +150,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
public override void Write(byte[] buffer, int offset, int count)
{
this.deflateStream.Write(buffer, offset, count);
- this.adler32.Update(new ReadOnlySpan(buffer, offset, count));
+ this.adler32.Update(buffer.AsSpan(offset, count));
}
///
diff --git a/src/ImageSharp/IO/EndianBinaryReader.cs b/src/ImageSharp/IO/EndianBinaryReader.cs
deleted file mode 100644
index 6454ff250..000000000
--- a/src/ImageSharp/IO/EndianBinaryReader.cs
+++ /dev/null
@@ -1,364 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Buffers.Binary;
-using System.IO;
-using System.Text;
-
-namespace SixLabors.ImageSharp.IO
-{
- ///
- /// Equivalent of , but with either endianness.
- /// No data is buffered in the reader; the client may seek within the stream at will.
- ///
- internal class EndianBinaryReader : IDisposable
- {
- ///
- /// Buffer used for temporary storage before conversion into primitives
- ///
- private readonly byte[] storageBuffer = new byte[16];
-
- ///
- /// Whether or not this reader has been disposed yet.
- ///
- private bool disposed;
-
- ///
- /// The endianness used to read data
- ///
- private readonly Endianness endianness;
-
- ///
- /// Initializes a new instance of the class.
- /// Constructs a new binary reader with the given bit converter, reading
- /// to the given stream, using the given encoding.
- ///
- /// Endianness to use when reading data
- /// Stream to read data from
- public EndianBinaryReader(Endianness endianness, Stream stream)
- {
- Guard.NotNull(stream, nameof(stream));
- Guard.IsTrue(stream.CanRead, nameof(stream), "Stream isn't readable");
-
- this.BaseStream = stream;
- this.endianness = endianness;
- }
-
- ///
- /// Gets the underlying stream of the EndianBinaryReader.
- ///
- public Stream BaseStream { get; }
-
- ///
- /// Closes the reader, including the underlying stream.
- ///
- public void Close()
- {
- this.Dispose();
- }
-
- ///
- /// Seeks within the stream.
- ///
- /// Offset to seek to.
- /// Origin of seek operation.
- public void Seek(int offset, SeekOrigin origin)
- {
- this.CheckDisposed();
- this.BaseStream.Seek(offset, origin);
- }
-
- ///
- /// Reads a single byte from the stream.
- ///
- /// The byte read
- public byte ReadByte()
- {
- this.ReadInternal(this.storageBuffer, 1);
- return this.storageBuffer[0];
- }
-
- ///
- /// Reads a single signed byte from the stream.
- ///
- /// The byte read
- public sbyte ReadSByte()
- {
- this.ReadInternal(this.storageBuffer, 1);
- return unchecked((sbyte)this.storageBuffer[0]);
- }
-
- ///
- /// Reads a boolean from the stream. 1 byte is read.
- ///
- /// The boolean read
- public bool ReadBoolean()
- {
- this.ReadInternal(this.storageBuffer, 1);
-
- return this.storageBuffer[0] != 0;
- }
-
- ///
- /// Reads a 16-bit signed integer from the stream, using the bit converter
- /// for this reader. 2 bytes are read.
- ///
- /// The 16-bit integer read
- public short ReadInt16()
- {
- this.ReadInternal(this.storageBuffer, 2);
-
- return (this.endianness == Endianness.BigEndian)
- ? BinaryPrimitives.ReadInt16BigEndian(this.storageBuffer)
- : BinaryPrimitives.ReadInt16LittleEndian(this.storageBuffer);
- }
-
- ///
- /// Reads a 32-bit signed integer from the stream, using the bit converter
- /// for this reader. 4 bytes are read.
- ///
- /// The 32-bit integer read
- public int ReadInt32()
- {
- this.ReadInternal(this.storageBuffer, 4);
-
- return (this.endianness == Endianness.BigEndian)
- ? BinaryPrimitives.ReadInt32BigEndian(this.storageBuffer)
- : BinaryPrimitives.ReadInt32LittleEndian(this.storageBuffer);
- }
-
- ///
- /// Reads a 64-bit signed integer from the stream, using the bit converter
- /// for this reader. 8 bytes are read.
- ///
- /// The 64-bit integer read
- public long ReadInt64()
- {
- this.ReadInternal(this.storageBuffer, 8);
-
- return (this.endianness == Endianness.BigEndian)
- ? BinaryPrimitives.ReadInt64BigEndian(this.storageBuffer)
- : BinaryPrimitives.ReadInt64LittleEndian(this.storageBuffer);
- }
-
- ///
- /// Reads a 16-bit unsigned integer from the stream, using the bit converter
- /// for this reader. 2 bytes are read.
- ///
- /// The 16-bit unsigned integer read
- public ushort ReadUInt16()
- {
- this.ReadInternal(this.storageBuffer, 2);
-
- return (this.endianness == Endianness.BigEndian)
- ? BinaryPrimitives.ReadUInt16BigEndian(this.storageBuffer)
- : BinaryPrimitives.ReadUInt16LittleEndian(this.storageBuffer);
- }
-
- ///
- /// Reads a 32-bit unsigned integer from the stream, using the bit converter
- /// for this reader. 4 bytes are read.
- ///
- /// The 32-bit unsigned integer read
- public uint ReadUInt32()
- {
- this.ReadInternal(this.storageBuffer, 4);
-
- return (this.endianness == Endianness.BigEndian)
- ? BinaryPrimitives.ReadUInt32BigEndian(this.storageBuffer)
- : BinaryPrimitives.ReadUInt32LittleEndian(this.storageBuffer);
- }
-
- ///
- /// Reads a 64-bit unsigned integer from the stream, using the bit converter
- /// for this reader. 8 bytes are read.
- ///
- /// The 64-bit unsigned integer read
- public ulong ReadUInt64()
- {
- this.ReadInternal(this.storageBuffer, 8);
-
- return (this.endianness == Endianness.BigEndian)
- ? BinaryPrimitives.ReadUInt64BigEndian(this.storageBuffer)
- : BinaryPrimitives.ReadUInt64LittleEndian(this.storageBuffer);
- }
-
- ///
- /// Reads a single-precision floating-point value from the stream, using the bit converter
- /// for this reader. 4 bytes are read.
- ///
- /// The floating point value read
- public unsafe float ReadSingle()
- {
- int intValue = this.ReadInt32();
-
- return *((float*)&intValue);
- }
-
- ///
- /// Reads a double-precision floating-point value from the stream, using the bit converter
- /// for this reader. 8 bytes are read.
- ///
- /// The floating point value read
- public unsafe double ReadDouble()
- {
- long value = this.ReadInt64();
-
- return *((double*)&value);
- }
-
- ///
- /// Reads the specified number of bytes into the given buffer, starting at
- /// the given index.
- ///
- /// The buffer to copy data into
- /// The first index to copy data into
- /// The number of bytes to read
- /// The number of bytes actually read. This will only be less than
- /// the requested number of bytes if the end of the stream is reached.
- ///
- public int Read(byte[] buffer, int index, int count)
- {
- this.CheckDisposed();
-
- Guard.NotNull(this.storageBuffer, nameof(this.storageBuffer));
- Guard.MustBeGreaterThanOrEqualTo(index, 0, nameof(index));
- Guard.MustBeGreaterThanOrEqualTo(count, 0, nameof(count));
- Guard.IsFalse(count + index > buffer.Length, nameof(buffer.Length), "Not enough space in buffer for specified number of bytes starting at specified index.");
-
- int read = 0;
- while (count > 0)
- {
- int block = this.BaseStream.Read(buffer, index, count);
- if (block == 0)
- {
- return read;
- }
-
- index += block;
- read += block;
- count -= block;
- }
-
- return read;
- }
-
- ///
- /// Reads the specified number of bytes, returning them in a new byte array.
- /// If not enough bytes are available before the end of the stream, this
- /// method will return what is available.
- ///
- /// The number of bytes to read
- /// The bytes read
- public byte[] ReadBytes(int count)
- {
- this.CheckDisposed();
- Guard.MustBeGreaterThanOrEqualTo(count, 0, nameof(count));
-
- byte[] ret = new byte[count];
- int index = 0;
- while (index < count)
- {
- int read = this.BaseStream.Read(ret, index, count - index);
-
- // Stream has finished half way through. That's fine, return what we've got.
- if (read == 0)
- {
- byte[] copy = new byte[index];
- Buffer.BlockCopy(ret, 0, copy, 0, index);
- return copy;
- }
-
- index += read;
- }
-
- return ret;
- }
-
- ///
- /// Reads the specified number of bytes, returning them in a new byte array.
- /// If not enough bytes are available before the end of the stream, this
- /// method will throw an IOException.
- ///
- /// The number of bytes to read
- /// The bytes read
- public byte[] ReadBytesOrThrow(int count)
- {
- byte[] ret = new byte[count];
- this.ReadInternal(ret, count);
- return ret;
- }
-
- ///
- /// Disposes of the underlying stream.
- ///
- public void Dispose()
- {
- if (!this.disposed)
- {
- this.disposed = true;
- ((IDisposable)this.BaseStream).Dispose();
- }
- }
-
- ///
- /// Checks whether or not the reader has been disposed, throwing an exception if so.
- ///
- private void CheckDisposed()
- {
- if (this.disposed)
- {
- throw new ObjectDisposedException(nameof(EndianBinaryReader));
- }
- }
-
- ///
- /// Reads the given number of bytes from the stream, throwing an exception
- /// if they can't all be read.
- ///
- /// Buffer to read into
- /// Number of bytes to read
- private void ReadInternal(byte[] data, int size)
- {
- this.CheckDisposed();
- int index = 0;
- while (index < size)
- {
- int read = this.BaseStream.Read(data, index, size - index);
- if (read == 0)
- {
- throw new EndOfStreamException($"End of stream reached with {size - index} byte{(size - index == 1 ? "s" : string.Empty)} left to read.");
- }
-
- index += read;
- }
- }
-
- ///
- /// Reads the given number of bytes from the stream if possible, returning
- /// the number of bytes actually read, which may be less than requested if
- /// (and only if) the end of the stream is reached.
- ///
- /// Buffer to read into
- /// Number of bytes to read
- /// Number of bytes actually read
- private int TryReadInternal(byte[] data, int size)
- {
- this.CheckDisposed();
- int index = 0;
- while (index < size)
- {
- int read = this.BaseStream.Read(data, index, size - index);
- if (read == 0)
- {
- return index;
- }
-
- index += read;
- }
-
- return index;
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/IO/EndianBinaryWriter.cs b/src/ImageSharp/IO/EndianBinaryWriter.cs
deleted file mode 100644
index 9c42f0b69..000000000
--- a/src/ImageSharp/IO/EndianBinaryWriter.cs
+++ /dev/null
@@ -1,303 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Buffers.Binary;
-using System.IO;
-
-namespace SixLabors.ImageSharp.IO
-{
- ///
- /// Equivalent of , but with either endianness
- ///
- internal class EndianBinaryWriter : IDisposable
- {
- ///
- /// Buffer used for temporary storage during conversion from primitives
- ///
- private readonly byte[] buffer = new byte[16];
-
- ///
- /// The endianness used to write the data
- ///
- private readonly Endianness endianness;
-
- ///
- /// Whether or not this writer has been disposed yet.
- ///
- private bool disposed;
-
- ///
- /// Initializes a new instance of the class
- /// with the given bit converter, writing to the given stream, using the given encoding.
- ///
- /// Endianness to use when writing data
- /// Stream to write data to
- public EndianBinaryWriter(Endianness endianness, Stream stream)
- {
- Guard.NotNull(stream, nameof(stream));
- Guard.IsTrue(stream.CanWrite, nameof(stream), "Stream isn't writable");
-
- this.BaseStream = stream;
- this.endianness = endianness;
- }
-
- ///
- /// Gets the underlying stream of the EndianBinaryWriter.
- ///
- public Stream BaseStream { get; }
-
- ///
- /// Closes the writer, including the underlying stream.
- ///
- public void Close()
- {
- this.Dispose();
- }
-
- ///
- /// Flushes the underlying stream.
- ///
- public void Flush()
- {
- this.CheckDisposed();
- this.BaseStream.Flush();
- }
-
- ///
- /// Seeks within the stream.
- ///
- /// Offset to seek to.
- /// Origin of seek operation.
- public void Seek(int offset, SeekOrigin origin)
- {
- this.CheckDisposed();
- this.BaseStream.Seek(offset, origin);
- }
-
- ///
- /// Writes a boolean value to the stream. 1 byte is written.
- ///
- /// The value to write
- public void Write(bool value)
- {
- this.buffer[0] = value ? (byte)1 : (byte)0;
-
- this.WriteInternal(this.buffer, 1);
- }
-
- ///
- /// Writes a 16-bit signed integer to the stream, using the bit converter
- /// for this writer. 2 bytes are written.
- ///
- /// The value to write
- public void Write(short value)
- {
- if (this.endianness == Endianness.BigEndian)
- {
- BinaryPrimitives.WriteInt16BigEndian(this.buffer, value);
- }
- else
- {
- BinaryPrimitives.WriteInt16LittleEndian(this.buffer, value);
- }
-
- this.WriteInternal(this.buffer, 2);
- }
-
- ///
- /// Writes a 32-bit signed integer to the stream, using the bit converter
- /// for this writer. 4 bytes are written.
- ///
- /// The value to write
- public void Write(int value)
- {
- if (this.endianness == Endianness.BigEndian)
- {
- BinaryPrimitives.WriteInt32BigEndian(this.buffer, value);
- }
- else
- {
- BinaryPrimitives.WriteInt32LittleEndian(this.buffer, value);
- }
-
- this.WriteInternal(this.buffer, 4);
- }
-
- ///
- /// Writes a 64-bit signed integer to the stream, using the bit converter
- /// for this writer. 8 bytes are written.
- ///
- /// The value to write
- public void Write(long value)
- {
- if (this.endianness == Endianness.BigEndian)
- {
- BinaryPrimitives.WriteInt64BigEndian(this.buffer, value);
- }
- else
- {
- BinaryPrimitives.WriteInt64LittleEndian(this.buffer, value);
- }
-
- this.WriteInternal(this.buffer, 8);
- }
-
- ///
- /// Writes a 16-bit unsigned integer to the stream, using the bit converter
- /// for this writer. 2 bytes are written.
- ///
- /// The value to write
- public void Write(ushort value)
- {
- if (this.endianness == Endianness.BigEndian)
- {
- BinaryPrimitives.WriteUInt16BigEndian(this.buffer, value);
- }
- else
- {
- BinaryPrimitives.WriteUInt16LittleEndian(this.buffer, value);
- }
-
- this.WriteInternal(this.buffer, 2);
- }
-
- ///
- /// Writes a 32-bit unsigned integer to the stream, using the bit converter
- /// for this writer. 4 bytes are written.
- ///
- /// The value to write
- public void Write(uint value)
- {
- if (this.endianness == Endianness.BigEndian)
- {
- BinaryPrimitives.WriteUInt32BigEndian(this.buffer, value);
- }
- else
- {
- BinaryPrimitives.WriteUInt32LittleEndian(this.buffer, value);
- }
-
- this.WriteInternal(this.buffer, 4);
- }
-
- ///
- /// Writes a 64-bit unsigned integer to the stream, using the bit converter
- /// for this writer. 8 bytes are written.
- ///
- /// The value to write
- public void Write(ulong value)
- {
- if (this.endianness == Endianness.BigEndian)
- {
- BinaryPrimitives.WriteUInt64BigEndian(this.buffer, value);
- }
- else
- {
- BinaryPrimitives.WriteUInt64LittleEndian(this.buffer, value);
- }
-
- this.WriteInternal(this.buffer, 8);
- }
-
- ///
- /// Writes a single-precision floating-point value to the stream, using the bit converter
- /// for this writer. 4 bytes are written.
- ///
- /// The value to write
- public unsafe void Write(float value)
- {
- this.Write(*((int*)&value));
- }
-
- ///
- /// Writes a double-precision floating-point value to the stream, using the bit converter
- /// for this writer. 8 bytes are written.
- ///
- /// The value to write
- public unsafe void Write(double value)
- {
- this.Write(*((long*)&value));
- }
-
- ///
- /// Writes a signed byte to the stream.
- ///
- /// The value to write
- public void Write(byte value)
- {
- this.buffer[0] = value;
- this.WriteInternal(this.buffer, 1);
- }
-
- ///
- /// Writes an unsigned byte to the stream.
- ///
- /// The value to write
- public void Write(sbyte value)
- {
- this.buffer[0] = unchecked((byte)value);
- this.WriteInternal(this.buffer, 1);
- }
-
- ///
- /// Writes an array of bytes to the stream.
- ///
- /// The values to write
- /// value is null
- public void Write(byte[] value)
- {
- Guard.NotNull(value, nameof(value));
- this.WriteInternal(value, value.Length);
- }
-
- ///
- /// Writes a portion of an array of bytes to the stream.
- ///
- /// An array containing the bytes to write
- /// The index of the first byte to write within the array
- /// The number of bytes to write
- /// value is null
- public void Write(byte[] value, int offset, int count)
- {
- this.CheckDisposed();
- this.BaseStream.Write(value, offset, count);
- }
-
- ///
- /// Disposes of the underlying stream.
- ///
- public void Dispose()
- {
- if (!this.disposed)
- {
- this.Flush();
- this.disposed = true;
- ((IDisposable)this.BaseStream).Dispose();
- }
- }
-
- ///
- /// Checks whether or not the writer has been disposed, throwing an exception if so.
- ///
- private void CheckDisposed()
- {
- if (this.disposed)
- {
- throw new ObjectDisposedException(nameof(EndianBinaryWriter));
- }
- }
-
- ///
- /// Writes the specified number of bytes from the start of the given byte array,
- /// after checking whether or not the writer has been disposed.
- ///
- /// The array of bytes to write from
- /// The number of bytes to write
- private void WriteInternal(byte[] bytes, int length)
- {
- this.CheckDisposed();
- this.BaseStream.Write(bytes, 0, length);
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Image.LoadPixelData.cs b/src/ImageSharp/Image.LoadPixelData.cs
index b0bb03580..0179e62ac 100644
--- a/src/ImageSharp/Image.LoadPixelData.cs
+++ b/src/ImageSharp/Image.LoadPixelData.cs
@@ -99,7 +99,7 @@ namespace SixLabors.ImageSharp
public static Image LoadPixelData(Configuration config, TPixel[] data, int width, int height)
where TPixel : struct, IPixel
{
- return LoadPixelData(config, new Span(data), width, height);
+ return LoadPixelData(config, data.AsSpan(), width, height);
}
///
diff --git a/src/ImageSharp/ImageExtensions.cs b/src/ImageSharp/ImageExtensions.cs
index 1f7e418ad..2cdb71fc0 100644
--- a/src/ImageSharp/ImageExtensions.cs
+++ b/src/ImageSharp/ImageExtensions.cs
@@ -143,7 +143,7 @@ namespace SixLabors.ImageSharp
/// Thrown if the stream is null.
public static void SavePixelData(this ImageFrame source, TPixel[] buffer)
where TPixel : struct, IPixel
- => SavePixelData(source, new Span(buffer));
+ => SavePixelData(source, buffer.AsSpan());
///
/// Saves the raw image pixels to a byte array in row-major order.
diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj
index 8bb0442a1..63b1f6170 100644
--- a/src/ImageSharp/ImageSharp.csproj
+++ b/src/ImageSharp/ImageSharp.csproj
@@ -86,9 +86,6 @@
TextTemplatingFileGenerator
-
-
-
True
diff --git a/src/ImageSharp/Memory/BasicArrayBuffer.cs b/src/ImageSharp/Memory/BasicArrayBuffer.cs
index a4810d037..dd2f7ef86 100644
--- a/src/ImageSharp/Memory/BasicArrayBuffer.cs
+++ b/src/ImageSharp/Memory/BasicArrayBuffer.cs
@@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.Memory
public int Length { get; }
- public Span Span => new Span(this.Array, 0, this.Length);
+ public Span Span => this.Array.AsSpan(0, this.Length);
///
/// Returns a reference to specified element of the buffer.
diff --git a/src/ImageSharp/MetaData/ImageMetaData.cs b/src/ImageSharp/MetaData/ImageMetaData.cs
index 9613e9b46..af3cc5f5f 100644
--- a/src/ImageSharp/MetaData/ImageMetaData.cs
+++ b/src/ImageSharp/MetaData/ImageMetaData.cs
@@ -43,17 +43,15 @@ namespace SixLabors.ImageSharp.MetaData
///
/// The other to create this instance from.
///
- internal ImageMetaData(ImageMetaData other)
+ private ImageMetaData(ImageMetaData other)
{
- DebugGuard.NotNull(other, nameof(other));
-
this.HorizontalResolution = other.HorizontalResolution;
this.VerticalResolution = other.VerticalResolution;
this.RepeatCount = other.RepeatCount;
foreach (ImageProperty property in other.Properties)
{
- this.Properties.Add(new ImageProperty(property));
+ this.Properties.Add(property);
}
this.ExifProfile = other.ExifProfile != null
@@ -114,7 +112,6 @@ namespace SixLabors.ImageSharp.MetaData
///
/// Gets the list of properties for storing meta information about this image.
///
- /// A list of image properties.
public IList Properties { get; } = new List();
///
@@ -123,6 +120,29 @@ namespace SixLabors.ImageSharp.MetaData
///
public ushort RepeatCount { get; set; }
+ ///
+ /// Looks up a property with the provided name.
+ ///
+ /// The name of the property to lookup.
+ /// The property, if found, with the provided name.
+ /// Whether the property was found.
+ internal bool TryGetProperty(string name, out ImageProperty result)
+ {
+ foreach (ImageProperty property in this.Properties)
+ {
+ if (property.Name == name)
+ {
+ result = property;
+
+ return true;
+ }
+ }
+
+ result = default;
+
+ return false;
+ }
+
///
/// Clones this into a new instance
///
diff --git a/src/ImageSharp/MetaData/ImageProperty.cs b/src/ImageSharp/MetaData/ImageProperty.cs
index e4f60e8b3..c67c1f3cf 100644
--- a/src/ImageSharp/MetaData/ImageProperty.cs
+++ b/src/ImageSharp/MetaData/ImageProperty.cs
@@ -25,21 +25,6 @@ namespace SixLabors.ImageSharp.MetaData
this.Value = value;
}
- ///
- /// Initializes a new instance of the struct
- /// by making a copy from another property.
- ///
- ///
- /// The other to create this instance from.
- ///
- internal ImageProperty(ImageProperty other)
- {
- DebugGuard.NotNull(other, nameof(other));
-
- this.Name = other.Name;
- this.Value = other.Value;
- }
-
///
/// Gets the name of this indicating which kind of
/// information this property stores.
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccFormulaCurveElement.cs b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccFormulaCurveElement.cs
index 5d931039c..d168c5c28 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccFormulaCurveElement.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccFormulaCurveElement.cs
@@ -90,4 +90,4 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return this.Equals((IccCurveSegment)other);
}
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccOneDimensionalCurve.cs b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccOneDimensionalCurve.cs
index d916486db..a7ce0e809 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccOneDimensionalCurve.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccOneDimensionalCurve.cs
@@ -7,7 +7,7 @@ using System.Linq;
namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
///
- /// A one dimensional curve
+ /// A one dimensional ICC curve.
///
internal sealed class IccOneDimensionalCurve : IEquatable
{
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccParametricCurve.cs b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccParametricCurve.cs
index ee8b4c731..9c3f8aa5e 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccParametricCurve.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccParametricCurve.cs
@@ -125,7 +125,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public bool Equals(IccParametricCurve other)
{
- if (ReferenceEquals(null, other))
+ if (other == null)
{
return false;
}
@@ -148,7 +148,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj == null)
{
return false;
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccResponseCurve.cs b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccResponseCurve.cs
index 8a7162198..02a817b8c 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccResponseCurve.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccResponseCurve.cs
@@ -49,7 +49,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public bool Equals(IccResponseCurve other)
{
- if (ReferenceEquals(null, other))
+ if (other == null)
{
return false;
}
@@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj == null)
{
return false;
}
@@ -86,8 +86,8 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
unchecked
{
int hashCode = (int)this.CurveType;
- hashCode = (hashCode * 397) ^ (this.XyzValues != null ? this.XyzValues.GetHashCode() : 0);
- hashCode = (hashCode * 397) ^ (this.ResponseArrays != null ? this.ResponseArrays.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (this.XyzValues?.GetHashCode() ?? 0);
+ hashCode = (hashCode * 397) ^ (this.ResponseArrays?.GetHashCode() ?? 0);
return hashCode;
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Curves.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Curves.cs
index 0ea404ad9..ee91ad7a1 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Curves.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Curves.cs
@@ -191,7 +191,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// The curve data
private IccTagDataEntry[] ReadCurves(int count)
{
- IccTagDataEntry[] tdata = new IccTagDataEntry[count];
+ var tdata = new IccTagDataEntry[count];
for (int i = 0; i < count; i++)
{
IccTypeSignature type = this.ReadTagDataEntryHeader();
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Primitives.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Primitives.cs
index 794d77ba1..538a31d6a 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Primitives.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Primitives.cs
@@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// the value
public ushort ReadUInt16()
{
- return BinaryPrimitives.ReadUInt16BigEndian(new Span(this.data, this.AddIndex(2), 2));
+ return BinaryPrimitives.ReadUInt16BigEndian(this.data.AsSpan(this.AddIndex(2), 2));
}
///
@@ -27,7 +27,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// the value
public short ReadInt16()
{
- return BinaryPrimitives.ReadInt16BigEndian(new Span(this.data, this.AddIndex(2), 2));
+ return BinaryPrimitives.ReadInt16BigEndian(this.data.AsSpan(this.AddIndex(2), 2));
}
///
@@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// the value
public uint ReadUInt32()
{
- return BinaryPrimitives.ReadUInt32BigEndian(new Span(this.data, this.AddIndex(4), 4));
+ return BinaryPrimitives.ReadUInt32BigEndian(this.data.AsSpan(this.AddIndex(4), 4));
}
///
@@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// the value
public int ReadInt32()
{
- return BinaryPrimitives.ReadInt32BigEndian(new Span(this.data, this.AddIndex(4), 4));
+ return BinaryPrimitives.ReadInt32BigEndian(this.data.AsSpan(this.AddIndex(4), 4));
}
///
@@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// the value
public ulong ReadUInt64()
{
- return BinaryPrimitives.ReadUInt64BigEndian(new Span(this.data, this.AddIndex(8), 8));
+ return BinaryPrimitives.ReadUInt64BigEndian(this.data.AsSpan(this.AddIndex(8), 8));
}
///
@@ -63,11 +63,11 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// the value
public long ReadInt64()
{
- return BinaryPrimitives.ReadInt64BigEndian(new Span(this.data, this.AddIndex(8), 8));
+ return BinaryPrimitives.ReadInt64BigEndian(this.data.AsSpan(this.AddIndex(8), 8));
}
///
- /// Reads a float
+ /// Reads a float.
///
/// the value
public unsafe float ReadSingle()
@@ -89,7 +89,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
///
- /// Reads an ASCII encoded string
+ /// Reads an ASCII encoded string.
///
/// number of bytes to read
/// The value as a string
@@ -114,7 +114,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
///
- /// Reads an UTF-16 big-endian encoded string
+ /// Reads an UTF-16 big-endian encoded string.
///
/// number of bytes to read
/// The value as a string
@@ -131,34 +131,25 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
///
- /// Reads a signed 32bit number with 1 sign bit, 15 value bits and 16 fractional bits
+ /// Reads a signed 32bit number with 1 sign bit, 15 value bits and 16 fractional bits.
///
/// The number as double
- public float ReadFix16()
- {
- return this.ReadInt32() / 65536f;
- }
+ public float ReadFix16() => this.ReadInt32() / 65536f;
///
- /// Reads an unsigned 32bit number with 16 value bits and 16 fractional bits
+ /// Reads an unsigned 32bit number with 16 value bits and 16 fractional bits.
///
/// The number as double
- public float ReadUFix16()
- {
- return this.ReadUInt32() / 65536f;
- }
+ public float ReadUFix16() => this.ReadUInt32() / 65536f;
///
- /// Reads an unsigned 16bit number with 1 value bit and 15 fractional bits
+ /// Reads an unsigned 16bit number with 1 value bit and 15 fractional bits.
///
/// The number as double
- public float ReadU1Fix15()
- {
- return this.ReadUInt16() / 32768f;
- }
+ public float ReadU1Fix15() => this.ReadUInt16() / 32768f;
///
- /// Reads an unsigned 16bit number with 8 value bits and 8 fractional bits
+ /// Reads an unsigned 16bit number with 8 value bits and 8 fractional bits.
///
/// The number as double
public float ReadUFix8()
@@ -167,7 +158,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
///
- /// Reads a number of bytes and advances the index
+ /// Reads a number of bytes and advances the index.
///
/// The number of bytes to read
/// The read bytes
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs
index 5c14448fa..e41d9b3b8 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs
@@ -183,7 +183,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
public IccColorantTableTagDataEntry ReadColorantTableTagDataEntry()
{
uint colorantCount = this.ReadUInt32();
- IccColorantTableEntry[] cdata = new IccColorantTableEntry[colorantCount];
+ var cdata = new IccColorantTableEntry[colorantCount];
for (int i = 0; i < colorantCount; i++)
{
cdata[i] = this.ReadColorantTableEntry();
@@ -265,7 +265,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
ushort outTableCount = this.ReadUInt16();
// Input LUT
- IccLut[] inValues = new IccLut[inChCount];
+ var inValues = new IccLut[inChCount];
byte[] gridPointCount = new byte[inChCount];
for (int i = 0; i < inChCount; i++)
{
@@ -277,7 +277,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
IccClut clut = this.ReadClut16(inChCount, outChCount, gridPointCount);
// Output LUT
- IccLut[] outValues = new IccLut[outChCount];
+ var outValues = new IccLut[outChCount];
for (int i = 0; i < outChCount; i++)
{
outValues[i] = this.ReadLut16(outTableCount);
@@ -300,7 +300,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
float[,] matrix = this.ReadMatrix(3, 3, false);
// Input LUT
- IccLut[] inValues = new IccLut[inChCount];
+ var inValues = new IccLut[inChCount];
byte[] gridPointCount = new byte[inChCount];
for (int i = 0; i < inChCount; i++)
{
@@ -312,7 +312,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
IccClut clut = this.ReadClut8(inChCount, outChCount, gridPointCount);
// Output LUT
- IccLut[] outValues = new IccLut[outChCount];
+ var outValues = new IccLut[outChCount];
for (int i = 0; i < outChCount; i++)
{
outValues[i] = this.ReadLut8();
@@ -463,9 +463,9 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
uint recordCount = this.ReadUInt32();
this.ReadUInt32(); // Record size (always 12)
- IccLocalizedString[] text = new IccLocalizedString[recordCount];
+ var text = new IccLocalizedString[recordCount];
- CultureInfo[] culture = new CultureInfo[recordCount];
+ var culture = new CultureInfo[recordCount];
uint[] length = new uint[recordCount];
uint[] offset = new uint[recordCount];
@@ -531,13 +531,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
ushort outChannelCount = this.ReadUInt16();
uint elementCount = this.ReadUInt32();
- IccPositionNumber[] positionTable = new IccPositionNumber[elementCount];
+ var positionTable = new IccPositionNumber[elementCount];
for (int i = 0; i < elementCount; i++)
{
positionTable[i] = this.ReadPositionNumber();
}
- IccMultiProcessElement[] elements = new IccMultiProcessElement[elementCount];
+ var elements = new IccMultiProcessElement[elementCount];
for (int i = 0; i < elementCount; i++)
{
this.currentIndex = (int)positionTable[i].Offset + start;
@@ -559,7 +559,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
string prefix = this.ReadAsciiString(32);
string suffix = this.ReadAsciiString(32);
- IccNamedColor[] colors = new IccNamedColor[colorCount];
+ var colors = new IccNamedColor[colorCount];
for (int i = 0; i < colorCount; i++)
{
colors[i] = this.ReadNamedColor(coordCount);
@@ -584,7 +584,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
public IccProfileSequenceDescTagDataEntry ReadProfileSequenceDescTagDataEntry()
{
uint count = this.ReadUInt32();
- IccProfileDescription[] description = new IccProfileDescription[count];
+ var description = new IccProfileDescription[count];
for (int i = 0; i < count; i++)
{
description[i] = this.ReadProfileDescription();
@@ -601,13 +601,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
int start = this.currentIndex - 8; // 8 is the tag header size
uint count = this.ReadUInt32();
- IccPositionNumber[] table = new IccPositionNumber[count];
+ var table = new IccPositionNumber[count];
for (int i = 0; i < count; i++)
{
table[i] = this.ReadPositionNumber();
}
- IccProfileSequenceIdentifier[] entries = new IccProfileSequenceIdentifier[count];
+ var entries = new IccProfileSequenceIdentifier[count];
for (int i = 0; i < count; i++)
{
this.currentIndex = (int)(start + table[i].Offset);
@@ -636,7 +636,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
offset[i] = this.ReadUInt32();
}
- IccResponseCurve[] curves = new IccResponseCurve[measurmentCount];
+ var curves = new IccResponseCurve[measurmentCount];
for (int i = 0; i < measurmentCount; i++)
{
this.currentIndex = (int)(start + offset[i]);
@@ -783,7 +783,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
public IccXyzTagDataEntry ReadXyzTagDataEntry(uint size)
{
uint count = (size - 8) / 12;
- Vector3[] arrayData = new Vector3[count];
+ var arrayData = new Vector3[count];
for (int i = 0; i < count; i++)
{
arrayData[i] = this.ReadXyzNumber();
@@ -864,7 +864,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
var flags = (IccScreeningFlag)this.ReadInt32();
uint channelCount = this.ReadUInt32();
- IccScreeningChannel[] channels = new IccScreeningChannel[channelCount];
+ var channels = new IccScreeningChannel[channelCount];
for (int i = 0; i < channels.Length; i++)
{
channels[i] = this.ReadScreeningChannel();
@@ -902,4 +902,4 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return new IccUcrBgTagDataEntry(ucrCurve, bgCurve, description);
}
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs
index 9ee4f0004..18280faaf 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs
@@ -206,8 +206,11 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
public int WriteColorantTableTagDataEntry(IccColorantTableTagDataEntry value)
{
int count = this.WriteUInt32((uint)value.ColorantData.Length);
- foreach (IccColorantTableEntry colorant in value.ColorantData)
+
+ for (int i = 0; i < value.ColorantData.Length; i++)
{
+ ref IccColorantTableEntry colorant = ref value.ColorantData[i];
+
count += this.WriteAsciiString(colorant.Name, 32, true);
count += this.WriteUInt16(colorant.Pcs1);
count += this.WriteUInt16(colorant.Pcs2);
@@ -683,8 +686,11 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
public int WriteProfileSequenceDescTagDataEntry(IccProfileSequenceDescTagDataEntry value)
{
int count = this.WriteUInt32((uint)value.Descriptions.Length);
- foreach (IccProfileDescription desc in value.Descriptions)
+
+ for (int i = 0; i < value.Descriptions.Length; i++)
{
+ ref IccProfileDescription desc = ref value.Descriptions[i];
+
count += this.WriteProfileDescription(desc);
}
@@ -706,13 +712,15 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
// Jump over position table
long tablePosition = this.dataStream.Position;
this.dataStream.Position += length * 8;
- IccPositionNumber[] table = new IccPositionNumber[length];
+ var table = new IccPositionNumber[length];
for (int i = 0; i < length; i++)
{
+ ref IccProfileSequenceIdentifier sequenceIdentifier = ref value.Data[i];
+
uint offset = (uint)(this.dataStream.Position - start);
- int size = this.WriteProfileId(value.Data[i].Id);
- size += this.WriteTagDataEntry(new IccMultiLocalizedUnicodeTagDataEntry(value.Data[i].Description));
+ int size = this.WriteProfileId(sequenceIdentifier.Id);
+ size += this.WriteTagDataEntry(new IccMultiLocalizedUnicodeTagDataEntry(sequenceIdentifier.Description));
size += this.WritePadding();
table[i] = new IccPositionNumber(offset, (uint)size);
count += size;
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Exceptions/InvalidIccProfileException.cs b/src/ImageSharp/MetaData/Profiles/ICC/Exceptions/InvalidIccProfileException.cs
index d867edbeb..f69067041 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/Exceptions/InvalidIccProfileException.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/Exceptions/InvalidIccProfileException.cs
@@ -10,13 +10,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public class InvalidIccProfileException : Exception
{
- ///
- /// Initializes a new instance of the class.
- ///
- public InvalidIccProfileException()
- {
- }
-
///
/// Initializes a new instance of the class.
///
@@ -37,4 +30,4 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
}
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/IccReader.cs b/src/ImageSharp/MetaData/Profiles/ICC/IccReader.cs
index ea84113fd..ca7c73620 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/IccReader.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/IccReader.cs
@@ -84,7 +84,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
private IccTagDataEntry[] ReadTagData(IccDataReader reader)
{
IccTagTableEntry[] tagTable = this.ReadTagTable(reader);
- IccTagDataEntry[] entries = new IccTagDataEntry[tagTable.Length];
+ var entries = new IccTagDataEntry[tagTable.Length];
var store = new Dictionary();
for (int i = 0; i < tagTable.Length; i++)
{
@@ -112,7 +112,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
reader.SetIndex(128); // An ICC header is 128 bytes long
uint tagCount = reader.ReadUInt32();
- IccTagTableEntry[] table = new IccTagTableEntry[tagCount];
+ var table = new IccTagTableEntry[tagCount];
for (int i = 0; i < tagCount; i++)
{
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/IccTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/IccTagDataEntry.cs
index 4789a69fe..1b0d041b6 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/IccTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/IccTagDataEntry.cs
@@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj == null)
{
return false;
}
@@ -54,8 +54,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return true;
}
- var entry = obj as IccTagDataEntry;
- return entry != null && this.Equals(entry);
+ return obj is IccTagDataEntry entry && this.Equals(entry);
}
///
@@ -70,7 +69,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public virtual bool Equals(IccTagDataEntry other)
{
- if (ReferenceEquals(null, other))
+ if (other == null)
{
return false;
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccCurveSetProcessElement.cs b/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccCurveSetProcessElement.cs
index d04869548..0aa030684 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccCurveSetProcessElement.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccCurveSetProcessElement.cs
@@ -44,4 +44,4 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return this.Equals((IccMultiProcessElement)other);
}
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccMultiProcessElement.cs b/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccMultiProcessElement.cs
index 59acd0eb7..3da482b1f 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccMultiProcessElement.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/MultiProcessElements/IccMultiProcessElement.cs
@@ -27,7 +27,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
///
- /// Gets the signature of this element
+ /// Gets the signature of this element,
///
public IccMultiProcessElementSignature Signature { get; }
@@ -37,7 +37,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
public int InputChannelCount { get; }
///
- /// Gets the number of output channels
+ /// Gets the number of output channels.
///
public int OutputChannelCount { get; }
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccChromaticityTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccChromaticityTagDataEntry.cs
index 6d838558a..b400e1bd7 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccChromaticityTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccChromaticityTagDataEntry.cs
@@ -82,8 +82,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccChromaticityTagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccChromaticityTagDataEntry entry && this.Equals(entry);
}
///
@@ -105,7 +104,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj == null)
{
return false;
}
@@ -125,7 +124,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
int hashCode = base.GetHashCode();
hashCode = (hashCode * 397) ^ (int)this.ColorantType;
- hashCode = (hashCode * 397) ^ (this.ChannelValues != null ? this.ChannelValues.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (this.ChannelValues?.GetHashCode() ?? 0);
return hashCode;
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantOrderTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantOrderTagDataEntry.cs
index 56af95a16..73024ee12 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantOrderTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantOrderTagDataEntry.cs
@@ -43,14 +43,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccColorantOrderTagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccColorantOrderTagDataEntry entry && this.Equals(entry);
}
///
public bool Equals(IccColorantOrderTagDataEntry other)
{
- if (ReferenceEquals(null, other))
+ if (other == null)
{
return false;
}
@@ -66,7 +65,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj == null)
{
return false;
}
@@ -76,7 +75,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return true;
}
- return obj is IccColorantOrderTagDataEntry && this.Equals((IccColorantOrderTagDataEntry)obj);
+ return obj is IccColorantOrderTagDataEntry other && this.Equals(other);
}
///
@@ -84,7 +83,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
unchecked
{
- return (base.GetHashCode() * 397) ^ (this.ColorantNumber != null ? this.ColorantNumber.GetHashCode() : 0);
+ return (base.GetHashCode() * 397) ^ (this.ColorantNumber?.GetHashCode() ?? 0);
}
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantTableTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantTableTagDataEntry.cs
index b04ee10d0..353dab604 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantTableTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantTableTagDataEntry.cs
@@ -44,14 +44,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccColorantTableTagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccColorantTableTagDataEntry entry && this.Equals(entry);
}
///
public bool Equals(IccColorantTableTagDataEntry other)
{
- if (ReferenceEquals(null, other))
+ if (other == null)
{
return false;
}
@@ -67,7 +66,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj == null)
{
return false;
}
@@ -77,7 +76,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return true;
}
- return obj is IccColorantTableTagDataEntry && this.Equals((IccColorantTableTagDataEntry)obj);
+ return obj is IccColorantTableTagDataEntry other && this.Equals(other);
}
///
@@ -85,7 +84,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
unchecked
{
- return (base.GetHashCode() * 397) ^ (this.ColorantData != null ? this.ColorantData.GetHashCode() : 0);
+ return (base.GetHashCode() * 397) ^ (this.ColorantData?.GetHashCode() ?? 0);
}
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCrdInfoTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCrdInfoTagDataEntry.cs
index 1e516ce7f..848418f95 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCrdInfoTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCrdInfoTagDataEntry.cs
@@ -88,14 +88,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccCrdInfoTagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccCrdInfoTagDataEntry entry && this.Equals(entry);
}
///
public bool Equals(IccCrdInfoTagDataEntry other)
{
- if (ReferenceEquals(null, other))
+ if (other == null)
{
return false;
}
@@ -116,7 +115,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj == null)
{
return false;
}
@@ -126,7 +125,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return true;
}
- return obj is IccCrdInfoTagDataEntry && this.Equals((IccCrdInfoTagDataEntry)obj);
+ return obj is IccCrdInfoTagDataEntry other && this.Equals(other);
}
///
@@ -135,11 +134,11 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
unchecked
{
int hashCode = base.GetHashCode();
- hashCode = (hashCode * 397) ^ (this.PostScriptProductName != null ? this.PostScriptProductName.GetHashCode() : 0);
- hashCode = (hashCode * 397) ^ (this.RenderingIntent0Crd != null ? this.RenderingIntent0Crd.GetHashCode() : 0);
- hashCode = (hashCode * 397) ^ (this.RenderingIntent1Crd != null ? this.RenderingIntent1Crd.GetHashCode() : 0);
- hashCode = (hashCode * 397) ^ (this.RenderingIntent2Crd != null ? this.RenderingIntent2Crd.GetHashCode() : 0);
- hashCode = (hashCode * 397) ^ (this.RenderingIntent3Crd != null ? this.RenderingIntent3Crd.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (this.PostScriptProductName?.GetHashCode() ?? 0);
+ hashCode = (hashCode * 397) ^ (this.RenderingIntent0Crd?.GetHashCode() ?? 0);
+ hashCode = (hashCode * 397) ^ (this.RenderingIntent1Crd?.GetHashCode() ?? 0);
+ hashCode = (hashCode * 397) ^ (this.RenderingIntent2Crd?.GetHashCode() ?? 0);
+ hashCode = (hashCode * 397) ^ (this.RenderingIntent3Crd?.GetHashCode() ?? 0);
return hashCode;
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCurveTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCurveTagDataEntry.cs
index 7f753ff7d..c9a59bb32 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCurveTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCurveTagDataEntry.cs
@@ -79,26 +79,25 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
public float Gamma => this.IsGamma ? this.CurveData[0] : 0;
///
- /// Gets a value indicating whether the curve maps input directly to output
+ /// Gets a value indicating whether the curve maps input directly to output.
///
public bool IsIdentityResponse => this.CurveData.Length == 0;
///
- /// Gets a value indicating whether the curve is a gamma curve
+ /// Gets a value indicating whether the curve is a gamma curve.
///
public bool IsGamma => this.CurveData.Length == 1;
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccCurveTagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccCurveTagDataEntry entry && this.Equals(entry);
}
///
public bool Equals(IccCurveTagDataEntry other)
{
- if (ReferenceEquals(null, other))
+ if (other == null)
{
return false;
}
@@ -114,7 +113,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj == null)
{
return false;
}
@@ -124,7 +123,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return true;
}
- return obj is IccCurveTagDataEntry && this.Equals((IccCurveTagDataEntry)obj);
+ return obj is IccCurveTagDataEntry other && this.Equals(other);
}
///
@@ -132,7 +131,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
unchecked
{
- return (base.GetHashCode() * 397) ^ (this.CurveData != null ? this.CurveData.GetHashCode() : 0);
+ return (base.GetHashCode() * 397) ^ (this.CurveData?.GetHashCode() ?? 0);
}
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDataTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDataTagDataEntry.cs
index 3b17e2942..c8f5f8b7c 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDataTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDataTagDataEntry.cs
@@ -67,14 +67,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccDataTagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccDataTagDataEntry entry && this.Equals(entry);
}
///
public bool Equals(IccDataTagDataEntry other)
{
- if (ReferenceEquals(null, other))
+ if (other == null)
{
return false;
}
@@ -90,7 +89,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj == null)
{
return false;
}
@@ -100,7 +99,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return true;
}
- return obj is IccDataTagDataEntry && this.Equals((IccDataTagDataEntry)obj);
+ return obj is IccDataTagDataEntry other && this.Equals(other);
}
///
@@ -109,7 +108,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
unchecked
{
int hashCode = base.GetHashCode();
- hashCode = (hashCode * 397) ^ (this.Data != null ? this.Data.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (this.Data?.GetHashCode() ?? 0);
hashCode = (hashCode * 397) ^ this.IsAscii.GetHashCode();
return hashCode;
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDateTimeTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDateTimeTagDataEntry.cs
index 879c208c1..7a2d97571 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDateTimeTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDateTimeTagDataEntry.cs
@@ -38,14 +38,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccDateTimeTagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccDateTimeTagDataEntry entry && this.Equals(entry);
}
///
public bool Equals(IccDateTimeTagDataEntry other)
{
- if (ReferenceEquals(null, other))
+ if (other == null)
{
return false;
}
@@ -61,7 +60,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj == null)
{
return false;
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccFix16ArrayTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccFix16ArrayTagDataEntry.cs
index 23580fac6..afe4e0bd3 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccFix16ArrayTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccFix16ArrayTagDataEntry.cs
@@ -40,14 +40,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccFix16ArrayTagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccFix16ArrayTagDataEntry entry && this.Equals(entry);
}
///
public bool Equals(IccFix16ArrayTagDataEntry other)
{
- if (ReferenceEquals(null, other))
+ if (other == null)
{
return false;
}
@@ -63,7 +62,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj == null)
{
return false;
}
@@ -73,7 +72,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return true;
}
- return obj is IccFix16ArrayTagDataEntry && this.Equals((IccFix16ArrayTagDataEntry)obj);
+ return obj is IccFix16ArrayTagDataEntry other && this.Equals(other);
}
///
@@ -81,7 +80,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
unchecked
{
- return (base.GetHashCode() * 397) ^ (this.Data != null ? this.Data.GetHashCode() : 0);
+ return (base.GetHashCode() * 397) ^ (this.Data?.GetHashCode() ?? 0);
}
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs
index 13e146330..d98e45ace 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs
@@ -111,14 +111,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccLut16TagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccLut16TagDataEntry entry && this.Equals(entry);
}
///
public bool Equals(IccLut16TagDataEntry other)
{
- if (ReferenceEquals(null, other))
+ if (other == null)
{
return false;
}
@@ -138,7 +137,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj == null)
{
return false;
}
@@ -158,9 +157,9 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
int hashCode = base.GetHashCode();
hashCode = (hashCode * 397) ^ this.Matrix.GetHashCode();
- hashCode = (hashCode * 397) ^ (this.InputValues != null ? this.InputValues.GetHashCode() : 0);
- hashCode = (hashCode * 397) ^ (this.ClutValues != null ? this.ClutValues.GetHashCode() : 0);
- hashCode = (hashCode * 397) ^ (this.OutputValues != null ? this.OutputValues.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (this.InputValues?.GetHashCode() ?? 0);
+ hashCode = (hashCode * 397) ^ (this.ClutValues?.GetHashCode() ?? 0);
+ hashCode = (hashCode * 397) ^ (this.OutputValues?.GetHashCode() ?? 0);
return hashCode;
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs
index fd6d028ea..e57e0f543 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs
@@ -114,14 +114,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccLut8TagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccLut8TagDataEntry entry && this.Equals(entry);
}
///
public bool Equals(IccLut8TagDataEntry other)
{
- if (ReferenceEquals(null, other))
+ if (other == null)
{
return false;
}
@@ -141,7 +140,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj == null)
{
return false;
}
@@ -161,9 +160,9 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
int hashCode = base.GetHashCode();
hashCode = (hashCode * 397) ^ this.Matrix.GetHashCode();
- hashCode = (hashCode * 397) ^ (this.InputValues != null ? this.InputValues.GetHashCode() : 0);
- hashCode = (hashCode * 397) ^ (this.ClutValues != null ? this.ClutValues.GetHashCode() : 0);
- hashCode = (hashCode * 397) ^ (this.OutputValues != null ? this.OutputValues.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (this.InputValues?.GetHashCode() ?? 0);
+ hashCode = (hashCode * 397) ^ (this.ClutValues?.GetHashCode() ?? 0);
+ hashCode = (hashCode * 397) ^ (this.OutputValues?.GetHashCode() ?? 0);
return hashCode;
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs
index faf9a4550..59c80d409 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs
@@ -147,14 +147,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccLutAToBTagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccLutAToBTagDataEntry entry && this.Equals(entry);
}
///
public bool Equals(IccLutAToBTagDataEntry other)
{
- if (ReferenceEquals(null, other))
+ if (other == null)
{
return false;
}
@@ -178,7 +177,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj == null)
{
return false;
}
@@ -188,7 +187,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return true;
}
- return obj is IccLutAToBTagDataEntry && this.Equals((IccLutAToBTagDataEntry)obj);
+ return obj is IccLutAToBTagDataEntry other && this.Equals(other);
}
///
@@ -201,10 +200,10 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
hashCode = (hashCode * 397) ^ this.OutputChannelCount;
hashCode = (hashCode * 397) ^ this.Matrix3x3.GetHashCode();
hashCode = (hashCode * 397) ^ this.Matrix3x1.GetHashCode();
- hashCode = (hashCode * 397) ^ (this.ClutValues != null ? this.ClutValues.GetHashCode() : 0);
- hashCode = (hashCode * 397) ^ (this.CurveB != null ? this.CurveB.GetHashCode() : 0);
- hashCode = (hashCode * 397) ^ (this.CurveM != null ? this.CurveM.GetHashCode() : 0);
- hashCode = (hashCode * 397) ^ (this.CurveA != null ? this.CurveA.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (this.ClutValues?.GetHashCode() ?? 0);
+ hashCode = (hashCode * 397) ^ (this.CurveB?.GetHashCode() ?? 0);
+ hashCode = (hashCode * 397) ^ (this.CurveM?.GetHashCode() ?? 0);
+ hashCode = (hashCode * 397) ^ (this.CurveA?.GetHashCode() ?? 0);
return hashCode;
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs
index 10ffca335..57b17c452 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs
@@ -147,14 +147,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccLutBToATagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccLutBToATagDataEntry entry && this.Equals(entry);
}
///
public bool Equals(IccLutBToATagDataEntry other)
{
- if (ReferenceEquals(null, other))
+ if (other == null)
{
return false;
}
@@ -178,7 +177,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj == null)
{
return false;
}
@@ -188,7 +187,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return true;
}
- return obj is IccLutBToATagDataEntry && this.Equals((IccLutBToATagDataEntry)obj);
+ return obj is IccLutBToATagDataEntry other && this.Equals(other);
}
///
@@ -201,10 +200,10 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
hashCode = (hashCode * 397) ^ this.OutputChannelCount;
hashCode = (hashCode * 397) ^ this.Matrix3x3.GetHashCode();
hashCode = (hashCode * 397) ^ this.Matrix3x1.GetHashCode();
- hashCode = (hashCode * 397) ^ (this.ClutValues != null ? this.ClutValues.GetHashCode() : 0);
- hashCode = (hashCode * 397) ^ (this.CurveB != null ? this.CurveB.GetHashCode() : 0);
- hashCode = (hashCode * 397) ^ (this.CurveM != null ? this.CurveM.GetHashCode() : 0);
- hashCode = (hashCode * 397) ^ (this.CurveA != null ? this.CurveA.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (this.ClutValues?.GetHashCode() ?? 0);
+ hashCode = (hashCode * 397) ^ (this.CurveB?.GetHashCode() ?? 0);
+ hashCode = (hashCode * 397) ^ (this.CurveM?.GetHashCode() ?? 0);
+ hashCode = (hashCode * 397) ^ (this.CurveA?.GetHashCode() ?? 0);
return hashCode;
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMeasurementTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMeasurementTagDataEntry.cs
index 12010ea09..5f2dbe347 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMeasurementTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMeasurementTagDataEntry.cs
@@ -73,14 +73,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccMeasurementTagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccMeasurementTagDataEntry entry && this.Equals(entry);
}
///
public bool Equals(IccMeasurementTagDataEntry other)
{
- if (ReferenceEquals(null, other))
+ if (other == null)
{
return false;
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiLocalizedUnicodeTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiLocalizedUnicodeTagDataEntry.cs
index 62792b44e..d1745faac 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiLocalizedUnicodeTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiLocalizedUnicodeTagDataEntry.cs
@@ -41,14 +41,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccMultiLocalizedUnicodeTagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccMultiLocalizedUnicodeTagDataEntry entry && this.Equals(entry);
}
///
public bool Equals(IccMultiLocalizedUnicodeTagDataEntry other)
{
- if (ReferenceEquals(null, other))
+ if (other == null)
{
return false;
}
@@ -64,7 +63,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj == null)
{
return false;
}
@@ -82,7 +81,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
unchecked
{
- return (base.GetHashCode() * 397) ^ (this.Texts != null ? this.Texts.GetHashCode() : 0);
+ return (base.GetHashCode() * 397) ^ (this.Texts?.GetHashCode() ?? 0);
}
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiProcessElementsTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiProcessElementsTagDataEntry.cs
index 437c6734b..8b0c06568 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiProcessElementsTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiProcessElementsTagDataEntry.cs
@@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public bool Equals(IccMultiProcessElementsTagDataEntry other)
{
- if (ReferenceEquals(null, other))
+ if (other == null)
{
return false;
}
@@ -94,7 +94,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return true;
}
- return obj is IccMultiProcessElementsTagDataEntry && this.Equals((IccMultiProcessElementsTagDataEntry)obj);
+ return obj is IccMultiProcessElementsTagDataEntry other && this.Equals(other);
}
///
@@ -105,7 +105,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
int hashCode = base.GetHashCode();
hashCode = (hashCode * 397) ^ this.InputChannelCount;
hashCode = (hashCode * 397) ^ this.OutputChannelCount;
- hashCode = (hashCode * 397) ^ (this.Data != null ? this.Data.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (this.Data?.GetHashCode() ?? 0);
return hashCode;
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs
index d3e73b018..bdb1aacb3 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs
@@ -121,8 +121,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccNamedColor2TagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccNamedColor2TagDataEntry entry && this.Equals(entry);
}
///
@@ -159,7 +158,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return true;
}
- return obj is IccNamedColor2TagDataEntry && this.Equals((IccNamedColor2TagDataEntry)obj);
+ return obj is IccNamedColor2TagDataEntry other && this.Equals(other);
}
///
@@ -169,10 +168,10 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
int hashCode = base.GetHashCode();
hashCode = (hashCode * 397) ^ this.CoordinateCount;
- hashCode = (hashCode * 397) ^ (this.Prefix != null ? this.Prefix.GetHashCode() : 0);
- hashCode = (hashCode * 397) ^ (this.Suffix != null ? this.Suffix.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (this.Prefix?.GetHashCode() ?? 0);
+ hashCode = (hashCode * 397) ^ (this.Suffix?.GetHashCode() ?? 0);
hashCode = (hashCode * 397) ^ this.VendorFlags;
- hashCode = (hashCode * 397) ^ (this.Colors != null ? this.Colors.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (this.Colors?.GetHashCode() ?? 0);
return hashCode;
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccParametricCurveTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccParametricCurveTagDataEntry.cs
index 192be52a1..e8bbc5e8f 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccParametricCurveTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccParametricCurveTagDataEntry.cs
@@ -39,8 +39,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccParametricCurveTagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccParametricCurveTagDataEntry entry && this.Equals(entry);
}
///
@@ -72,7 +71,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return true;
}
- return obj is IccParametricCurveTagDataEntry && this.Equals((IccParametricCurveTagDataEntry)obj);
+ return obj is IccParametricCurveTagDataEntry other && this.Equals(other);
}
///
@@ -80,7 +79,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
unchecked
{
- return (base.GetHashCode() * 397) ^ (this.Curve != null ? this.Curve.GetHashCode() : 0);
+ return (base.GetHashCode() * 397) ^ (this.Curve?.GetHashCode() ?? 0);
}
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceDescTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceDescTagDataEntry.cs
index 88aaa0976..cde7c4043 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceDescTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceDescTagDataEntry.cs
@@ -42,8 +42,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccProfileSequenceDescTagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccProfileSequenceDescTagDataEntry entry && this.Equals(entry);
}
///
@@ -65,7 +64,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj == null)
{
return false;
}
@@ -75,7 +74,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return true;
}
- return obj is IccProfileSequenceDescTagDataEntry && this.Equals((IccProfileSequenceDescTagDataEntry)obj);
+ return obj is IccProfileSequenceDescTagDataEntry other && this.Equals(other);
}
///
@@ -83,7 +82,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
unchecked
{
- return (base.GetHashCode() * 397) ^ (this.Descriptions != null ? this.Descriptions.GetHashCode() : 0);
+ return (base.GetHashCode() * 397) ^ (this.Descriptions?.GetHashCode() ?? 0);
}
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceIdentifierTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceIdentifierTagDataEntry.cs
index 7ef17d37e..2309a460e 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceIdentifierTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceIdentifierTagDataEntry.cs
@@ -41,8 +41,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccProfileSequenceIdentifierTagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccProfileSequenceIdentifierTagDataEntry entry && this.Equals(entry);
}
///
@@ -74,7 +73,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return true;
}
- return obj is IccProfileSequenceIdentifierTagDataEntry && this.Equals((IccProfileSequenceIdentifierTagDataEntry)obj);
+ return obj is IccProfileSequenceIdentifierTagDataEntry other && this.Equals(other);
}
///
@@ -82,7 +81,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
unchecked
{
- return (base.GetHashCode() * 397) ^ (this.Data != null ? this.Data.GetHashCode() : 0);
+ return (base.GetHashCode() * 397) ^ (this.Data?.GetHashCode() ?? 0);
}
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccResponseCurveSet16TagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccResponseCurveSet16TagDataEntry.cs
index 7faad30f3..5925454a3 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccResponseCurveSet16TagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccResponseCurveSet16TagDataEntry.cs
@@ -53,8 +53,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccResponseCurveSet16TagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccResponseCurveSet16TagDataEntry entry && this.Equals(entry);
}
///
@@ -98,7 +97,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
int hashCode = base.GetHashCode();
hashCode = (hashCode * 397) ^ this.ChannelCount.GetHashCode();
- hashCode = (hashCode * 397) ^ (this.Curves != null ? this.Curves.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (this.Curves?.GetHashCode() ?? 0);
return hashCode;
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccScreeningTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccScreeningTagDataEntry.cs
index 7a5062707..1e17d0862 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccScreeningTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccScreeningTagDataEntry.cs
@@ -50,8 +50,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccScreeningTagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccScreeningTagDataEntry entry && this.Equals(entry);
}
///
@@ -85,7 +84,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return true;
}
- return obj is IccScreeningTagDataEntry && this.Equals((IccScreeningTagDataEntry)obj);
+ return obj is IccScreeningTagDataEntry other && this.Equals(other);
}
///
@@ -95,7 +94,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
int hashCode = base.GetHashCode();
hashCode = (hashCode * 397) ^ (int)this.Flags;
- hashCode = (hashCode * 397) ^ (this.Channels != null ? this.Channels.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (this.Channels?.GetHashCode() ?? 0);
return hashCode;
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccSignatureTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccSignatureTagDataEntry.cs
index 82462afa3..a808541cf 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccSignatureTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccSignatureTagDataEntry.cs
@@ -40,8 +40,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccSignatureTagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccSignatureTagDataEntry entry && this.Equals(entry);
}
///
@@ -73,7 +72,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return true;
}
- return obj is IccSignatureTagDataEntry && this.Equals((IccSignatureTagDataEntry)obj);
+ return obj is IccSignatureTagDataEntry other && this.Equals(other);
}
///
@@ -81,7 +80,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
unchecked
{
- return (base.GetHashCode() * 397) ^ (this.SignatureData != null ? this.SignatureData.GetHashCode() : 0);
+ return (base.GetHashCode() * 397) ^ (this.SignatureData?.GetHashCode() ?? 0);
}
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs
index 71030c2a6..c509197e4 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs
@@ -133,8 +133,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccTextDescriptionTagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccTextDescriptionTagDataEntry entry && this.Equals(entry);
}
///
@@ -161,7 +160,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj == null)
{
return false;
}
@@ -180,9 +179,9 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
unchecked
{
int hashCode = base.GetHashCode();
- hashCode = (hashCode * 397) ^ (this.Ascii != null ? this.Ascii.GetHashCode() : 0);
- hashCode = (hashCode * 397) ^ (this.Unicode != null ? this.Unicode.GetHashCode() : 0);
- hashCode = (hashCode * 397) ^ (this.ScriptCode != null ? this.ScriptCode.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (this.Ascii?.GetHashCode() ?? 0);
+ hashCode = (hashCode * 397) ^ (this.Unicode?.GetHashCode() ?? 0);
+ hashCode = (hashCode * 397) ^ (this.ScriptCode?.GetHashCode() ?? 0);
hashCode = (hashCode * 397) ^ (int)this.UnicodeLanguageCode;
hashCode = (hashCode * 397) ^ this.ScriptCodeCode.GetHashCode();
return hashCode;
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextTagDataEntry.cs
index 8127fae29..f5e31ea87 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextTagDataEntry.cs
@@ -39,8 +39,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccTextTagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccTextTagDataEntry entry && this.Equals(entry);
}
///
@@ -72,7 +71,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return true;
}
- return obj is IccTextTagDataEntry && this.Equals((IccTextTagDataEntry)obj);
+ return obj is IccTextTagDataEntry other && this.Equals(other);
}
///
@@ -80,7 +79,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
unchecked
{
- return (base.GetHashCode() * 397) ^ (this.Text != null ? this.Text.GetHashCode() : 0);
+ return (base.GetHashCode() * 397) ^ (this.Text?.GetHashCode() ?? 0);
}
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUFix16ArrayTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUFix16ArrayTagDataEntry.cs
index 709106a52..c619b40d4 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUFix16ArrayTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUFix16ArrayTagDataEntry.cs
@@ -33,15 +33,14 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
///
- /// Gets the array data
+ /// Gets the array data.
///
public float[] Data { get; }
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccUFix16ArrayTagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccUFix16ArrayTagDataEntry entry && this.Equals(entry);
}
///
@@ -63,7 +62,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj == null)
{
return false;
}
@@ -73,7 +72,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return true;
}
- return obj is IccUFix16ArrayTagDataEntry && this.Equals((IccUFix16ArrayTagDataEntry)obj);
+ return obj is IccUFix16ArrayTagDataEntry other && this.Equals(other);
}
///
@@ -81,7 +80,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
unchecked
{
- return (base.GetHashCode() * 397) ^ (this.Data != null ? this.Data.GetHashCode() : 0);
+ return (base.GetHashCode() * 397) ^ (this.Data?.GetHashCode() ?? 0);
}
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt16ArrayTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt16ArrayTagDataEntry.cs
index bcd991cea..4f1959cf1 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt16ArrayTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt16ArrayTagDataEntry.cs
@@ -40,8 +40,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccUInt16ArrayTagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccUInt16ArrayTagDataEntry entry && this.Equals(entry);
}
///
@@ -73,7 +72,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return true;
}
- return obj is IccUInt16ArrayTagDataEntry && this.Equals((IccUInt16ArrayTagDataEntry)obj);
+ return obj is IccUInt16ArrayTagDataEntry other && this.Equals(other);
}
///
@@ -81,7 +80,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
unchecked
{
- return (base.GetHashCode() * 397) ^ (this.Data != null ? this.Data.GetHashCode() : 0);
+ return (base.GetHashCode() * 397) ^ (this.Data?.GetHashCode() ?? 0);
}
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt32ArrayTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt32ArrayTagDataEntry.cs
index 8a5ccb0c0..00ca43084 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt32ArrayTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt32ArrayTagDataEntry.cs
@@ -40,14 +40,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccUInt32ArrayTagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccUInt32ArrayTagDataEntry entry && this.Equals(entry);
}
///
public bool Equals(IccUInt32ArrayTagDataEntry other)
{
- if (ReferenceEquals(null, other))
+ if (other == null)
{
return false;
}
@@ -63,7 +62,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj == null)
{
return false;
}
@@ -81,7 +80,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
unchecked
{
- return (base.GetHashCode() * 397) ^ (this.Data != null ? this.Data.GetHashCode() : 0);
+ return (base.GetHashCode() * 397) ^ (this.Data?.GetHashCode() ?? 0);
}
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt64ArrayTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt64ArrayTagDataEntry.cs
index 6e22f7758..27c273e42 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt64ArrayTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt64ArrayTagDataEntry.cs
@@ -40,14 +40,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccUInt64ArrayTagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccUInt64ArrayTagDataEntry entry && this.Equals(entry);
}
///
public bool Equals(IccUInt64ArrayTagDataEntry other)
{
- if (ReferenceEquals(null, other))
+ if (other == null)
{
return false;
}
@@ -63,7 +62,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj == null)
{
return false;
}
@@ -81,7 +80,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
unchecked
{
- return (base.GetHashCode() * 397) ^ (this.Data != null ? this.Data.GetHashCode() : 0);
+ return (base.GetHashCode() * 397) ^ (this.Data?.GetHashCode() ?? 0);
}
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt8ArrayTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt8ArrayTagDataEntry.cs
index 07e142d49..bf6fdd662 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt8ArrayTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt8ArrayTagDataEntry.cs
@@ -33,21 +33,20 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
///
- /// Gets the array data
+ /// Gets the array data.
///
public byte[] Data { get; }
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccUInt8ArrayTagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccUInt8ArrayTagDataEntry entry && this.Equals(entry);
}
///
public bool Equals(IccUInt8ArrayTagDataEntry other)
{
- if (ReferenceEquals(null, other))
+ if (other == null)
{
return false;
}
@@ -63,7 +62,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj == null)
{
return false;
}
@@ -73,7 +72,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return true;
}
- return obj is IccUInt8ArrayTagDataEntry && this.Equals((IccUInt8ArrayTagDataEntry)obj);
+ return obj is IccUInt8ArrayTagDataEntry other && this.Equals(other);
}
///
@@ -81,7 +80,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
unchecked
{
- return (base.GetHashCode() * 397) ^ (this.Data != null ? this.Data.GetHashCode() : 0);
+ return (base.GetHashCode() * 397) ^ (this.Data?.GetHashCode() ?? 0);
}
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUcrBgTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUcrBgTagDataEntry.cs
index 0f8bd6c33..0f190021f 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUcrBgTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUcrBgTagDataEntry.cs
@@ -60,14 +60,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccUcrBgTagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccUcrBgTagDataEntry entry && this.Equals(entry);
}
///
public bool Equals(IccUcrBgTagDataEntry other)
{
- if (ReferenceEquals(null, other))
+ if (other == null)
{
return false;
}
@@ -86,7 +85,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj == null)
{
return false;
}
@@ -96,7 +95,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return true;
}
- return obj is IccUcrBgTagDataEntry && this.Equals((IccUcrBgTagDataEntry)obj);
+ return obj is IccUcrBgTagDataEntry other && this.Equals(other);
}
///
@@ -105,9 +104,9 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
unchecked
{
int hashCode = base.GetHashCode();
- hashCode = (hashCode * 397) ^ (this.UcrCurve != null ? this.UcrCurve.GetHashCode() : 0);
- hashCode = (hashCode * 397) ^ (this.BgCurve != null ? this.BgCurve.GetHashCode() : 0);
- hashCode = (hashCode * 397) ^ (this.Description != null ? this.Description.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (this.UcrCurve?.GetHashCode() ?? 0);
+ hashCode = (hashCode * 397) ^ (this.BgCurve?.GetHashCode() ?? 0);
+ hashCode = (hashCode * 397) ^ (this.Description?.GetHashCode() ?? 0);
return hashCode;
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUnknownTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUnknownTagDataEntry.cs
index 8b60aad26..ce3be9b69 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUnknownTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUnknownTagDataEntry.cs
@@ -33,21 +33,20 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
///
- /// Gets the raw data of the entry
+ /// Gets the raw data of the entry.
///
public byte[] Data { get; }
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccUnknownTagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccUnknownTagDataEntry entry && this.Equals(entry);
}
///
public bool Equals(IccUnknownTagDataEntry other)
{
- if (ReferenceEquals(null, other))
+ if (other == null)
{
return false;
}
@@ -63,7 +62,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj == null)
{
return false;
}
@@ -73,7 +72,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return true;
}
- return obj is IccUnknownTagDataEntry && this.Equals((IccUnknownTagDataEntry)obj);
+ return obj is IccUnknownTagDataEntry other && this.Equals(other);
}
///
@@ -81,7 +80,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
unchecked
{
- return (base.GetHashCode() * 397) ^ (this.Data != null ? this.Data.GetHashCode() : 0);
+ return (base.GetHashCode() * 397) ^ (this.Data?.GetHashCode() ?? 0);
}
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccViewingConditionsTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccViewingConditionsTagDataEntry.cs
index 2c12066f1..a4db8f7ab 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccViewingConditionsTagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccViewingConditionsTagDataEntry.cs
@@ -38,7 +38,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
///
- /// Gets the XYZ values of Illuminant
+ /// Gets the XYZ values of illuminant.
///
public Vector3 IlluminantXyz { get; }
@@ -48,15 +48,14 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
public Vector3 SurroundXyz { get; }
///
- /// Gets the illuminant
+ /// Gets the illuminant.
///
public IccStandardIlluminant Illuminant { get; }
///
public override bool Equals(IccTagDataEntry other)
{
- var entry = other as IccViewingConditionsTagDataEntry;
- return entry != null && this.Equals(entry);
+ return other is IccViewingConditionsTagDataEntry entry && this.Equals(entry);
}
///
@@ -81,7 +80,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj == null)
{
return false;
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccClut.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccClut.cs
index af7e3e011..c42d85134 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccClut.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccClut.cs
@@ -94,9 +94,9 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
public float[][] Values { get; }
///
- /// Gets or sets the CLUT data type (important when writing a profile)
+ /// Gets the CLUT data type (important when writing a profile)
///
- public IccClutDataType DataType { get; set; }
+ public IccClutDataType DataType { get; }
///
/// Gets the number of input channels
@@ -116,7 +116,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public bool Equals(IccClut other)
{
- if (ReferenceEquals(null, other))
+ if (other == null)
{
return false;
}
@@ -136,7 +136,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
+ if (obj == null)
{
return false;
}
@@ -146,7 +146,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return true;
}
- return obj is IccClut && this.Equals((IccClut)obj);
+ return obj is IccClut other && this.Equals(other);
}
///
@@ -154,11 +154,11 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
unchecked
{
- int hashCode = this.Values != null ? this.Values.GetHashCode() : 0;
+ int hashCode = this.Values?.GetHashCode() ?? 0;
hashCode = (hashCode * 397) ^ (int)this.DataType;
hashCode = (hashCode * 397) ^ this.InputChannelCount;
hashCode = (hashCode * 397) ^ this.OutputChannelCount;
- hashCode = (hashCode * 397) ^ (this.GridPointCount != null ? this.GridPointCount.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (this.GridPointCount?.GetHashCode() ?? 0);
return hashCode;
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccColorantTableEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccColorantTableEntry.cs
index c5b005ea0..22e4a0523 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccColorantTableEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccColorantTableEntry.cs
@@ -87,9 +87,9 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
///
- public override bool Equals(object other)
+ public override bool Equals(object obj)
{
- return (other is IccColorantTableEntry) && this.Equals((IccColorantTableEntry)other);
+ return obj is IccColorantTableEntry other && this.Equals(other);
}
///
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccLocalizedString.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccLocalizedString.cs
index 68a5e7cfa..18e28e94c 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccLocalizedString.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccLocalizedString.cs
@@ -7,12 +7,12 @@ using System.Globalization;
namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
///
- /// A string with a specific locale
+ /// A string with a specific locale.
///
- internal sealed class IccLocalizedString : IEquatable
+ internal readonly struct IccLocalizedString : IEquatable
{
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the struct.
/// The culture will be
///
/// The text value of this string
@@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the struct.
/// The culture will be
///
/// The culture of this string
@@ -37,26 +37,19 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
///
- /// Gets the actual text value
+ /// Gets the text value.
///
public string Text { get; }
///
- /// Gets the culture of the text
+ /// Gets the culture of text.
///
public CultureInfo Culture { get; }
///
- public bool Equals(IccLocalizedString other)
- {
- if (ReferenceEquals(this, other))
- {
- return true;
- }
-
- return this.Culture.Equals(other.Culture)
- && this.Text == other.Text;
- }
+ public bool Equals(IccLocalizedString other) =>
+ this.Culture.Equals(other.Culture) &&
+ this.Text == other.Text;
///
public override string ToString()
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccLut.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccLut.cs
index 12d3208a7..c263ffe27 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccLut.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccLut.cs
@@ -9,10 +9,10 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
/// Lookup Table
///
- internal sealed class IccLut : IEquatable
+ internal readonly struct IccLut : IEquatable
{
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the struct.
///
/// The LUT values
public IccLut(float[] values)
@@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the struct.
///
/// The LUT values
public IccLut(ushort[] values)
@@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the struct.
///
/// The LUT values
public IccLut(byte[] values)
@@ -63,12 +63,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
public bool Equals(IccLut other)
{
- if (other == null)
- {
- return false;
- }
-
- if (ReferenceEquals(this, other))
+ if (ReferenceEquals(this.Values, other.Values))
{
return true;
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccNamedColor.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccNamedColor.cs
index 22916c134..5b013fc2c 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccNamedColor.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccNamedColor.cs
@@ -74,18 +74,16 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
///
- public override bool Equals(object other)
+ public override bool Equals(object obj)
{
- return (other is IccNamedColor) && this.Equals((IccNamedColor)other);
+ return obj is IccNamedColor other && this.Equals(other);
}
///
- public bool Equals(IccNamedColor other)
- {
- return this.Name == other.Name
- && this.PcsCoordinates.SequenceEqual(other.PcsCoordinates)
- && this.DeviceCoordinates.SequenceEqual(other.DeviceCoordinates);
- }
+ public bool Equals(IccNamedColor other) =>
+ this.Name == other.Name &&
+ this.PcsCoordinates.SequenceEqual(other.PcsCoordinates) &&
+ this.DeviceCoordinates.SequenceEqual(other.DeviceCoordinates);
///
public override int GetHashCode()
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccPositionNumber.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccPositionNumber.cs
index d886dc099..aad130b0d 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccPositionNumber.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccPositionNumber.cs
@@ -62,17 +62,15 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
///
- public override bool Equals(object other)
+ public override bool Equals(object obj)
{
- return (other is IccPositionNumber) && this.Equals((IccPositionNumber)other);
+ return obj is IccPositionNumber other && this.Equals(other);
}
///
- public bool Equals(IccPositionNumber other)
- {
- return this.Offset == other.Offset
- && this.Size == other.Size;
- }
+ public bool Equals(IccPositionNumber other) =>
+ this.Offset == other.Offset &&
+ this.Size == other.Size;
///
public override int GetHashCode()
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileDescription.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileDescription.cs
index 455717a03..9db4bb9c4 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileDescription.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileDescription.cs
@@ -9,10 +9,10 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
///
/// ICC Profile description
///
- internal sealed class IccProfileDescription : IEquatable
+ internal readonly struct IccProfileDescription : IEquatable
{
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the struct.
///
/// Device Manufacturer
/// Device Model
@@ -40,70 +40,48 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
///
- /// Gets the device manufacturer
+ /// Gets the device manufacturer.
///
public uint DeviceManufacturer { get; }
///
- /// Gets the device model
+ /// Gets the device model.
///
public uint DeviceModel { get; }
///
- /// Gets the device attributes
+ /// Gets the device attributes.
///
public IccDeviceAttribute DeviceAttributes { get; }
///
- /// Gets the technology information
+ /// Gets the technology information.
///
public IccProfileTag TechnologyInformation { get; }
///
- /// Gets the device manufacturer info
+ /// Gets the device manufacturer info.
///
public IccLocalizedString[] DeviceManufacturerInfo { get; }
///
- /// Gets the device model info
+ /// Gets the device model info.
///
public IccLocalizedString[] DeviceModelInfo { get; }
///
- public bool Equals(IccProfileDescription other)
- {
- if (ReferenceEquals(null, other))
- {
- return false;
- }
-
- if (ReferenceEquals(this, other))
- {
- return true;
- }
-
- return this.DeviceManufacturer == other.DeviceManufacturer
- && this.DeviceModel == other.DeviceModel
- && this.DeviceAttributes == other.DeviceAttributes
- && this.TechnologyInformation == other.TechnologyInformation
- && this.DeviceManufacturerInfo.SequenceEqual(other.DeviceManufacturerInfo)
- && this.DeviceModelInfo.SequenceEqual(other.DeviceModelInfo);
- }
+ public bool Equals(IccProfileDescription other) =>
+ this.DeviceManufacturer == other.DeviceManufacturer &&
+ this.DeviceModel == other.DeviceModel &&
+ this.DeviceAttributes == other.DeviceAttributes &&
+ this.TechnologyInformation == other.TechnologyInformation &&
+ this.DeviceManufacturerInfo.SequenceEqual(other.DeviceManufacturerInfo) &&
+ this.DeviceModelInfo.SequenceEqual(other.DeviceModelInfo);
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
- {
- return false;
- }
-
- if (ReferenceEquals(this, obj))
- {
- return true;
- }
-
- return obj is IccProfileDescription && this.Equals((IccProfileDescription)obj);
+ return obj is IccProfileDescription other && this.Equals(other);
}
///
@@ -115,8 +93,8 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
hashCode = (hashCode * 397) ^ (int)this.DeviceModel;
hashCode = (hashCode * 397) ^ this.DeviceAttributes.GetHashCode();
hashCode = (hashCode * 397) ^ (int)this.TechnologyInformation;
- hashCode = (hashCode * 397) ^ (this.DeviceManufacturerInfo != null ? this.DeviceManufacturerInfo.GetHashCode() : 0);
- hashCode = (hashCode * 397) ^ (this.DeviceModelInfo != null ? this.DeviceModelInfo.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (this.DeviceManufacturerInfo?.GetHashCode() ?? 0);
+ hashCode = (hashCode * 397) ^ (this.DeviceModelInfo?.GetHashCode() ?? 0);
return hashCode;
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileId.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileId.cs
index 4070f835d..67911936f 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileId.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileId.cs
@@ -95,19 +95,17 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
///
- public override bool Equals(object other)
+ public override bool Equals(object obj)
{
- return (other is IccProfileId) && this.Equals((IccProfileId)other);
+ return obj is IccProfileId other && this.Equals(other);
}
///
- public bool Equals(IccProfileId other)
- {
- return this.Part1 == other.Part1
- && this.Part2 == other.Part2
- && this.Part3 == other.Part3
- && this.Part4 == other.Part4;
- }
+ public bool Equals(IccProfileId other) =>
+ this.Part1 == other.Part1 &&
+ this.Part2 == other.Part2 &&
+ this.Part3 == other.Part3 &&
+ this.Part4 == other.Part4;
///
public override int GetHashCode()
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileSequenceIdentifier.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileSequenceIdentifier.cs
index dfa3fb203..d5362ad70 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileSequenceIdentifier.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileSequenceIdentifier.cs
@@ -7,12 +7,12 @@ using System.Linq;
namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
///
- /// Description of a profile within a sequence
+ /// Description of a profile within a sequence.
///
- internal sealed class IccProfileSequenceIdentifier : IEquatable
+ internal readonly struct IccProfileSequenceIdentifier : IEquatable
{
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the struct.
///
/// ID of the profile
/// Description of the profile
@@ -25,45 +25,24 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
///
- /// Gets the ID of the profile
+ /// Gets the ID of the profile.
///
public IccProfileId Id { get; }
///
- /// Gets the description of the profile
+ /// Gets the description of the profile.
///
public IccLocalizedString[] Description { get; }
///
- public bool Equals(IccProfileSequenceIdentifier other)
- {
- if (ReferenceEquals(null, other))
- {
- return false;
- }
-
- if (ReferenceEquals(this, other))
- {
- return true;
- }
-
- return this.Id.Equals(other.Id) && this.Description.SequenceEqual(other.Description);
- }
+ public bool Equals(IccProfileSequenceIdentifier other) =>
+ this.Id.Equals(other.Id) &&
+ this.Description.SequenceEqual(other.Description);
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(null, obj))
- {
- return false;
- }
-
- if (ReferenceEquals(this, obj))
- {
- return true;
- }
-
- return obj is IccProfileSequenceIdentifier && this.Equals((IccProfileSequenceIdentifier)obj);
+ return obj is IccProfileSequenceIdentifier other && this.Equals(other);
}
///
@@ -71,7 +50,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
unchecked
{
- return (this.Id.GetHashCode() * 397) ^ (this.Description != null ? this.Description.GetHashCode() : 0);
+ return (this.Id.GetHashCode() * 397) ^ (this.Description?.GetHashCode() ?? 0);
}
}
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccResponseNumber.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccResponseNumber.cs
index c786a0fd4..d1da2366e 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccResponseNumber.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccResponseNumber.cs
@@ -62,17 +62,15 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
///
- public override bool Equals(object other)
+ public override bool Equals(object obj)
{
- return (other is IccResponseNumber) && this.Equals((IccResponseNumber)other);
+ return obj is IccResponseNumber other && this.Equals(other);
}
///
- public bool Equals(IccResponseNumber other)
- {
- return this.DeviceCode == other.DeviceCode
- && this.MeasurementValue == other.MeasurementValue;
- }
+ public bool Equals(IccResponseNumber other) =>
+ this.DeviceCode == other.DeviceCode &&
+ this.MeasurementValue == other.MeasurementValue;
///
public override int GetHashCode()
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs
index e1f1bb32f..c038cfaba 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs
@@ -69,12 +69,10 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
///
- public bool Equals(IccScreeningChannel other)
- {
- return this.Frequency.Equals(other.Frequency)
- && this.Angle.Equals(other.Angle)
- && this.SpotShape == other.SpotShape;
- }
+ public bool Equals(IccScreeningChannel other) =>
+ this.Frequency == other.Frequency &&
+ this.Angle == other.Angle &&
+ this.SpotShape == other.SpotShape;
///
public override bool Equals(object obj)
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccTagTableEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccTagTableEntry.cs
index 7cb5c7901..04357dcf6 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccTagTableEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccTagTableEntry.cs
@@ -69,18 +69,16 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
///
- public override bool Equals(object other)
+ public override bool Equals(object obj)
{
- return (other is IccTagTableEntry) && this.Equals((IccTagTableEntry)other);
+ return obj is IccTagTableEntry other && this.Equals(other);
}
///
- public bool Equals(IccTagTableEntry other)
- {
- return this.Signature == other.Signature
- && this.Offset == other.Offset
- && this.DataSize == other.DataSize;
- }
+ public bool Equals(IccTagTableEntry other) =>
+ this.Signature == other.Signature &&
+ this.Offset == other.Offset &&
+ this.DataSize == other.DataSize;
///
public override int GetHashCode()
diff --git a/src/ImageSharp/PixelFormats/Alpha8.cs b/src/ImageSharp/PixelFormats/Alpha8.cs
index 57e2e984b..659b2439f 100644
--- a/src/ImageSharp/PixelFormats/Alpha8.cs
+++ b/src/ImageSharp/PixelFormats/Alpha8.cs
@@ -97,6 +97,20 @@ namespace SixLabors.ImageSharp.PixelFormats
this.PackedValue = source.A;
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromArgb32(Argb32 source)
+ {
+ this.PackedValue = source.A;
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromBgra32(Bgra32 source)
+ {
+ this.PackedValue = source.A;
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
@@ -114,6 +128,16 @@ namespace SixLabors.ImageSharp.PixelFormats
dest.A = this.PackedValue;
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void ToArgb32(ref Argb32 dest)
+ {
+ dest.R = 0;
+ dest.G = 0;
+ dest.B = 0;
+ dest.A = this.PackedValue;
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
diff --git a/src/ImageSharp/PixelFormats/Argb32.cs b/src/ImageSharp/PixelFormats/Argb32.cs
index 7030006f6..ef869af01 100644
--- a/src/ImageSharp/PixelFormats/Argb32.cs
+++ b/src/ImageSharp/PixelFormats/Argb32.cs
@@ -1,15 +1,15 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using System;
using System.Numerics;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
namespace SixLabors.ImageSharp.PixelFormats
{
///
/// Packed pixel type containing four 8-bit unsigned normalized values ranging from 0 to 255.
- /// The color components are stored in alpha, red, green, and blue order.
+ /// The color components are stored in alpha, red, green, and blue order (least significant to most significant byte).
///
/// Ranges from [0, 0, 0, 0] to [1, 1, 1, 1] in vector form.
///
@@ -18,27 +18,28 @@ namespace SixLabors.ImageSharp.PixelFormats
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
/// as it avoids the need to create new values for modification operations.
///
+ [StructLayout(LayoutKind.Sequential)]
public struct Argb32 : IPixel, IPackedVector
{
///
- /// The shift count for the blue component
+ /// Gets or sets the alpha component.
///
- private const int BlueShift = 0;
+ public byte A;
///
- /// The shift count for the green component
+ /// Gets or sets the red component.
///
- private const int GreenShift = 8;
+ public byte R;
///
- /// The shift count for the red component
+ /// Gets or sets the green component.
///
- private const int RedShift = 16;
+ public byte G;
///
- /// The shift count for the alpha component
+ /// Gets or sets the blue component.
///
- private const int AlphaShift = 24;
+ public byte B;
///
/// The maximum byte value.
@@ -56,11 +57,13 @@ namespace SixLabors.ImageSharp.PixelFormats
/// The red component.
/// The green component.
/// The blue component.
- /// The alpha component.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Argb32(byte r, byte g, byte b, byte a)
+ public Argb32(byte r, byte g, byte b)
{
- this.PackedValue = Pack(r, g, b, a);
+ this.R = r;
+ this.G = g;
+ this.B = b;
+ this.A = 255;
}
///
@@ -69,10 +72,14 @@ namespace SixLabors.ImageSharp.PixelFormats
/// The red component.
/// The green component.
/// The blue component.
+ /// The alpha component.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Argb32(byte r, byte g, byte b)
+ public Argb32(byte r, byte g, byte b, byte a)
{
- this.PackedValue = Pack(r, g, b, 255);
+ this.R = r;
+ this.G = g;
+ this.B = b;
+ this.A = a;
}
///
@@ -82,9 +89,11 @@ namespace SixLabors.ImageSharp.PixelFormats
/// The green component.
/// The blue component.
/// The alpha component.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public Argb32(float r, float g, float b, float a = 1)
+ : this()
{
- this.PackedValue = Pack(r, g, b, a);
+ this.Pack(r, g, b, a);
}
///
@@ -93,9 +102,11 @@ namespace SixLabors.ImageSharp.PixelFormats
///
/// The vector containing the components for the packed vector.
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public Argb32(Vector3 vector)
+ : this()
{
- this.PackedValue = Pack(ref vector);
+ this.Pack(ref vector);
}
///
@@ -104,9 +115,11 @@ namespace SixLabors.ImageSharp.PixelFormats
///
/// The vector containing the components for the packed vector.
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public Argb32(Vector4 vector)
+ : this()
{
- this.PackedValue = Pack(ref vector);
+ this.Pack(ref vector);
}
///
@@ -115,84 +128,30 @@ namespace SixLabors.ImageSharp.PixelFormats
///
/// The packed value.
///
- public Argb32(uint packed = 0)
- {
- this.PackedValue = packed;
- }
-
- ///
- public uint PackedValue { get; set; }
-
- ///
- /// Gets or sets the red component.
- ///
- public byte R
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Argb32(uint packed)
+ : this()
{
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get
- {
- return (byte)(this.PackedValue >> RedShift);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- set
- {
- this.PackedValue = this.PackedValue & 0xFF00FFFF | (uint)value << RedShift;
- }
+ this.Argb = packed;
}
///
- /// Gets or sets the green component.
+ /// Gets or sets the packed representation of the Argb32 struct.
///
- public byte G
+ public uint Argb
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get
- {
- return (byte)(this.PackedValue >> GreenShift);
- }
+ get => Unsafe.As(ref this);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set
- {
- this.PackedValue = this.PackedValue & 0xFFFF00FF | (uint)value << GreenShift;
- }
+ set => Unsafe.As(ref this) = value;
}
- ///
- /// Gets or sets the blue component.
- ///
- public byte B
+ ///
+ public uint PackedValue
{
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get
- {
- return (byte)(this.PackedValue >> BlueShift);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- set
- {
- this.PackedValue = this.PackedValue & 0xFFFFFF00 | (uint)value << BlueShift;
- }
- }
-
- ///
- /// Gets or sets the alpha component.
- ///
- public byte A
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get
- {
- return (byte)(this.PackedValue >> AlphaShift);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- set
- {
- this.PackedValue = this.PackedValue & 0x00FFFFFF | (uint)value << AlphaShift;
- }
+ get => this.Argb;
+ set => this.Argb = value;
}
///
@@ -210,7 +169,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Argb32 left, Argb32 right)
{
- return left.PackedValue == right.PackedValue;
+ return left.Argb == right.Argb;
}
///
@@ -224,14 +183,14 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Argb32 left, Argb32 right)
{
- return left.PackedValue != right.PackedValue;
+ return left.Argb != right.Argb;
}
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
{
- this.PackedValue = Pack(ref vector);
+ this.Pack(ref vector);
}
///
@@ -262,7 +221,27 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
- this.PackedValue = Pack(source.R, source.G, source.B, source.A);
+ this.R = source.R;
+ this.G = source.G;
+ this.B = source.B;
+ this.A = source.A;
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromArgb32(Argb32 source)
+ {
+ this.PackedValue = source.PackedValue;
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromBgra32(Bgra32 source)
+ {
+ this.R = source.R;
+ this.G = source.G;
+ this.B = source.B;
+ this.A = source.A;
}
///
@@ -284,6 +263,13 @@ namespace SixLabors.ImageSharp.PixelFormats
dest.A = this.A;
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void ToArgb32(ref Argb32 dest)
+ {
+ dest = this;
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
@@ -303,17 +289,47 @@ namespace SixLabors.ImageSharp.PixelFormats
dest.A = this.A;
}
+ ///
+ /// Converts the pixel to format.
+ ///
+ /// The RGBA value
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Rgba32 ToRgba32() => new Rgba32(this.R, this.G, this.B, this.A);
+
+ ///
+ /// Converts the pixel to format.
+ ///
+ /// The RGBA value
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Bgra32 ToBgra32() => new Bgra32(this.R, this.G, this.B, this.A);
+
+ ///
+ /// Converts the pixel to format.
+ ///
+ /// The RGBA value
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Argb32 ToArgb32() => this;
+
///
public override bool Equals(object obj)
{
- return obj is Argb32 && this.Equals((Argb32)obj);
+ return obj is Argb32 argb32 && this.Equals(argb32);
}
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Argb32 other)
{
- return this.PackedValue == other.PackedValue;
+ return this.Argb == other.Argb;
+ }
+
+ ///
+ /// Gets a string representation of the packed vector.
+ ///
+ /// A string representation of the packed vector.
+ public override string ToString()
+ {
+ return $"({this.R},{this.G},{this.B},{this.A})";
}
///
@@ -321,65 +337,59 @@ namespace SixLabors.ImageSharp.PixelFormats
public override int GetHashCode()
{
// ReSharper disable once NonReadonlyMemberInGetHashCode
- return this.PackedValue.GetHashCode();
+ return this.Argb.GetHashCode();
}
///
- /// Packs the four floats into a .
+ /// Gets the representation without normalizing to [0, 1]
///
- /// The x-component
- /// The y-component
- /// The z-component
- /// The w-component
- /// The
+ /// A of values in [0, 255]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static uint Pack(float x, float y, float z, float w)
+ internal Vector4 ToByteScaledVector4()
{
- var value = new Vector4(x, y, z, w);
- return Pack(ref value);
+ return new Vector4(this.R, this.G, this.B, this.A);
}
///
- /// Packs the four floats into a .
+ /// Packs the four floats into a color.
///
/// The x-component
/// The y-component
/// The z-component
/// The w-component
- /// The
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static uint Pack(byte x, byte y, byte z, byte w)
+ private void Pack(float x, float y, float z, float w)
{
- return (uint)(x << RedShift | y << GreenShift | z << BlueShift | w << AlphaShift);
+ var value = new Vector4(x, y, z, w);
+ this.Pack(ref value);
}
///
/// Packs a into a uint.
///
/// The vector containing the values to pack.
- /// The containing the packed values.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static uint Pack(ref Vector3 vector)
+ private void Pack(ref Vector3 vector)
{
var value = new Vector4(vector, 1);
- return Pack(ref value);
+ this.Pack(ref value);
}
///
- /// Packs a into a uint.
+ /// Packs a into a color.
///
/// The vector containing the values to pack.
- /// The containing the packed values.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static uint Pack(ref Vector4 vector)
+ private void Pack(ref Vector4 vector)
{
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
- return (uint)(((byte)vector.X << RedShift)
- | ((byte)vector.Y << GreenShift)
- | ((byte)vector.Z << BlueShift)
- | (byte)vector.W << AlphaShift);
+
+ this.R = (byte)vector.X;
+ this.G = (byte)vector.Y;
+ this.B = (byte)vector.Z;
+ this.A = (byte)vector.W;
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/PixelFormats/Bgr24.cs b/src/ImageSharp/PixelFormats/Bgr24.cs
index 61b447b88..955b5c161 100644
--- a/src/ImageSharp/PixelFormats/Bgr24.cs
+++ b/src/ImageSharp/PixelFormats/Bgr24.cs
@@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.PixelFormats
{
///
/// Pixel type containing three 8-bit unsigned normalized values ranging from 0 to 255.
- /// The color components are stored in blue, green, red order.
+ /// The color components are stored in blue, green, red order (least significant to most significant byte).
///
/// Ranges from [0, 0, 0, 1] to [1, 1, 1, 1] in vector form.
///
@@ -82,6 +82,24 @@ namespace SixLabors.ImageSharp.PixelFormats
this = source.Bgr;
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromArgb32(Argb32 source)
+ {
+ this.R = source.R;
+ this.G = source.G;
+ this.B = source.B;
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromBgra32(Bgra32 source)
+ {
+ this.R = source.R;
+ this.G = source.G;
+ this.B = source.B;
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromScaledVector4(Vector4 vector)
@@ -131,6 +149,16 @@ namespace SixLabors.ImageSharp.PixelFormats
dest.A = 255;
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void ToArgb32(ref Argb32 dest)
+ {
+ dest.R = this.R;
+ dest.G = this.G;
+ dest.B = this.B;
+ dest.A = 255;
+ }
+
///
public void ToBgr24(ref Bgr24 dest)
{
diff --git a/src/ImageSharp/PixelFormats/Bgr565.cs b/src/ImageSharp/PixelFormats/Bgr565.cs
index 54e29e21e..d1fa162e7 100644
--- a/src/ImageSharp/PixelFormats/Bgr565.cs
+++ b/src/ImageSharp/PixelFormats/Bgr565.cs
@@ -120,6 +120,20 @@ namespace SixLabors.ImageSharp.PixelFormats
this.PackFromVector4(source.ToVector4());
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromArgb32(Argb32 source)
+ {
+ this.PackFromVector4(source.ToVector4());
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromBgra32(Bgra32 source)
+ {
+ this.PackFromVector4(source.ToVector4());
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
@@ -141,6 +155,17 @@ namespace SixLabors.ImageSharp.PixelFormats
dest.A = (byte)MathF.Round(vector.W);
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void ToArgb32(ref Argb32 dest)
+ {
+ Vector4 vector = this.ToVector4() * 255F;
+ dest.R = (byte)MathF.Round(vector.X);
+ dest.G = (byte)MathF.Round(vector.Y);
+ dest.B = (byte)MathF.Round(vector.Z);
+ dest.A = (byte)MathF.Round(vector.W);
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
diff --git a/src/ImageSharp/PixelFormats/Bgra32.cs b/src/ImageSharp/PixelFormats/Bgra32.cs
index ad5efa257..20dfda504 100644
--- a/src/ImageSharp/PixelFormats/Bgra32.cs
+++ b/src/ImageSharp/PixelFormats/Bgra32.cs
@@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats
{
///
/// Packed pixel type containing four 8-bit unsigned normalized values ranging from 0 to 255.
- /// The color components are stored in blue, green, red, and alpha order.
+ /// The color components are stored in blue, green, red, and alpha order (least significant to most significant byte).
///
/// Ranges from [0, 0, 0, 0] to [1, 1, 1, 1] in vector form.
///
@@ -75,16 +75,10 @@ namespace SixLabors.ImageSharp.PixelFormats
public uint Bgra
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get
- {
- return Unsafe.As(ref this);
- }
+ get => Unsafe.As(ref this);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set
- {
- Unsafe.As(ref this) = value;
- }
+ set => Unsafe.As(ref this) = value;
}
///
@@ -119,6 +113,16 @@ namespace SixLabors.ImageSharp.PixelFormats
}
}
+ ///
+ /// Gets the representation without normalizing to [0, 1]
+ ///
+ /// A of values in [0, 255]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal Vector4 ToByteScaledVector4()
+ {
+ return new Vector4(this.R, this.G, this.B, this.A);
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromScaledVector4(Vector4 vector)
@@ -159,6 +163,23 @@ namespace SixLabors.ImageSharp.PixelFormats
this.A = source.A;
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromArgb32(Argb32 source)
+ {
+ this.R = source.R;
+ this.G = source.G;
+ this.B = source.B;
+ this.A = source.A;
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromBgra32(Bgra32 source)
+ {
+ this.PackedValue = source.PackedValue;
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
@@ -178,6 +199,16 @@ namespace SixLabors.ImageSharp.PixelFormats
dest.A = this.A;
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void ToArgb32(ref Argb32 dest)
+ {
+ dest.R = this.R;
+ dest.G = this.G;
+ dest.B = this.B;
+ dest.A = this.A;
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
@@ -198,5 +229,19 @@ namespace SixLabors.ImageSharp.PixelFormats
/// The RGBA value
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Rgba32 ToRgba32() => new Rgba32(this.R, this.G, this.B, this.A);
+
+ ///
+ /// Converts the pixel to format.
+ ///
+ /// The RGBA value
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Argb32 ToArgb32() => new Argb32(this.R, this.G, this.B, this.A);
+
+ ///
+ /// Converts the pixel to format.
+ ///
+ /// The RGBA value
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Bgra32 ToBgra32() => this;
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/PixelFormats/Bgra4444.cs b/src/ImageSharp/PixelFormats/Bgra4444.cs
index 0f52d0068..393723c85 100644
--- a/src/ImageSharp/PixelFormats/Bgra4444.cs
+++ b/src/ImageSharp/PixelFormats/Bgra4444.cs
@@ -111,6 +111,20 @@ namespace SixLabors.ImageSharp.PixelFormats
this.PackFromVector4(source.ToVector4());
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromArgb32(Argb32 source)
+ {
+ this.PackFromVector4(source.ToVector4());
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromBgra32(Bgra32 source)
+ {
+ this.PackFromVector4(source.ToVector4());
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
@@ -132,6 +146,17 @@ namespace SixLabors.ImageSharp.PixelFormats
dest.A = (byte)vector.W;
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void ToArgb32(ref Argb32 dest)
+ {
+ Vector4 vector = this.ToVector4() * 255F;
+ dest.R = (byte)vector.X;
+ dest.G = (byte)vector.Y;
+ dest.B = (byte)vector.Z;
+ dest.A = (byte)vector.W;
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
diff --git a/src/ImageSharp/PixelFormats/Bgra5551.cs b/src/ImageSharp/PixelFormats/Bgra5551.cs
index d24bab848..ba3441270 100644
--- a/src/ImageSharp/PixelFormats/Bgra5551.cs
+++ b/src/ImageSharp/PixelFormats/Bgra5551.cs
@@ -111,6 +111,20 @@ namespace SixLabors.ImageSharp.PixelFormats
this.PackFromVector4(source.ToVector4());
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromArgb32(Argb32 source)
+ {
+ this.PackFromVector4(source.ToVector4());
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromBgra32(Bgra32 source)
+ {
+ this.PackFromVector4(source.ToVector4());
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
@@ -132,6 +146,17 @@ namespace SixLabors.ImageSharp.PixelFormats
dest.A = (byte)vector.W;
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void ToArgb32(ref Argb32 dest)
+ {
+ Vector4 vector = this.ToByteScaledVector4();
+ dest.R = (byte)vector.X;
+ dest.G = (byte)vector.Y;
+ dest.B = (byte)vector.Z;
+ dest.A = (byte)vector.W;
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
diff --git a/src/ImageSharp/PixelFormats/Byte4.cs b/src/ImageSharp/PixelFormats/Byte4.cs
index d7aae5df9..d91dac9ac 100644
--- a/src/ImageSharp/PixelFormats/Byte4.cs
+++ b/src/ImageSharp/PixelFormats/Byte4.cs
@@ -112,6 +112,20 @@ namespace SixLabors.ImageSharp.PixelFormats
this.PackFromVector4(source.ToByteScaledVector4());
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromArgb32(Argb32 source)
+ {
+ this.PackFromVector4(source.ToByteScaledVector4());
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromBgra32(Bgra32 source)
+ {
+ this.PackFromVector4(source.ToByteScaledVector4());
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
@@ -133,6 +147,17 @@ namespace SixLabors.ImageSharp.PixelFormats
dest.A = (byte)vector.W;
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void ToArgb32(ref Argb32 dest)
+ {
+ var vector = this.ToVector4();
+ dest.R = (byte)vector.X;
+ dest.G = (byte)vector.Y;
+ dest.B = (byte)vector.Z;
+ dest.A = (byte)vector.W;
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
diff --git a/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs b/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs
index 81a86cdc5..025204c89 100644
--- a/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs
+++ b/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs
@@ -10,8 +10,8 @@ namespace SixLabors.ImageSharp.PixelFormats
public partial class PixelOperations
{
-
- ///
+
+ ///
/// Converts 'count' elements in 'source` span of data to a span of -s.
///
/// The source of data.
@@ -19,12 +19,12 @@ namespace SixLabors.ImageSharp.PixelFormats
/// The number of pixels to convert.
internal virtual void PackFromRgba32(ReadOnlySpan source, Span destPixels, int count)
{
- GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
-
+ GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
+
ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(source);
ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels);
- Rgba32 rgba = new Rgba32(0, 0, 0, 255);
+ var rgba = new Rgba32(0, 0, 0, 255);
for (int i = 0; i < count; i++)
{
@@ -33,8 +33,8 @@ namespace SixLabors.ImageSharp.PixelFormats
dp.PackFromRgba32(rgba);
}
}
-
- ///
+
+ ///
/// A helper for that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with layout.
///
@@ -46,8 +46,8 @@ namespace SixLabors.ImageSharp.PixelFormats
{
this.PackFromRgba32(MemoryMarshal.Cast(sourceBytes), destPixels, count);
}
-
- ///
+
+ ///
/// Converts 'count' pixels in 'sourcePixels` span to a span of -s.
/// Bulk version of .
///
@@ -69,20 +69,20 @@ namespace SixLabors.ImageSharp.PixelFormats
}
}
- ///
+ ///
/// A helper for that expects a byte span as destination.
/// The layout of the data in 'destBytes' must be compatible with layout.
///
/// The to the source colors.
/// The to the destination bytes.
/// The number of pixels to convert.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void ToRgba32Bytes(ReadOnlySpan sourceColors, Span destBytes, int count)
{
this.ToRgba32(sourceColors, MemoryMarshal.Cast(destBytes), count);
}
-
- ///
+
+ ///
/// Converts 'count' elements in 'source` span of data to a span of -s.
///
/// The source of data.
@@ -90,22 +90,22 @@ namespace SixLabors.ImageSharp.PixelFormats
/// The number of pixels to convert.
internal virtual void PackFromBgra32(ReadOnlySpan source, Span destPixels, int count)
{
- GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
-
+ GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
+
ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(source);
ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels);
- var rgba = new Rgba32(0, 0, 0, 255);
+ var bgra = new Bgra32(0, 0, 0, 255);
for (int i = 0; i < count; i++)
{
ref TPixel dp = ref Unsafe.Add(ref destRef, i);
- rgba = Unsafe.Add(ref sourceRef, i).ToRgba32();
- dp.PackFromRgba32(rgba);
+ bgra = Unsafe.Add(ref sourceRef, i);
+ dp.PackFromBgra32(bgra);
}
}
-
- ///
+
+ ///
/// A helper for that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with layout.
///
@@ -117,8 +117,8 @@ namespace SixLabors.ImageSharp.PixelFormats
{
this.PackFromBgra32(MemoryMarshal.Cast(sourceBytes), destPixels, count);
}
-
- ///
+
+ ///
/// Converts 'count' pixels in 'sourcePixels` span to a span of -s.
/// Bulk version of .
///
@@ -140,20 +140,20 @@ namespace SixLabors.ImageSharp.PixelFormats
}
}
- ///
+ ///
/// A helper for that expects a byte span as destination.
/// The layout of the data in 'destBytes' must be compatible with layout.
///
/// The to the source colors.
/// The to the destination bytes.
/// The number of pixels to convert.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void ToBgra32Bytes(ReadOnlySpan sourceColors, Span destBytes, int count)
{
this.ToBgra32(sourceColors, MemoryMarshal.Cast(destBytes), count);
}
-
- ///
+
+ ///
/// Converts 'count' elements in 'source` span of data to a span of -s.
///
/// The source of data.
@@ -161,8 +161,8 @@ namespace SixLabors.ImageSharp.PixelFormats
/// The number of pixels to convert.
internal virtual void PackFromRgb24(ReadOnlySpan source, Span destPixels, int count)
{
- GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
-
+ GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
+
ref Rgb24 sourceRef = ref MemoryMarshal.GetReference(source);
ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels);
@@ -175,8 +175,8 @@ namespace SixLabors.ImageSharp.PixelFormats
dp.PackFromRgba32(rgba);
}
}
-
- ///
+
+ ///
/// A helper for that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with layout.
///
@@ -188,8 +188,8 @@ namespace SixLabors.ImageSharp.PixelFormats
{
this.PackFromRgb24(MemoryMarshal.Cast(sourceBytes), destPixels, count);
}
-
- ///
+
+ ///
/// Converts 'count' pixels in 'sourcePixels` span to a span of -s.
/// Bulk version of .
///
@@ -211,20 +211,20 @@ namespace SixLabors.ImageSharp.PixelFormats
}
}
- ///
+ ///
/// A helper for that expects a byte span as destination.
/// The layout of the data in 'destBytes' must be compatible with layout.
///
/// The to the source colors.
/// The to the destination bytes.
/// The number of pixels to convert.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void ToRgb24Bytes(ReadOnlySpan sourceColors, Span destBytes, int count)
{
this.ToRgb24(sourceColors, MemoryMarshal.Cast(destBytes), count);
}
-
- ///
+
+ ///
/// Converts 'count' elements in 'source` span of data to a span of -s.
///
/// The source of data.
@@ -232,12 +232,12 @@ namespace SixLabors.ImageSharp.PixelFormats
/// The number of pixels to convert.
internal virtual void PackFromBgr24(ReadOnlySpan source, Span destPixels, int count)
{
- GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
-
+ GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
+
ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(source);
ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels);
- Rgba32 rgba = new Rgba32(0, 0, 0, 255);
+ var rgba = new Rgba32(0, 0, 0, 255);
for (int i = 0; i < count; i++)
{
@@ -246,8 +246,8 @@ namespace SixLabors.ImageSharp.PixelFormats
dp.PackFromRgba32(rgba);
}
}
-
- ///
+
+ ///
/// A helper for that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with layout.
///
@@ -259,8 +259,8 @@ namespace SixLabors.ImageSharp.PixelFormats
{
this.PackFromBgr24(MemoryMarshal.Cast(sourceBytes), destPixels, count);
}
-
- ///
+
+ ///
/// Converts 'count' pixels in 'sourcePixels` span to a span of -s.
/// Bulk version of .
///
@@ -282,18 +282,89 @@ namespace SixLabors.ImageSharp.PixelFormats
}
}
- ///
+ ///
/// A helper for that expects a byte span as destination.
/// The layout of the data in 'destBytes' must be compatible with layout.
///
/// The to the source colors.
/// The to the destination bytes.
/// The number of pixels to convert.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void ToBgr24Bytes(ReadOnlySpan sourceColors, Span destBytes, int count)
{
this.ToBgr24(sourceColors, MemoryMarshal.Cast(destBytes), count);
}
+
+ ///
+ /// Converts 'count' elements in 'source` span of data to a span of -s.
+ ///
+ /// The source of data.
+ /// The to the destination pixels.
+ /// The number of pixels to convert.
+ internal virtual void PackFromArgb32(ReadOnlySpan source, Span destPixels, int count)
+ {
+ GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
+
+ ref Argb32 sourceRef = ref MemoryMarshal.GetReference(source);
+ ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ var argb = new Argb32(0, 0, 0, 255);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref TPixel dp = ref Unsafe.Add(ref destRef, i);
+ argb = Unsafe.Add(ref sourceRef, i);
+ dp.PackFromArgb32(argb);
+ }
+ }
+
+ ///
+ /// A helper for that expects a byte span.
+ /// The layout of the data in 'sourceBytes' must be compatible with layout.
+ ///
+ /// The to the source bytes.
+ /// The to the destination pixels.
+ /// The number of pixels to convert.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal void PackFromArgb32Bytes(ReadOnlySpan sourceBytes, Span destPixels, int count)
+ {
+ this.PackFromArgb32(MemoryMarshal.Cast(sourceBytes), destPixels, count);
+ }
+
+ ///
+ /// Converts 'count' pixels in 'sourcePixels` span to a span of -s.
+ /// Bulk version of .
+ ///
+ /// The span of source pixels
+ /// The destination span of data.
+ /// The number of pixels to convert.
+ internal virtual void ToArgb32(ReadOnlySpan sourcePixels, Span dest, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
+
+ ref TPixel sourceBaseRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Argb32 destBaseRef = ref MemoryMarshal.GetReference(dest);
- }
+ for (int i = 0; i < count; i++)
+ {
+ ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i);
+ ref Argb32 dp = ref Unsafe.Add(ref destBaseRef, i);
+ sp.ToArgb32(ref dp);
+ }
+ }
+
+ ///
+ /// A helper for that expects a byte span as destination.
+ /// The layout of the data in 'destBytes' must be compatible with layout.
+ ///
+ /// The to the source colors.
+ /// The to the destination bytes.
+ /// The number of pixels to convert.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal void ToArgb32Bytes(ReadOnlySpan sourceColors, Span destBytes, int count)
+ {
+ this.ToArgb32(sourceColors, MemoryMarshal.Cast(destBytes), count);
+ }
+
+ }
}
\ No newline at end of file
diff --git a/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt b/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt
index d0a05677f..060973c74 100644
--- a/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt
+++ b/src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt
@@ -46,7 +46,7 @@
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void To<#=pixelType#>Bytes(ReadOnlySpan sourceColors, Span destBytes, int count)
{
- this.To<#=pixelType#>(sourceColors, destBytes.NonPortableCast>(), count);
+ this.To<#=pixelType#>(sourceColors, MemoryMarshal.Cast>(destBytes), count);
}
<#
}
@@ -68,13 +68,13 @@
ref <#=pixelType#> sourceRef = ref MemoryMarshal.GetReference(source);
ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels);
- Rgba32 rgba = new Rgba32(0, 0, 0, 255);
+ var rgba = new Rgba32(0, 0, 0, 255);
for (int i = 0; i < count; i++)
{
ref TPixel dp = ref Unsafe.Add(ref destRef, i);
<#=rgbaOperationCode#>
- dp.PackFromRgba32(rgba);
+ dp.PackFromRgba32(rgba);
}
}
@@ -88,7 +88,91 @@
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void PackFrom<#=pixelType#>Bytes(ReadOnlySpan sourceBytes, Span destPixels, int count)
{
- this.PackFrom<#=pixelType#>(sourceBytes.NonPortableCast>(), destPixels, count);
+ this.PackFrom<#=pixelType#>(MemoryMarshal.Cast>(sourceBytes), destPixels, count);
+ }
+ <#
+ }
+
+ void GeneratePackFromMethodUsingPackFromArgb32(string pixelType, string argbOperationCode)
+ {
+ #>
+
+ ///
+ /// Converts 'count' elements in 'source` span of data to a span of -s.
+ ///
+ /// The source of data.
+ /// The to the destination pixels.
+ /// The number of pixels to convert.
+ internal virtual void PackFrom<#=pixelType#>(ReadOnlySpan<<#=pixelType#>> source, Span destPixels, int count)
+ {
+ GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
+
+ ref <#=pixelType#> sourceRef = ref MemoryMarshal.GetReference(source);
+ ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ var argb = new Argb32(0, 0, 0, 255);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref TPixel dp = ref Unsafe.Add(ref destRef, i);
+ <#=argbOperationCode#>
+ dp.PackFromArgb32(argb);
+ }
+ }
+
+ ///
+ /// A helper for that expects a byte span.
+ /// The layout of the data in 'sourceBytes' must be compatible with layout.
+ ///
+ /// The to the source bytes.
+ /// The to the destination pixels.
+ /// The number of pixels to convert.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal void PackFrom<#=pixelType#>Bytes(ReadOnlySpan sourceBytes, Span destPixels, int count)
+ {
+ this.PackFrom<#=pixelType#>(MemoryMarshal.Cast>(sourceBytes), destPixels, count);
+ }
+ <#
+ }
+
+ void GeneratePackFromMethodUsingPackFromBgra32(string pixelType, string bgraOperationCode)
+ {
+ #>
+
+ ///
+ /// Converts 'count' elements in 'source` span of data to a span of -s.
+ ///
+ /// The source of data.
+ /// The to the destination pixels.
+ /// The number of pixels to convert.
+ internal virtual void PackFrom<#=pixelType#>(ReadOnlySpan<<#=pixelType#>> source, Span destPixels, int count)
+ {
+ GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
+
+ ref <#=pixelType#> sourceRef = ref MemoryMarshal.GetReference(source);
+ ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ var bgra = new Bgra32(0, 0, 0, 255);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref TPixel dp = ref Unsafe.Add(ref destRef, i);
+ <#=bgraOperationCode#>
+ dp.PackFromBgra32(bgra);
+ }
+ }
+
+ ///
+ /// A helper for that expects a byte span.
+ /// The layout of the data in 'sourceBytes' must be compatible with layout.
+ ///
+ /// The to the source bytes.
+ /// The to the destination pixels.
+ /// The number of pixels to convert.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal void PackFrom<#=pixelType#>Bytes(ReadOnlySpan sourceBytes, Span destPixels, int count)
+ {
+ this.PackFrom<#=pixelType#>(MemoryMarshal.Cast>(sourceBytes), destPixels, count);
}
<#
}
@@ -111,7 +195,7 @@ namespace SixLabors.ImageSharp.PixelFormats
GeneratePackFromMethodUsingPackFromRgba32("Rgba32", "rgba = Unsafe.Add(ref sourceRef, i);");
GenerateToDestFormatMethods("Rgba32");
- GeneratePackFromMethodUsingPackFromRgba32("Bgra32", "rgba = Unsafe.Add(ref sourceRef, i).ToRgba32();");
+ GeneratePackFromMethodUsingPackFromBgra32("Bgra32", "bgra = Unsafe.Add(ref sourceRef, i);");
GenerateToDestFormatMethods("Bgra32");
GeneratePackFromMethodUsingPackFromRgba32("Rgb24", "rgba.Rgb = Unsafe.Add(ref sourceRef, i);");
@@ -120,6 +204,9 @@ namespace SixLabors.ImageSharp.PixelFormats
GeneratePackFromMethodUsingPackFromRgba32("Bgr24", "rgba.Bgr = Unsafe.Add(ref sourceRef, i);");
GenerateToDestFormatMethods("Bgr24");
+ GeneratePackFromMethodUsingPackFromArgb32("Argb32", "argb = Unsafe.Add(ref sourceRef, i);");
+ GenerateToDestFormatMethods("Argb32");
+
#>
}
diff --git a/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.cs
index a8e68e36d..e68efba25 100644
--- a/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.cs
+++ b/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.cs
@@ -112,6 +112,38 @@ namespace SixLabors.ImageSharp.PixelFormats
}
}
+ ///
+ internal override void PackFromArgb32(ReadOnlySpan source, Span destPixels, int count)
+ {
+ GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
+
+ ref Argb32 sourceRef = ref MemoryMarshal.GetReference(source);
+ ref Rgba32 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Rgba32 dp = ref Unsafe.Add(ref destRef, i);
+ dp = sp.ToRgba32();
+ }
+ }
+
+ ///
+ internal override void ToArgb32(ReadOnlySpan sourcePixels, Span dest, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
+
+ ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Argb32 destRef = ref MemoryMarshal.GetReference(dest);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Argb32 dp = ref Unsafe.Add(ref destRef, i);
+ dp = sp.ToArgb32();
+ }
+ }
+
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.tt
index 4a88bbad7..a73433339 100644
--- a/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.tt
+++ b/src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.tt
@@ -79,6 +79,9 @@ namespace SixLabors.ImageSharp.PixelFormats
GeneratePackFromMethod("Bgra32", "dp = sp.ToRgba32();");
GenerateConvertToMethod("Bgra32", "dp = sp.ToBgra32();");
+
+ GeneratePackFromMethod("Argb32", "dp = sp.ToRgba32();");
+ GenerateConvertToMethod("Argb32", "dp = sp.ToArgb32();");
#>
}
diff --git a/src/ImageSharp/PixelFormats/HalfSingle.cs b/src/ImageSharp/PixelFormats/HalfSingle.cs
index 0569b796d..f85370ba1 100644
--- a/src/ImageSharp/PixelFormats/HalfSingle.cs
+++ b/src/ImageSharp/PixelFormats/HalfSingle.cs
@@ -125,6 +125,20 @@ namespace SixLabors.ImageSharp.PixelFormats
this.PackFromVector4(source.ToVector4());
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromArgb32(Argb32 source)
+ {
+ this.PackFromVector4(source.ToVector4());
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromBgra32(Bgra32 source)
+ {
+ this.PackFromVector4(source.ToVector4());
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
@@ -146,6 +160,17 @@ namespace SixLabors.ImageSharp.PixelFormats
dest.A = (byte)vector.W;
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void ToArgb32(ref Argb32 dest)
+ {
+ Vector4 vector = this.ToByteScaledVector4();
+ dest.R = (byte)vector.X;
+ dest.G = (byte)vector.Y;
+ dest.B = (byte)vector.Z;
+ dest.A = (byte)vector.W;
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
diff --git a/src/ImageSharp/PixelFormats/HalfVector2.cs b/src/ImageSharp/PixelFormats/HalfVector2.cs
index b26ae9598..acee34d6c 100644
--- a/src/ImageSharp/PixelFormats/HalfVector2.cs
+++ b/src/ImageSharp/PixelFormats/HalfVector2.cs
@@ -140,6 +140,20 @@ namespace SixLabors.ImageSharp.PixelFormats
this.PackFromVector4(source.ToVector4());
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromArgb32(Argb32 source)
+ {
+ this.PackFromVector4(source.ToVector4());
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromBgra32(Bgra32 source)
+ {
+ this.PackFromVector4(source.ToVector4());
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
@@ -161,6 +175,17 @@ namespace SixLabors.ImageSharp.PixelFormats
dest.A = 255;
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void ToArgb32(ref Argb32 dest)
+ {
+ Vector4 vector = this.ToByteScaledVector4();
+ dest.R = (byte)vector.X;
+ dest.G = (byte)vector.Y;
+ dest.B = 0;
+ dest.A = 255;
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
diff --git a/src/ImageSharp/PixelFormats/HalfVector4.cs b/src/ImageSharp/PixelFormats/HalfVector4.cs
index c92de4ef1..7c4cfb31c 100644
--- a/src/ImageSharp/PixelFormats/HalfVector4.cs
+++ b/src/ImageSharp/PixelFormats/HalfVector4.cs
@@ -133,6 +133,20 @@ namespace SixLabors.ImageSharp.PixelFormats
this.PackFromVector4(source.ToVector4());
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromArgb32(Argb32 source)
+ {
+ this.PackFromVector4(source.ToVector4());
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromBgra32(Bgra32 source)
+ {
+ this.PackFromVector4(source.ToVector4());
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
@@ -154,6 +168,17 @@ namespace SixLabors.ImageSharp.PixelFormats
dest.A = (byte)vector.W;
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void ToArgb32(ref Argb32 dest)
+ {
+ Vector4 vector = this.ToByteScaledVector4();
+ dest.R = (byte)vector.X;
+ dest.G = (byte)vector.Y;
+ dest.B = (byte)vector.Z;
+ dest.A = (byte)vector.W;
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
diff --git a/src/ImageSharp/PixelFormats/IPixel.cs b/src/ImageSharp/PixelFormats/IPixel.cs
index 954e14cc0..7501cf382 100644
--- a/src/ImageSharp/PixelFormats/IPixel.cs
+++ b/src/ImageSharp/PixelFormats/IPixel.cs
@@ -8,6 +8,8 @@ namespace SixLabors.ImageSharp.PixelFormats
{
///
/// An interface that represents a generic pixel type.
+ /// The naming convention of each pixel format is to order the color components from least significant to most significant, reading from left to right.
+ /// For example in the pixel format the R component is the least significant byte, and the A component is the most significant.
///
/// The type implementing this interface
public interface IPixel : IPixel, IEquatable
@@ -59,6 +61,18 @@ namespace SixLabors.ImageSharp.PixelFormats
/// The value.
void PackFromRgba32(Rgba32 source);
+ ///
+ /// Packs the pixel from an value.
+ ///
+ /// The value.
+ void PackFromArgb32(Argb32 source);
+
+ ///
+ /// Packs the pixel from an value.
+ ///
+ /// The value.
+ void PackFromBgra32(Bgra32 source);
+
///
/// Converts the pixel to format.
///
@@ -71,6 +85,12 @@ namespace SixLabors.ImageSharp.PixelFormats
/// The destination pixel to write to
void ToRgba32(ref Rgba32 dest);
+ ///
+ /// Converts the pixel to format.
+ ///
+ /// The destination pixel to write to
+ void ToArgb32(ref Argb32 dest);
+
///
/// Converts the pixel to format.
///
diff --git a/src/ImageSharp/PixelFormats/NormalizedByte2.cs b/src/ImageSharp/PixelFormats/NormalizedByte2.cs
index 9bac82856..36ca11dd8 100644
--- a/src/ImageSharp/PixelFormats/NormalizedByte2.cs
+++ b/src/ImageSharp/PixelFormats/NormalizedByte2.cs
@@ -149,6 +149,30 @@ namespace SixLabors.ImageSharp.PixelFormats
this.PackFromVector4(vector);
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromArgb32(Argb32 source)
+ {
+ Vector4 vector = source.ToByteScaledVector4();
+ vector -= Round;
+ vector -= Half;
+ vector -= Round;
+ vector /= Half;
+ this.PackFromVector4(vector);
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromBgra32(Bgra32 source)
+ {
+ Vector4 vector = source.ToByteScaledVector4();
+ vector -= Round;
+ vector -= Half;
+ vector -= Round;
+ vector /= Half;
+ this.PackFromVector4(vector);
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
@@ -170,6 +194,17 @@ namespace SixLabors.ImageSharp.PixelFormats
dest.A = 255;
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void ToArgb32(ref Argb32 dest)
+ {
+ Vector4 vector = this.ToByteScaledVector4();
+ dest.R = (byte)vector.X;
+ dest.G = (byte)vector.Y;
+ dest.B = 0;
+ dest.A = 255;
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
diff --git a/src/ImageSharp/PixelFormats/NormalizedByte4.cs b/src/ImageSharp/PixelFormats/NormalizedByte4.cs
index a3aa60fd2..8471285c7 100644
--- a/src/ImageSharp/PixelFormats/NormalizedByte4.cs
+++ b/src/ImageSharp/PixelFormats/NormalizedByte4.cs
@@ -142,6 +142,30 @@ namespace SixLabors.ImageSharp.PixelFormats
this.PackFromVector4(vector);
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromArgb32(Argb32 source)
+ {
+ Vector4 vector = source.ToByteScaledVector4();
+ vector -= Round;
+ vector -= Half;
+ vector -= Round;
+ vector /= Half;
+ this.PackFromVector4(vector);
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromBgra32(Bgra32 source)
+ {
+ Vector4 vector = source.ToByteScaledVector4();
+ vector -= Round;
+ vector -= Half;
+ vector -= Round;
+ vector /= Half;
+ this.PackFromVector4(vector);
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
@@ -163,6 +187,17 @@ namespace SixLabors.ImageSharp.PixelFormats
dest.A = (byte)vector.W;
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void ToArgb32(ref Argb32 dest)
+ {
+ Vector4 vector = this.ToByteScaledVector4();
+ dest.R = (byte)vector.X;
+ dest.G = (byte)vector.Y;
+ dest.B = (byte)vector.Z;
+ dest.A = (byte)vector.W;
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
diff --git a/src/ImageSharp/PixelFormats/NormalizedShort2.cs b/src/ImageSharp/PixelFormats/NormalizedShort2.cs
index afea6aaad..6907594a0 100644
--- a/src/ImageSharp/PixelFormats/NormalizedShort2.cs
+++ b/src/ImageSharp/PixelFormats/NormalizedShort2.cs
@@ -136,6 +136,30 @@ namespace SixLabors.ImageSharp.PixelFormats
this.PackFromVector4(vector);
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromArgb32(Argb32 source)
+ {
+ Vector4 vector = source.ToByteScaledVector4();
+ vector -= Round;
+ vector -= Half;
+ vector -= Round;
+ vector /= Half;
+ this.PackFromVector4(vector);
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromBgra32(Bgra32 source)
+ {
+ Vector4 vector = source.ToByteScaledVector4();
+ vector -= Round;
+ vector -= Half;
+ vector -= Round;
+ vector /= Half;
+ this.PackFromVector4(vector);
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
@@ -157,6 +181,17 @@ namespace SixLabors.ImageSharp.PixelFormats
dest.A = 255;
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void ToArgb32(ref Argb32 dest)
+ {
+ Vector4 vector = this.ToByteScaledVector4();
+ dest.R = (byte)MathF.Round(vector.X);
+ dest.G = (byte)MathF.Round(vector.Y);
+ dest.B = 0;
+ dest.A = 255;
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
diff --git a/src/ImageSharp/PixelFormats/NormalizedShort4.cs b/src/ImageSharp/PixelFormats/NormalizedShort4.cs
index 87c92cb73..78c65212b 100644
--- a/src/ImageSharp/PixelFormats/NormalizedShort4.cs
+++ b/src/ImageSharp/PixelFormats/NormalizedShort4.cs
@@ -144,6 +144,30 @@ namespace SixLabors.ImageSharp.PixelFormats
this.PackFromVector4(vector);
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromArgb32(Argb32 source)
+ {
+ Vector4 vector = source.ToByteScaledVector4();
+ vector -= Round;
+ vector -= Half;
+ vector -= Round;
+ vector /= Half;
+ this.PackFromVector4(vector);
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromBgra32(Bgra32 source)
+ {
+ Vector4 vector = source.ToByteScaledVector4();
+ vector -= Round;
+ vector -= Half;
+ vector -= Round;
+ vector /= Half;
+ this.PackFromVector4(vector);
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
@@ -165,6 +189,17 @@ namespace SixLabors.ImageSharp.PixelFormats
dest.A = (byte)MathF.Round(vector.W);
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void ToArgb32(ref Argb32 dest)
+ {
+ Vector4 vector = this.ToByteScaledVector4();
+ dest.R = (byte)MathF.Round(vector.X);
+ dest.G = (byte)MathF.Round(vector.Y);
+ dest.B = (byte)MathF.Round(vector.Z);
+ dest.A = (byte)MathF.Round(vector.W);
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
diff --git a/src/ImageSharp/PixelFormats/README.md b/src/ImageSharp/PixelFormats/README.md
index c7aa01295..c332bc92c 100644
--- a/src/ImageSharp/PixelFormats/README.md
+++ b/src/ImageSharp/PixelFormats/README.md
@@ -4,4 +4,7 @@ https://github.com/MonoGame/MonoGame
Rgba32 is our default format. As such it positioned within the ImageSharp root namespace to ensure visibility of the format.
-All other pixel formats should be positioned within ImageSharp.PixelFormats to reduce intellisense burden.
\ No newline at end of file
+All other pixel formats should be positioned within ImageSharp.PixelFormats to reduce intellisense burden.
+
+The naming convention of each pixel format is to order the color components from least significant to most significant, reading from left to right.
+For example in the Rgba32 pixel format the R component is the least significant byte, and the A component is the most significant.
diff --git a/src/ImageSharp/PixelFormats/Rg32.cs b/src/ImageSharp/PixelFormats/Rg32.cs
index 5ce029af3..696b823ce 100644
--- a/src/ImageSharp/PixelFormats/Rg32.cs
+++ b/src/ImageSharp/PixelFormats/Rg32.cs
@@ -124,6 +124,20 @@ namespace SixLabors.ImageSharp.PixelFormats
this.PackFromVector4(source.ToVector4());
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromArgb32(Argb32 source)
+ {
+ this.PackFromVector4(source.ToVector4());
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromBgra32(Bgra32 source)
+ {
+ this.PackFromVector4(source.ToVector4());
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
@@ -145,6 +159,17 @@ namespace SixLabors.ImageSharp.PixelFormats
dest.A = (byte)vector.W;
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void ToArgb32(ref Argb32 dest)
+ {
+ Vector4 vector = this.ToByteScaledVector4();
+ dest.R = (byte)vector.X;
+ dest.G = (byte)vector.Y;
+ dest.B = (byte)vector.Z;
+ dest.A = (byte)vector.W;
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
diff --git a/src/ImageSharp/PixelFormats/Rgb24.cs b/src/ImageSharp/PixelFormats/Rgb24.cs
index f07eadd56..fa03683c6 100644
--- a/src/ImageSharp/PixelFormats/Rgb24.cs
+++ b/src/ImageSharp/PixelFormats/Rgb24.cs
@@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats
{
///
/// Pixel type containing three 8-bit unsigned normalized values ranging from 0 to 255.
- /// The color components are stored in red, green, blue order.
+ /// The color components are stored in red, green, blue order (least significant to most significant byte).
///
/// Ranges from [0, 0, 0, 1] to [1, 1, 1, 1] in vector form.
///
@@ -83,6 +83,24 @@ namespace SixLabors.ImageSharp.PixelFormats
this = Unsafe.As(ref source);
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromArgb32(Argb32 source)
+ {
+ this.R = source.R;
+ this.G = source.G;
+ this.B = source.B;
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromBgra32(Bgra32 source)
+ {
+ this.R = source.R;
+ this.G = source.G;
+ this.B = source.B;
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromScaledVector4(Vector4 vector)
@@ -127,6 +145,15 @@ namespace SixLabors.ImageSharp.PixelFormats
dest.A = 255;
}
+ ///
+ public void ToArgb32(ref Argb32 dest)
+ {
+ dest.R = this.R;
+ dest.G = this.G;
+ dest.B = this.B;
+ dest.A = 255;
+ }
+
///
public void ToBgr24(ref Bgr24 dest)
{
diff --git a/src/ImageSharp/PixelFormats/Rgba1010102.cs b/src/ImageSharp/PixelFormats/Rgba1010102.cs
index 39eed08f3..166936d5e 100644
--- a/src/ImageSharp/PixelFormats/Rgba1010102.cs
+++ b/src/ImageSharp/PixelFormats/Rgba1010102.cs
@@ -118,6 +118,20 @@ namespace SixLabors.ImageSharp.PixelFormats
this.PackFromVector4(source.ToVector4());
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromArgb32(Argb32 source)
+ {
+ this.PackFromVector4(source.ToVector4());
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromBgra32(Bgra32 source)
+ {
+ this.PackFromVector4(source.ToVector4());
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
@@ -139,6 +153,17 @@ namespace SixLabors.ImageSharp.PixelFormats
dest.A = (byte)MathF.Round(vector.W);
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void ToArgb32(ref Argb32 dest)
+ {
+ Vector4 vector = this.ToVector4() * 255F;
+ dest.R = (byte)MathF.Round(vector.X);
+ dest.G = (byte)MathF.Round(vector.Y);
+ dest.B = (byte)MathF.Round(vector.Z);
+ dest.A = (byte)MathF.Round(vector.W);
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
diff --git a/src/ImageSharp/PixelFormats/Rgba32.cs b/src/ImageSharp/PixelFormats/Rgba32.cs
index 182fd7cce..f6979aad8 100644
--- a/src/ImageSharp/PixelFormats/Rgba32.cs
+++ b/src/ImageSharp/PixelFormats/Rgba32.cs
@@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.PixelFormats
{
///
/// Packed pixel type containing four 8-bit unsigned normalized values ranging from 0 to 255.
- /// The color components are stored in red, green, blue, and alpha order.
+ /// The color components are stored in red, green, blue, and alpha order (least significant to most significant byte).
///
/// Ranges from [0, 0, 0, 0] to [1, 1, 1, 1] in vector form.
///
@@ -161,16 +161,10 @@ namespace SixLabors.ImageSharp.PixelFormats
public uint Rgba
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get
- {
- return Unsafe.As(ref this);
- }
+ get => Unsafe.As(ref this);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set
- {
- Unsafe.As(ref this) = value;
- }
+ set => Unsafe.As(ref this) = value;
}
///
@@ -179,16 +173,10 @@ namespace SixLabors.ImageSharp.PixelFormats
public Rgb24 Rgb
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get
- {
- return Unsafe.As(ref this);
- }
+ get => Unsafe.As(ref this);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- set
- {
- Unsafe.As(ref this) = value;
- }
+ set => Unsafe.As(ref this) = value;
}
///
@@ -197,10 +185,7 @@ namespace SixLabors.ImageSharp.PixelFormats
public Bgr24 Bgr
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get
- {
- return new Bgr24(this.R, this.G, this.B);
- }
+ get => new Bgr24(this.R, this.G, this.B);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
@@ -275,13 +260,33 @@ namespace SixLabors.ImageSharp.PixelFormats
this = source;
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromArgb32(Argb32 source)
+ {
+ this.R = source.R;
+ this.G = source.G;
+ this.B = source.B;
+ this.A = source.A;
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromBgra32(Bgra32 source)
+ {
+ this.R = source.R;
+ this.G = source.G;
+ this.B = source.B;
+ this.A = source.A;
+ }
+
///
/// Converts the value of this instance to a hexadecimal string.
///
/// A hexadecimal string representation of the value.
public string ToHex()
{
- uint hexOrder = Pack(this.A, this.B, this.G, this.R);
+ uint hexOrder = (uint)(this.A << 0 | this.B << 8 | this.G << 16 | this.R << 24);
return hexOrder.ToString("X8");
}
@@ -299,6 +304,16 @@ namespace SixLabors.ImageSharp.PixelFormats
dest = this;
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void ToArgb32(ref Argb32 dest)
+ {
+ dest.R = this.R;
+ dest.G = this.G;
+ dest.B = this.B;
+ dest.A = this.A;
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
@@ -352,10 +367,22 @@ namespace SixLabors.ImageSharp.PixelFormats
///
/// A value.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Bgra32 ToBgra32()
- {
- return new Bgra32(this.R, this.G, this.B, this.A);
- }
+ public Bgra32 ToBgra32() => new Bgra32(this.R, this.G, this.B, this.A);
+
+ ///
+ /// Gets the value of this struct as .
+ /// Useful for changing the component order.
+ ///
+ /// A value.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Argb32 ToArgb32() => new Argb32(this.R, this.G, this.B, this.A);
+
+ ///
+ /// Converts the pixel to format.
+ ///
+ /// The RGBA value
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Rgba32 ToRgba32() => this;
///
public override bool Equals(object obj)
@@ -380,16 +407,11 @@ namespace SixLabors.ImageSharp.PixelFormats
}
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
{
- unchecked
- {
- int hashCode = this.R;
- hashCode = (hashCode * 397) ^ this.G;
- hashCode = (hashCode * 397) ^ this.B;
- hashCode = (hashCode * 397) ^ this.A;
- return hashCode;
- }
+ // ReSharper disable once NonReadonlyMemberInGetHashCode
+ return this.Rgba.GetHashCode();
}
///
@@ -402,20 +424,6 @@ namespace SixLabors.ImageSharp.PixelFormats
return new Vector4(this.R, this.G, this.B, this.A);
}
- ///
- /// Packs the four floats into a .
- ///
- /// The x-component
- /// The y-component
- /// The z-component
- /// The w-component
- /// The
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static uint Pack(byte x, byte y, byte z, byte w)
- {
- return (uint)(x << RedShift | y << GreenShift | z << BlueShift | w << AlphaShift);
- }
-
///
/// Packs a into a color returning a new instance as a result.
///
diff --git a/src/ImageSharp/PixelFormats/Rgba64.cs b/src/ImageSharp/PixelFormats/Rgba64.cs
index 4a2f9ef6a..1507a258c 100644
--- a/src/ImageSharp/PixelFormats/Rgba64.cs
+++ b/src/ImageSharp/PixelFormats/Rgba64.cs
@@ -117,6 +117,20 @@ namespace SixLabors.ImageSharp.PixelFormats
this.PackFromVector4(source.ToVector4());
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromArgb32(Argb32 source)
+ {
+ this.PackFromVector4(source.ToVector4());
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromBgra32(Bgra32 source)
+ {
+ this.PackFromVector4(source.ToVector4());
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
@@ -138,6 +152,17 @@ namespace SixLabors.ImageSharp.PixelFormats
dest.A = (byte)MathF.Round(vector.W);
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void ToArgb32(ref Argb32 dest)
+ {
+ Vector4 vector = this.ToVector4() * 255F;
+ dest.R = (byte)MathF.Round(vector.X);
+ dest.G = (byte)MathF.Round(vector.Y);
+ dest.B = (byte)MathF.Round(vector.Z);
+ dest.A = (byte)MathF.Round(vector.W);
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
diff --git a/src/ImageSharp/PixelFormats/RgbaVector.cs b/src/ImageSharp/PixelFormats/RgbaVector.cs
index 92faa4e27..6eaf69214 100644
--- a/src/ImageSharp/PixelFormats/RgbaVector.cs
+++ b/src/ImageSharp/PixelFormats/RgbaVector.cs
@@ -218,6 +218,20 @@ namespace SixLabors.ImageSharp.PixelFormats
this.backingVector = source.ToVector4();
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromArgb32(Argb32 source)
+ {
+ this.backingVector = source.ToVector4();
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromBgra32(Bgra32 source)
+ {
+ this.backingVector = source.ToVector4();
+ }
+
///
/// Converts the value of this instance to a hexadecimal string.
///
@@ -252,6 +266,17 @@ namespace SixLabors.ImageSharp.PixelFormats
dest.A = (byte)MathF.Round(vector.W);
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void ToArgb32(ref Argb32 dest)
+ {
+ Vector4 vector = this.ToByteScaledVector4();
+ dest.R = (byte)MathF.Round(vector.X);
+ dest.G = (byte)MathF.Round(vector.Y);
+ dest.B = (byte)MathF.Round(vector.Z);
+ dest.A = (byte)MathF.Round(vector.W);
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
diff --git a/src/ImageSharp/PixelFormats/Short2.cs b/src/ImageSharp/PixelFormats/Short2.cs
index 75429c0af..abe653e88 100644
--- a/src/ImageSharp/PixelFormats/Short2.cs
+++ b/src/ImageSharp/PixelFormats/Short2.cs
@@ -134,6 +134,26 @@ namespace SixLabors.ImageSharp.PixelFormats
this.PackedValue = Pack(vector.X, vector.Y);
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromArgb32(Argb32 source)
+ {
+ Vector2 vector = new Vector2(source.R, source.G) / 255;
+ vector *= 65534;
+ vector -= new Vector2(32767);
+ this.PackedValue = Pack(vector.X, vector.Y);
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromBgra32(Bgra32 source)
+ {
+ Vector2 vector = new Vector2(source.R, source.G) / 255;
+ vector *= 65534;
+ vector -= new Vector2(32767);
+ this.PackedValue = Pack(vector.X, vector.Y);
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
@@ -155,6 +175,17 @@ namespace SixLabors.ImageSharp.PixelFormats
dest.A = 255;
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void ToArgb32(ref Argb32 dest)
+ {
+ Vector2 vector = this.ToByteScaledVector2();
+ dest.R = (byte)MathF.Round(vector.X);
+ dest.G = (byte)MathF.Round(vector.Y);
+ dest.B = 0;
+ dest.A = 255;
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
diff --git a/src/ImageSharp/PixelFormats/Short4.cs b/src/ImageSharp/PixelFormats/Short4.cs
index 0ea2b10c2..d3bb891d9 100644
--- a/src/ImageSharp/PixelFormats/Short4.cs
+++ b/src/ImageSharp/PixelFormats/Short4.cs
@@ -140,6 +140,26 @@ namespace SixLabors.ImageSharp.PixelFormats
this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromArgb32(Argb32 source)
+ {
+ var vector = source.ToVector4();
+ vector *= 65534;
+ vector -= new Vector4(32767);
+ this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
+ }
+
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void PackFromBgra32(Bgra32 source)
+ {
+ var vector = source.ToVector4();
+ vector *= 65534;
+ vector -= new Vector4(32767);
+ this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
@@ -161,6 +181,17 @@ namespace SixLabors.ImageSharp.PixelFormats
dest.A = (byte)MathF.Round(vector.W);
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public void ToArgb32(ref Argb32 dest)
+ {
+ Vector4 vector = this.ToByteScaledVector4();
+ dest.R = (byte)MathF.Round(vector.X);
+ dest.G = (byte)MathF.Round(vector.Y);
+ dest.B = (byte)MathF.Round(vector.Z);
+ dest.A = (byte)MathF.Round(vector.W);
+ }
+
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegMultiple.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegMultiple.cs
index 7660769da..a1083e8eb 100644
--- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegMultiple.cs
+++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegMultiple.cs
@@ -3,6 +3,8 @@
using System.Collections.Generic;
using BenchmarkDotNet.Attributes;
+using SixLabors.ImageSharp.Formats.Jpeg.GolangPort;
+using SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort;
using SixLabors.ImageSharp.PixelFormats;
using SDImage = System.Drawing.Image;
@@ -20,9 +22,15 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
protected override IEnumerable SearchPatterns => new[] { "*.jpg" };
[Benchmark(Description = "DecodeJpegMultiple - ImageSharp")]
- public void DecodeJpegImageSharpNwq()
+ public void DecodeJpegImageSharpOrig()
{
- this.ForEachStream(ms => Image.Load(ms));
+ this.ForEachStream(ms => Image.Load(ms, new OrigJpegDecoder()));
+ }
+
+ [Benchmark(Description = "DecodeJpegMultiple - ImageSharp PDFJs")]
+ public void DecodeJpegImageSharpPdfJs()
+ {
+ this.ForEachStream(ms => Image.Load(ms, new PdfJsJpegDecoder()));
}
[Benchmark(Baseline = true, Description = "DecodeJpegMultiple - System.Drawing")]
diff --git a/tests/ImageSharp.Benchmarks/General/StructCasting.cs b/tests/ImageSharp.Benchmarks/General/StructCasting.cs
new file mode 100644
index 000000000..bed68b54a
--- /dev/null
+++ b/tests/ImageSharp.Benchmarks/General/StructCasting.cs
@@ -0,0 +1,28 @@
+using System.Runtime.CompilerServices;
+using BenchmarkDotNet.Attributes;
+
+namespace SixLabors.ImageSharp.Benchmarks.General
+{
+ public class StructCasting
+ {
+ [Benchmark(Baseline = true)]
+ public short ExplicitCast()
+ {
+ int x = 5 * 2;
+ return (short)x;
+ }
+
+ [Benchmark]
+ public short UnsafeCast()
+ {
+ int x = 5 * 2;
+ return Unsafe.As(ref x);
+ }
+
+ [Benchmark]
+ public short UnsafeCastRef()
+ {
+ return Unsafe.As(ref Unsafe.AsRef(5 * 2));
+ }
+ }
+}
diff --git a/tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs b/tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs
index 4291e775d..302b90e30 100644
--- a/tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs
+++ b/tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs
@@ -1,15 +1,13 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using Xunit;
-using SixLabors.ImageSharp.Advanced;
using System.Runtime.CompilerServices;
-// ReSharper disable InconsistentNaming
+using SixLabors.ImageSharp.Advanced;
+using SixLabors.ImageSharp.PixelFormats;
+using Xunit;
namespace SixLabors.ImageSharp.Tests.Advanced
{
- using SixLabors.ImageSharp.PixelFormats;
-
public class AdvancedImageExtensionsTests
{
[Theory]
@@ -19,7 +17,7 @@ namespace SixLabors.ImageSharp.Tests.Advanced
{
using (Image image = provider.GetImage())
{
- TPixel[] targetBuffer = new TPixel[image.Width * image.Height];
+ var targetBuffer = new TPixel[image.Width * image.Height];
ref byte source = ref Unsafe.As(ref targetBuffer[0]);
ref byte dest = ref Unsafe.As(ref image.DangerousGetPinnableReferenceToPixelBuffer());
diff --git a/tests/ImageSharp.Tests/BaseImageOperationsExtensionTest.cs b/tests/ImageSharp.Tests/BaseImageOperationsExtensionTest.cs
index 121d93dac..34b2f718e 100644
--- a/tests/ImageSharp.Tests/BaseImageOperationsExtensionTest.cs
+++ b/tests/ImageSharp.Tests/BaseImageOperationsExtensionTest.cs
@@ -1,10 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using System;
-using System.Collections.Generic;
-using System.Text;
-
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.Primitives;
diff --git a/tests/ImageSharp.Tests/Colorspaces/CieLabAndCieLchConversionTests.cs b/tests/ImageSharp.Tests/Colorspaces/CieLabAndCieLchConversionTests.cs
index 426945989..299b9e9e5 100644
--- a/tests/ImageSharp.Tests/Colorspaces/CieLabAndCieLchConversionTests.cs
+++ b/tests/ImageSharp.Tests/Colorspaces/CieLabAndCieLchConversionTests.cs
@@ -36,10 +36,10 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
public void Convert_Lch_to_Lab(float l, float c, float h, float l2, float a, float b)
{
// Arrange
- CieLch input = new CieLch(l, c, h);
+ var input = new CieLch(l, c, h);
// Act
- CieLab output = Converter.ToCieLab(input);
+ var output = Converter.ToCieLab(input);
// Assert
Assert.Equal(l2, output.L, FloatRoundingComparer);
@@ -62,10 +62,10 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
public void Convert_Lab_to_LCHab(float l, float a, float b, float l2, float c, float h)
{
// Arrange
- CieLab input = new CieLab(l, a, b);
+ var input = new CieLab(l, a, b);
// Act
- CieLch output = Converter.ToCieLch(input);
+ var output = Converter.ToCieLch(input);
// Assert
Assert.Equal(l2, output.L, FloatRoundingComparer);
diff --git a/tests/ImageSharp.Tests/Colorspaces/CieLuvAndCieLchuvConversionTests.cs b/tests/ImageSharp.Tests/Colorspaces/CieLuvAndCieLchuvConversionTests.cs
index 17fd1db50..cbcddcfe5 100644
--- a/tests/ImageSharp.Tests/Colorspaces/CieLuvAndCieLchuvConversionTests.cs
+++ b/tests/ImageSharp.Tests/Colorspaces/CieLuvAndCieLchuvConversionTests.cs
@@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
public void Convert_Lchuv_to_Luv(float l, float c, float h, float l2, float u, float v)
{
// Arrange
- CieLchuv input = new CieLchuv(l, c, h);
+ var input = new CieLchuv(l, c, h);
// Act
CieLuv output = Converter.ToCieLuv(input);
@@ -63,7 +63,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
public void Convert_Luv_to_LCHuv(float l, float u, float v, float l2, float c, float h)
{
// Arrange
- CieLuv input = new CieLuv(l, u, v);
+ var input = new CieLuv(l, u, v);
// Act
CieLchuv output = Converter.ToCieLchuv(input);
diff --git a/tests/ImageSharp.Tests/Colorspaces/CieXyzAndCieLuvConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/CieXyzAndCieLuvConversionTest.cs
index b18bd56dc..46f4f15b8 100644
--- a/tests/ImageSharp.Tests/Colorspaces/CieXyzAndCieLuvConversionTest.cs
+++ b/tests/ImageSharp.Tests/Colorspaces/CieXyzAndCieLuvConversionTest.cs
@@ -33,8 +33,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
public void Convert_Luv_to_Xyz(float l, float u, float v, float x, float y, float z)
{
// Arrange
- CieLuv input = new CieLuv(l, u, v, Illuminants.D65);
- ColorSpaceConverter converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65, TargetLabWhitePoint = Illuminants.D65 };
+ var input = new CieLuv(l, u, v, Illuminants.D65);
+ var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65, TargetLabWhitePoint = Illuminants.D65 };
// Act
CieXyz output = converter.ToCieXyz(input);
@@ -58,8 +58,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
public void Convert_Xyz_to_Luv(float x, float y, float z, float l, float u, float v)
{
// Arrange
- CieXyz input = new CieXyz(x, y, z);
- ColorSpaceConverter converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65, TargetLabWhitePoint = Illuminants.D65 };
+ var input = new CieXyz(x, y, z);
+ var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65, TargetLabWhitePoint = Illuminants.D65 };
// Act
CieLuv output = converter.ToCieLuv(input);
diff --git a/tests/ImageSharp.Tests/Colorspaces/CieXyzAndCieXyyConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/CieXyzAndCieXyyConversionTest.cs
index 1652c5392..d461acd56 100644
--- a/tests/ImageSharp.Tests/Colorspaces/CieXyzAndCieXyyConversionTest.cs
+++ b/tests/ImageSharp.Tests/Colorspaces/CieXyzAndCieXyyConversionTest.cs
@@ -28,8 +28,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
[InlineData(0, 0, 0, 0.538842, 0.000000, 0.000000)]
public void Convert_xyY_to_XYZ(float xyzX, float xyzY, float xyzZ, float x, float y, float yl)
{
- // Arrange
- CieXyy input = new CieXyy(x, y, yl);
+ var input = new CieXyy(x, y, yl);
// Act
CieXyz output = Converter.ToCieXyz(input);
@@ -47,8 +46,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
[InlineData(0.231809, 0, 0.077528, 0.749374, 0.000000, 0.000000)]
public void Convert_XYZ_to_xyY(float xyzX, float xyzY, float xyzZ, float x, float y, float yl)
{
- // Arrange
- CieXyz input = new CieXyz(xyzX, xyzY, xyzZ);
+ var input = new CieXyz(xyzX, xyzY, xyzZ);
// Act
CieXyy output = Converter.ToCieXyy(input);
diff --git a/tests/ImageSharp.Tests/Colorspaces/CieXyzAndHunterLabConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/CieXyzAndHunterLabConversionTest.cs
index 1c48d00ff..bea392c16 100644
--- a/tests/ImageSharp.Tests/Colorspaces/CieXyzAndHunterLabConversionTest.cs
+++ b/tests/ImageSharp.Tests/Colorspaces/CieXyzAndHunterLabConversionTest.cs
@@ -28,8 +28,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
public void Convert_HunterLab_to_Xyz(float l, float a, float b, float x, float y, float z)
{
// Arrange
- HunterLab input = new HunterLab(l, a, b);
- ColorSpaceConverter converter = new ColorSpaceConverter { WhitePoint = Illuminants.C };
+ var input = new HunterLab(l, a, b);
+ var converter = new ColorSpaceConverter { WhitePoint = Illuminants.C };
// Act
CieXyz output = converter.ToCieXyz(input);
@@ -49,8 +49,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
public void Convert_HunterLab_to_Xyz_D65(float l, float a, float b, float x, float y, float z)
{
// Arrange
- HunterLab input = new HunterLab(l, a, b);
- ColorSpaceConverter converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65 };
+ var input = new HunterLab(l, a, b);
+ var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65 };
// Act
CieXyz output = converter.ToCieXyz(input);
@@ -70,8 +70,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
public void Convert_Xyz_D65_to_HunterLab(float x, float y, float z, float l, float a, float b)
{
// Arrange
- CieXyz input = new CieXyz(x, y, z);
- ColorSpaceConverter converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65 };
+ var input = new CieXyz(x, y, z);
+ var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65 };
// Act
HunterLab output = converter.ToHunterLab(input);
diff --git a/tests/ImageSharp.Tests/Colorspaces/CieXyzAndLmsConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/CieXyzAndLmsConversionTest.cs
index f63c54212..45ca9049a 100644
--- a/tests/ImageSharp.Tests/Colorspaces/CieXyzAndLmsConversionTest.cs
+++ b/tests/ImageSharp.Tests/Colorspaces/CieXyzAndLmsConversionTest.cs
@@ -31,8 +31,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
public void Convert_Lms_to_CieXyz(float l, float m, float s, float x, float y, float z)
{
// Arrange
- Lms input = new Lms(l, m, s);
- ColorSpaceConverter converter = new ColorSpaceConverter();
+ var input = new Lms(l, m, s);
+ var converter = new ColorSpaceConverter();
// Act
CieXyz output = converter.ToCieXyz(input);
@@ -56,8 +56,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
public void Convert_CieXyz_to_Lms(float x, float y, float z, float l, float m, float s)
{
// Arrange
- CieXyz input = new CieXyz(x, y, z);
- ColorSpaceConverter converter = new ColorSpaceConverter();
+ var input = new CieXyz(x, y, z);
+ var converter = new ColorSpaceConverter();
// Act
Lms output = converter.ToLms(input);
diff --git a/tests/ImageSharp.Tests/Colorspaces/ColorConverterAdaptTest.cs b/tests/ImageSharp.Tests/Colorspaces/ColorConverterAdaptTest.cs
index 3d332eaf2..1cb3f56c7 100644
--- a/tests/ImageSharp.Tests/Colorspaces/ColorConverterAdaptTest.cs
+++ b/tests/ImageSharp.Tests/Colorspaces/ColorConverterAdaptTest.cs
@@ -28,9 +28,9 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
public void Adapt_RGB_WideGamutRGB_To_sRGB(float r1, float g1, float b1, float r2, float g2, float b2)
{
// Arrange
- Rgb input = new Rgb(r1, g1, b1, RgbWorkingSpaces.WideGamutRgb);
- Rgb expectedOutput = new Rgb(r2, g2, b2, RgbWorkingSpaces.SRgb);
- ColorSpaceConverter converter = new ColorSpaceConverter { TargetRgbWorkingSpace = RgbWorkingSpaces.SRgb };
+ var input = new Rgb(r1, g1, b1, RgbWorkingSpaces.WideGamutRgb);
+ var expectedOutput = new Rgb(r2, g2, b2, RgbWorkingSpaces.SRgb);
+ var converter = new ColorSpaceConverter { TargetRgbWorkingSpace = RgbWorkingSpaces.SRgb };
// Action
Rgb output = converter.Adapt(input);
@@ -49,9 +49,9 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
public void Adapt_RGB_SRGB_To_WideGamutRGB(float r1, float g1, float b1, float r2, float g2, float b2)
{
// Arrange
- Rgb input = new Rgb(r1, g1, b1, RgbWorkingSpaces.SRgb);
- Rgb expectedOutput = new Rgb(r2, g2, b2, RgbWorkingSpaces.WideGamutRgb);
- ColorSpaceConverter converter = new ColorSpaceConverter { TargetRgbWorkingSpace = RgbWorkingSpaces.WideGamutRgb };
+ var input = new Rgb(r1, g1, b1, RgbWorkingSpaces.SRgb);
+ var expectedOutput = new Rgb(r2, g2, b2, RgbWorkingSpaces.WideGamutRgb);
+ var converter = new ColorSpaceConverter { TargetRgbWorkingSpace = RgbWorkingSpaces.WideGamutRgb };
// Action
Rgb output = converter.Adapt(input);
@@ -69,9 +69,9 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
public void Adapt_Lab_D50_To_D65(float l1, float a1, float b1, float l2, float a2, float b2)
{
// Arrange
- CieLab input = new CieLab(l1, a1, b1, Illuminants.D65);
- CieLab expectedOutput = new CieLab(l2, a2, b2);
- ColorSpaceConverter converter = new ColorSpaceConverter { TargetLabWhitePoint = Illuminants.D50 };
+ var input = new CieLab(l1, a1, b1, Illuminants.D65);
+ var expectedOutput = new CieLab(l2, a2, b2);
+ var converter = new ColorSpaceConverter { TargetLabWhitePoint = Illuminants.D50 };
// Action
CieLab output = converter.Adapt(input);
@@ -110,9 +110,9 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
public void Adapt_CieXyz_D65_To_D50_XyzScaling(float x1, float y1, float z1, float x2, float y2, float z2)
{
// Arrange
- CieXyz input = new CieXyz(x1, y1, z1);
- CieXyz expectedOutput = new CieXyz(x2, y2, z2);
- ColorSpaceConverter converter = new ColorSpaceConverter
+ var input = new CieXyz(x1, y1, z1);
+ var expectedOutput = new CieXyz(x2, y2, z2);
+ var converter = new ColorSpaceConverter
{
ChromaticAdaptation = new VonKriesChromaticAdaptation(LmsAdaptationMatrix.XyzScaling),
WhitePoint = Illuminants.D50
@@ -133,9 +133,9 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
public void Adapt_Xyz_D65_To_D50_XyzScaling(float x1, float y1, float z1, float x2, float y2, float z2)
{
// Arrange
- CieXyz input = new CieXyz(x1, y1, z1);
- CieXyz expectedOutput = new CieXyz(x2, y2, z2);
- ColorSpaceConverter converter = new ColorSpaceConverter
+ var input = new CieXyz(x1, y1, z1);
+ var expectedOutput = new CieXyz(x2, y2, z2);
+ var converter = new ColorSpaceConverter
{
ChromaticAdaptation = new VonKriesChromaticAdaptation(LmsAdaptationMatrix.XyzScaling),
WhitePoint = Illuminants.D50
diff --git a/tests/ImageSharp.Tests/Colorspaces/RgbAndCieXyzConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/RgbAndCieXyzConversionTest.cs
index e7f197878..929c35ee9 100644
--- a/tests/ImageSharp.Tests/Colorspaces/RgbAndCieXyzConversionTest.cs
+++ b/tests/ImageSharp.Tests/Colorspaces/RgbAndCieXyzConversionTest.cs
@@ -35,8 +35,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
public void Convert_XYZ_D50_to_SRGB(float x, float y, float z, float r, float g, float b)
{
// Arrange
- CieXyz input = new CieXyz(x, y, z);
- ColorSpaceConverter converter = new ColorSpaceConverter { WhitePoint = Illuminants.D50, TargetRgbWorkingSpace = RgbWorkingSpaces.SRgb };
+ var input = new CieXyz(x, y, z);
+ var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D50, TargetRgbWorkingSpace = RgbWorkingSpaces.SRgb };
// Act
Rgb output = converter.ToRgb(input);
@@ -92,12 +92,12 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
public void Convert_SRGB_to_XYZ_D50(float r, float g, float b, float x, float y, float z)
{
// Arrange
- Rgb input = new Rgb(r, g, b);
- ColorSpaceConverter converter = new ColorSpaceConverter { WhitePoint = Illuminants.D50 };
+ var input = new Rgb(r, g, b);
+ var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D50 };
// Act
CieXyz output = converter.ToCieXyz(input);
-
+
// Assert
IEqualityComparer comparer = new ApproximateFloatComparer(0.001f);
Assert.Equal(x, output.X, comparer);
@@ -119,8 +119,8 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
public void Convert_SRGB_to_XYZ_D65(float r, float g, float b, float x, float y, float z)
{
// Arrange
- Rgb input = new Rgb(r, g, b);
- ColorSpaceConverter converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65 };
+ var input = new Rgb(r, g, b);
+ var converter = new ColorSpaceConverter { WhitePoint = Illuminants.D65 };
// Act
CieXyz output = converter.ToCieXyz(input);
diff --git a/tests/ImageSharp.Tests/Colorspaces/RgbAndHslConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/RgbAndHslConversionTest.cs
index f658ddaae..4f1537932 100644
--- a/tests/ImageSharp.Tests/Colorspaces/RgbAndHslConversionTest.cs
+++ b/tests/ImageSharp.Tests/Colorspaces/RgbAndHslConversionTest.cs
@@ -37,7 +37,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
public void Convert_Hsl_To_Rgb(float h, float s, float l, float r, float g, float b)
{
// Arrange
- Hsl input = new Hsl(h, s, l);
+ var input = new Hsl(h, s, l);
// Act
Rgb output = Converter.ToRgb(input);
@@ -61,7 +61,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
public void Convert_Rgb_To_Hsl(float r, float g, float b, float h, float s, float l)
{
// Arrange
- Rgb input = new Rgb(r, g, b);
+ var input = new Rgb(r, g, b);
// Act
Hsl output = Converter.ToHsl(input);
diff --git a/tests/ImageSharp.Tests/Colorspaces/RgbAndHsvConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/RgbAndHsvConversionTest.cs
index 63b3d9b74..7f46ff1fc 100644
--- a/tests/ImageSharp.Tests/Colorspaces/RgbAndHsvConversionTest.cs
+++ b/tests/ImageSharp.Tests/Colorspaces/RgbAndHsvConversionTest.cs
@@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
public void Convert_Hsv_To_Rgb(float h, float s, float v, float r, float g, float b)
{
// Arrange
- Hsv input = new Hsv(h, s, v);
+ var input = new Hsv(h, s, v);
// Act
Rgb output = Converter.ToRgb(input);
@@ -60,7 +60,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
public void Convert_Rgb_To_Hsv(float r, float g, float b, float h, float s, float v)
{
// Arrange
- Rgb input = new Rgb(r, g, b);
+ var input = new Rgb(r, g, b);
// Act
Hsv output = Converter.ToHsv(input);
diff --git a/tests/ImageSharp.Tests/Colorspaces/RgbAndYCbCrConversionTest.cs b/tests/ImageSharp.Tests/Colorspaces/RgbAndYCbCrConversionTest.cs
index 96c302e25..46c12e3a5 100644
--- a/tests/ImageSharp.Tests/Colorspaces/RgbAndYCbCrConversionTest.cs
+++ b/tests/ImageSharp.Tests/Colorspaces/RgbAndYCbCrConversionTest.cs
@@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
public void Convert_YCbCr_To_Rgb(float y, float cb, float cr, float r, float g, float b)
{
// Arrange
- YCbCr input = new YCbCr(y, cb, cr);
+ var input = new YCbCr(y, cb, cr);
// Act
Rgb output = Converter.ToRgb(input);
@@ -55,7 +55,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
public void Convert_Rgb_To_YCbCr(float r, float g, float b, float y, float cb, float cr)
{
// Arrange
- Rgb input = new Rgb(r, g, b);
+ var input = new Rgb(r, g, b);
// Act
YCbCr output = Converter.ToYCbCr(input);
diff --git a/tests/ImageSharp.Tests/Common/ConstantsTests.cs b/tests/ImageSharp.Tests/Common/ConstantsTests.cs
index 48ecbbbc9..38d754d60 100644
--- a/tests/ImageSharp.Tests/Common/ConstantsTests.cs
+++ b/tests/ImageSharp.Tests/Common/ConstantsTests.cs
@@ -13,4 +13,4 @@ namespace SixLabors.ImageSharp.Tests.Common
Assert.Equal(0.001f, Constants.Epsilon);
}
}
-}
+}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/Common/SimdUtilsTests.cs b/tests/ImageSharp.Tests/Common/SimdUtilsTests.cs
index d16c053cd..c6c3b68f3 100644
--- a/tests/ImageSharp.Tests/Common/SimdUtilsTests.cs
+++ b/tests/ImageSharp.Tests/Common/SimdUtilsTests.cs
@@ -1,18 +1,18 @@
-using System;
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+using System.Linq;
using System.Numerics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using SixLabors.ImageSharp.Common.Tuples;
+
using Xunit;
-// ReSharper disable InconsistentNaming
+using Xunit.Abstractions;
namespace SixLabors.ImageSharp.Tests.Common
{
- using System.Linq;
- using System.Runtime.CompilerServices;
- using System.Runtime.InteropServices;
- using SixLabors.ImageSharp.Common.Tuples;
-
- using Xunit.Abstractions;
- using Xunit.Sdk;
-
public class SimdUtilsTests
{
private ITestOutputHelper Output { get; }
@@ -36,22 +36,10 @@ namespace SixLabors.ImageSharp.Tests.Common
Vector4 actual = v.PseudoRound();
- Assert.Equal(
- R(v.X),
- (int)actual.X
- );
- Assert.Equal(
- R(v.Y),
- (int)actual.Y
- );
- Assert.Equal(
- R(v.Z),
- (int)actual.Z
- );
- Assert.Equal(
- R(v.W),
- (int)actual.W
- );
+ Assert.Equal(R(v.X), (int)actual.X);
+ Assert.Equal(R(v.Y), (int)actual.Y);
+ Assert.Equal(R(v.Z), (int)actual.Z);
+ Assert.Equal(R(v.W), (int)actual.W);
}
private static Vector CreateExactTestVector1()
@@ -73,12 +61,15 @@ namespace SixLabors.ImageSharp.Tests.Common
private static Vector CreateRandomTestVector(int seed, float min, float max)
{
float[] data = new float[Vector.Count];
- Random rnd = new Random();
+
+ var rnd = new Random();
+
for (int i = 0; i < Vector.Count; i++)
{
- float v = (float)rnd.NextDouble() * (max-min) + min;
+ float v = (float)rnd.NextDouble() * (max - min) + min;
data[i] = v;
}
+
return new Vector(data);
}
@@ -102,7 +93,7 @@ namespace SixLabors.ImageSharp.Tests.Common
[InlineData(42, 1000f)]
public void FastRound_RandomValues(int seed, float scale)
{
- Vector v = CreateRandomTestVector(seed, -scale*0.5f, scale*0.5f);
+ Vector v = CreateRandomTestVector(seed, -scale * 0.5f, scale * 0.5f);
Vector r = v.FastRound();
this.Output.WriteLine(v.ToString());
@@ -118,6 +109,7 @@ namespace SixLabors.ImageSharp.Tests.Common
this.Output.WriteLine("Skipping AVX2 specific test case: " + testCaseName);
return true;
}
+
return false;
}
@@ -133,7 +125,7 @@ namespace SixLabors.ImageSharp.Tests.Common
return;
}
- float[] orig = new Random(seed).GenerateRandomRoundedFloatArray(count, 0, 256);
+ float[] orig = new Random(seed).GenerateRandomRoundedFloatArray(count, 0, 256);
float[] normalized = orig.Select(f => f / 255f).ToArray();
byte[] dest = new byte[count];
@@ -158,12 +150,12 @@ namespace SixLabors.ImageSharp.Tests.Common
}
float[] source = new Random(seed).GenerateRandomFloatArray(count, 0, 1f);
-
+
byte[] dest = new byte[count];
-
+
SimdUtils.BulkConvertNormalizedFloatToByte(source, dest);
- byte[] expected = source.Select(f => (byte)Math.Round(f*255f)).ToArray();
+ byte[] expected = source.Select(f => (byte)Math.Round(f * 255f)).ToArray();
Assert.Equal(expected, dest);
}
@@ -217,16 +209,17 @@ namespace SixLabors.ImageSharp.Tests.Common
return;
}
- float[] source = {0, 7, 42, 255, 0.5f, 1.1f, 2.6f, 16f};
- byte[] expected = source.Select(f => (byte)Math.Round(f)).ToArray();
+ float[] source = { 0, 7, 42, 255, 0.5f, 1.1f, 2.6f, 16f };
+
+ var expected = source.Select(f => (byte)Math.Round(f)).ToArray();
source = source.Select(f => f / 255f).ToArray();
- byte[] dest = new byte[8];
+ Span dest = stackalloc byte[8];
this.MagicConvert(source, dest);
- Assert.Equal(expected, dest);
+ Assert.True(dest.SequenceEqual(expected));
}
private static byte MagicConvert(float x)
@@ -239,10 +232,11 @@ namespace SixLabors.ImageSharp.Tests.Common
private void MagicConvert(Span source, Span dest)
{
var magick = new Vector(32768.0f);
+
Vector scale = new Vector(255f) / new Vector(256f);
Vector x = MemoryMarshal.Cast>(source)[0];
-
+
x = (x * scale) + magick;
Tuple8.OfUInt32 ii = default;
@@ -252,7 +246,7 @@ namespace SixLabors.ImageSharp.Tests.Common
iiRef = x;
//Tuple8.OfUInt32 ii = Unsafe.As, Tuple8.OfUInt32>(ref x);
-
+
ref Tuple8.OfByte d = ref MemoryMarshal.Cast(dest)[0];
d.LoadFrom(ref ii);
@@ -266,6 +260,7 @@ namespace SixLabors.ImageSharp.Tests.Common
{
int actual = (int)r[i];
int expected = Re(v[i]);
+
Assert.Equal(expected, actual);
}
}
diff --git a/src/ImageSharp/Common/Tuples/Tuple8.cs b/tests/ImageSharp.Tests/Common/Tuple8.cs
similarity index 100%
rename from src/ImageSharp/Common/Tuples/Tuple8.cs
rename to tests/ImageSharp.Tests/Common/Tuple8.cs
diff --git a/tests/ImageSharp.Tests/ComplexIntegrationTests.cs b/tests/ImageSharp.Tests/ComplexIntegrationTests.cs
index 86703959a..ed4bb6104 100644
--- a/tests/ImageSharp.Tests/ComplexIntegrationTests.cs
+++ b/tests/ImageSharp.Tests/ComplexIntegrationTests.cs
@@ -1,13 +1,12 @@
-namespace SixLabors.ImageSharp.Tests
-{
- using SixLabors.ImageSharp.Formats.Jpeg;
- using SixLabors.ImageSharp.PixelFormats;
- using SixLabors.ImageSharp.Processing;
- using SixLabors.ImageSharp.Processing.Transforms;
- using SixLabors.Primitives;
+using SixLabors.ImageSharp.Formats.Jpeg;
+using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.ImageSharp.Processing.Transforms;
+using SixLabors.Primitives;
- using Xunit;
+using Xunit;
+namespace SixLabors.ImageSharp.Tests
+{
///
/// Might be useful to catch complex bugs
///
diff --git a/tests/ImageSharp.Tests/ConfigurationTests.cs b/tests/ImageSharp.Tests/ConfigurationTests.cs
index cf348569c..88aabfe33 100644
--- a/tests/ImageSharp.Tests/ConfigurationTests.cs
+++ b/tests/ImageSharp.Tests/ConfigurationTests.cs
@@ -1,95 +1,95 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using SixLabors.ImageSharp.Formats;
-using SixLabors.ImageSharp.IO;
-using SixLabors.ImageSharp.PixelFormats;
-using Moq;
-using Xunit;
-
-namespace SixLabors.ImageSharp.Tests
-{
- ///
- /// Tests the configuration class.
- ///
- public class ConfigurationTests
- {
- public Configuration ConfigurationEmpty { get; private set; }
- public Configuration DefaultConfiguration { get; private set; }
-
- public ConfigurationTests()
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using SixLabors.ImageSharp.Formats;
+using SixLabors.ImageSharp.IO;
+using SixLabors.ImageSharp.PixelFormats;
+using Moq;
+using Xunit;
+
+namespace SixLabors.ImageSharp.Tests
+{
+ ///
+ /// Tests the configuration class.
+ ///
+ public class ConfigurationTests
+ {
+ public Configuration ConfigurationEmpty { get; private set; }
+ public Configuration DefaultConfiguration { get; private set; }
+
+ public ConfigurationTests()
{
// the shallow copy of configuration should behave exactly like the default configuration,
- // so by using the copy, we test both the default and the copy.
- this.DefaultConfiguration = Configuration.CreateDefaultInstance().ShallowCopy();
- this.ConfigurationEmpty = new Configuration();
- }
-
- [Fact]
- public void DefaultsToLocalFileSystem()
- {
- Assert.IsType(this.DefaultConfiguration.FileSystem);
- Assert.IsType(this.ConfigurationEmpty.FileSystem);
- }
-
- ///
- /// Test that the default configuration is not null.
- ///
- [Fact]
- public void TestDefultConfigurationIsNotNull()
- {
- Assert.True(Configuration.Default != null);
- }
-
- ///
- /// Test that the default configuration parallel options is not null.
- ///
- [Fact]
- public void TestDefultConfigurationParallelOptionsIsNotNull()
- {
- Assert.True(Configuration.Default.ParallelOptions != null);
- }
-
- ///
- /// Test that the default configuration read origin options is set to begin.
- ///
- [Fact]
- public void TestDefultConfigurationReadOriginIsCurrent()
- {
- Assert.True(Configuration.Default.ReadOrigin == ReadOrigin.Current);
- }
-
- ///
- /// Test that the default configuration parallel options max degrees of parallelism matches the
- /// environment processor count.
- ///
- [Fact]
- public void TestDefultConfigurationMaxDegreeOfParallelism()
- {
- Assert.True(Configuration.Default.ParallelOptions.MaxDegreeOfParallelism == Environment.ProcessorCount);
- }
-
- [Fact]
- public void ConstructorCallConfigureOnFormatProvider()
- {
- var provider = new Mock();
- var config = new Configuration(provider.Object);
-
- provider.Verify(x => x.Configure(config));
- }
-
- [Fact]
- public void AddFormatCallsConfig()
- {
- var provider = new Mock();
- var config = new Configuration();
- config.Configure(provider.Object);
-
- provider.Verify(x => x.Configure(config));
- }
- }
+ // so by using the copy, we test both the default and the copy.
+ this.DefaultConfiguration = Configuration.CreateDefaultInstance().ShallowCopy();
+ this.ConfigurationEmpty = new Configuration();
+ }
+
+ [Fact]
+ public void DefaultsToLocalFileSystem()
+ {
+ Assert.IsType(this.DefaultConfiguration.FileSystem);
+ Assert.IsType(this.ConfigurationEmpty.FileSystem);
+ }
+
+ ///
+ /// Test that the default configuration is not null.
+ ///
+ [Fact]
+ public void TestDefultConfigurationIsNotNull()
+ {
+ Assert.True(Configuration.Default != null);
+ }
+
+ ///
+ /// Test that the default configuration parallel options is not null.
+ ///
+ [Fact]
+ public void TestDefultConfigurationParallelOptionsIsNotNull()
+ {
+ Assert.True(Configuration.Default.ParallelOptions != null);
+ }
+
+ ///
+ /// Test that the default configuration read origin options is set to begin.
+ ///
+ [Fact]
+ public void TestDefultConfigurationReadOriginIsCurrent()
+ {
+ Assert.True(Configuration.Default.ReadOrigin == ReadOrigin.Current);
+ }
+
+ ///
+ /// Test that the default configuration parallel options max degrees of parallelism matches the
+ /// environment processor count.
+ ///
+ [Fact]
+ public void TestDefultConfigurationMaxDegreeOfParallelism()
+ {
+ Assert.True(Configuration.Default.ParallelOptions.MaxDegreeOfParallelism == Environment.ProcessorCount);
+ }
+
+ [Fact]
+ public void ConstructorCallConfigureOnFormatProvider()
+ {
+ var provider = new Mock();
+ var config = new Configuration(provider.Object);
+
+ provider.Verify(x => x.Configure(config));
+ }
+
+ [Fact]
+ public void AddFormatCallsConfig()
+ {
+ var provider = new Mock();
+ var config = new Configuration();
+ config.Configure(provider.Object);
+
+ provider.Verify(x => x.Configure(config));
+ }
+ }
}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/Drawing/BeziersTests.cs b/tests/ImageSharp.Tests/Drawing/BeziersTests.cs
index a0f62c4e7..daa640a0b 100644
--- a/tests/ImageSharp.Tests/Drawing/BeziersTests.cs
+++ b/tests/ImageSharp.Tests/Drawing/BeziersTests.cs
@@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing
public void ImageShouldBeOverlayedByBezierLine()
{
string path = TestEnvironment.CreateOutputDirectory("Drawing", "BezierLine");
- using (Image image = new Image(500, 500))
+ using (var image = new Image(500, 500))
{
image.Mutate(x => x.BackgroundColor(Rgba32.Blue)
.DrawBeziers(Rgba32.HotPink, 5,
@@ -54,9 +54,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing
{
string path = TestEnvironment.CreateOutputDirectory("Drawing", "BezierLine");
- Rgba32 color = new Rgba32(Rgba32.HotPink.R, Rgba32.HotPink.G, Rgba32.HotPink.B, 150);
+ var color = new Rgba32(Rgba32.HotPink.R, Rgba32.HotPink.G, Rgba32.HotPink.B, 150);
- using (Image image = new Image(500, 500))
+ using (var image = new Image(500, 500))
{
image.Mutate(x => x.BackgroundColor(Rgba32.Blue)
.DrawBeziers(color,
@@ -70,7 +70,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing
image.Save($"{path}/Opacity.png");
//shift background color towards foreground color by the opacity amount
- Rgba32 mergedColor = new Rgba32(Vector4.Lerp(Rgba32.Blue.ToVector4(), Rgba32.HotPink.ToVector4(), 150f / 255f));
+ var mergedColor = new Rgba32(Vector4.Lerp(Rgba32.Blue.ToVector4(), Rgba32.HotPink.ToVector4(), 150f / 255f));
using (PixelAccessor sourcePixels = image.Lock())
{
diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs
index 0ff0b8557..d0087b1d2 100644
--- a/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs
+++ b/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs
@@ -3,8 +3,8 @@
using System;
using System.Numerics;
-using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Processing.Drawing;
using SixLabors.Primitives;
using Xunit;
@@ -93,7 +93,7 @@ namespace SixLabors.ImageSharp.Tests
Assert.Equal(Rgba32.White, backgroundPixel);
Assert.Equal(overlayPixel, background[0, 0]);
- background.DebugSave(provider, new[] { "Negative" });
+ background.DebugSave(provider, testOutputDetails: "Negative");
}
}
@@ -115,7 +115,7 @@ namespace SixLabors.ImageSharp.Tests
Assert.Equal(Rgba32.White, backgroundPixel);
Assert.Equal(overlayPixel, background[xy, xy]);
- background.DebugSave(provider, new[] { "Positive" });
+ background.DebugSave(provider, testOutputDetails: "Positive");
}
}
}
diff --git a/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs b/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs
index dbf0e6ce9..7e75f52b2 100644
--- a/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs
+++ b/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs
@@ -90,7 +90,6 @@ namespace SixLabors.ImageSharp.Tests.Drawing
}
}
-
[Fact]
public void PathExtendingOffEdgeOfImageShouldNotBeCropped()
{
diff --git a/tests/ImageSharp.Tests/Drawing/FillPatternTests.cs b/tests/ImageSharp.Tests/Drawing/FillPatternTests.cs
index 7db88e959..5b47e7835 100644
--- a/tests/ImageSharp.Tests/Drawing/FillPatternTests.cs
+++ b/tests/ImageSharp.Tests/Drawing/FillPatternTests.cs
@@ -3,17 +3,15 @@
using System;
using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.ImageSharp.Primitives;
+using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Processing.Drawing;
using SixLabors.ImageSharp.Processing.Drawing.Brushes;
-
+using SixLabors.ImageSharp.Processing.Transforms;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Drawing
{
- using SixLabors.ImageSharp.Primitives;
- using SixLabors.ImageSharp.Processing;
- using SixLabors.ImageSharp.Processing.Transforms;
-
public class FillPatternBrushTests : FileTestBase
{
private void Test(string name, Rgba32 background, IBrush brush, Rgba32[,] expectedPattern)
@@ -36,9 +34,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing
int yStride = expectedPatternFast.Rows;
int offsetX = r.Next(image.Width / xStride) * xStride;
int offsetY = r.Next(image.Height / yStride) * yStride;
- for (var x = 0; x < xStride; x++)
+ for (int x = 0; x < xStride; x++)
{
- for (var y = 0; y < yStride; y++)
+ for (int y = 0; y < yStride; y++)
{
int actualX = x + offsetX;
int actualY = y + offsetY;
diff --git a/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs b/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs
index c995dd31b..8c619c817 100644
--- a/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs
+++ b/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs
@@ -4,7 +4,7 @@
using System.Numerics;
using Moq;
-using Xunit;
+
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
using SixLabors.ImageSharp.Processing;
@@ -14,6 +14,8 @@ using SixLabors.ImageSharp.Processing.Drawing.Pens;
using SixLabors.ImageSharp.Processing.Drawing.Processors;
using SixLabors.Primitives;
+using Xunit;
+
namespace SixLabors.ImageSharp.Tests.Drawing
{
public class FillRegionProcessorTests
diff --git a/tests/ImageSharp.Tests/Drawing/FillSolidBrushTests.cs b/tests/ImageSharp.Tests/Drawing/FillSolidBrushTests.cs
index aa360c893..02e34092e 100644
--- a/tests/ImageSharp.Tests/Drawing/FillSolidBrushTests.cs
+++ b/tests/ImageSharp.Tests/Drawing/FillSolidBrushTests.cs
@@ -3,14 +3,13 @@
using System.Numerics;
using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Processing.Drawing;
+using SixLabors.ImageSharp.Processing.Overlays;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Drawing
{
- using SixLabors.ImageSharp.Processing;
- using SixLabors.ImageSharp.Processing.Overlays;
-
public class FillSolidBrushTests : FileTestBase
{
[Fact]
diff --git a/tests/ImageSharp.Tests/Drawing/LineComplexPolygonTests.cs b/tests/ImageSharp.Tests/Drawing/LineComplexPolygonTests.cs
index 0e0df6844..09ed46908 100644
--- a/tests/ImageSharp.Tests/Drawing/LineComplexPolygonTests.cs
+++ b/tests/ImageSharp.Tests/Drawing/LineComplexPolygonTests.cs
@@ -3,16 +3,16 @@
using System.Numerics;
using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Processing.Drawing;
using SixLabors.ImageSharp.Processing.Drawing.Pens;
+using SixLabors.ImageSharp.Processing.Overlays;
using SixLabors.Shapes;
+
using Xunit;
namespace SixLabors.ImageSharp.Tests.Drawing
{
- using SixLabors.ImageSharp.Processing;
- using SixLabors.ImageSharp.Processing.Overlays;
-
public class LineComplexPolygonTests : FileTestBase
{
[Fact]
@@ -87,9 +87,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing
using (PixelAccessor sourcePixels = image.Lock())
{
Assert.Equal(Rgba32.HotPink, sourcePixels[10, 10]);
-
Assert.Equal(Rgba32.HotPink, sourcePixels[200, 150]);
-
Assert.Equal(Rgba32.HotPink, sourcePixels[50, 300]);
@@ -110,7 +108,6 @@ namespace SixLabors.ImageSharp.Tests.Drawing
}
}
-
[Fact]
public void ImageShouldBeOverlayedByPolygonOutlineOverlapping()
{
@@ -135,13 +132,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing
using (PixelAccessor sourcePixels = image.Lock())
{
Assert.Equal(Rgba32.HotPink, sourcePixels[10, 10]);
-
Assert.Equal(Rgba32.HotPink, sourcePixels[200, 150]);
-
Assert.Equal(Rgba32.HotPink, sourcePixels[50, 300]);
-
Assert.Equal(Rgba32.Blue, sourcePixels[130, 41]);
-
Assert.Equal(Rgba32.Blue, sourcePixels[2, 2]);
//inside hole
@@ -153,7 +146,6 @@ namespace SixLabors.ImageSharp.Tests.Drawing
}
}
-
[Fact]
public void ImageShouldBeOverlayedByPolygonOutlineDashed()
{
@@ -177,7 +169,6 @@ namespace SixLabors.ImageSharp.Tests.Drawing
}
}
-
[Fact]
public void ImageShouldBeOverlayedPolygonOutlineWithOpacity()
{
@@ -206,24 +197,16 @@ namespace SixLabors.ImageSharp.Tests.Drawing
using (PixelAccessor sourcePixels = image.Lock())
{
Assert.Equal(mergedColor, sourcePixels[10, 10]);
-
Assert.Equal(mergedColor, sourcePixels[200, 150]);
-
Assert.Equal(mergedColor, sourcePixels[50, 300]);
-
-
Assert.Equal(mergedColor, sourcePixels[37, 85]);
-
Assert.Equal(mergedColor, sourcePixels[93, 85]);
-
Assert.Equal(mergedColor, sourcePixels[65, 137]);
-
Assert.Equal(Rgba32.Blue, sourcePixels[2, 2]);
//inside hole
Assert.Equal(Rgba32.Blue, sourcePixels[57, 99]);
-
//inside shape
Assert.Equal(Rgba32.Blue, sourcePixels[100, 192]);
}
diff --git a/tests/ImageSharp.Tests/Drawing/LineTests.cs b/tests/ImageSharp.Tests/Drawing/LineTests.cs
index e23616b1e..6128756c5 100644
--- a/tests/ImageSharp.Tests/Drawing/LineTests.cs
+++ b/tests/ImageSharp.Tests/Drawing/LineTests.cs
@@ -2,24 +2,24 @@
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
+
using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Processing.Drawing;
using SixLabors.ImageSharp.Processing.Drawing.Pens;
+using SixLabors.ImageSharp.Processing.Overlays;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Drawing
{
- using SixLabors.ImageSharp.Processing;
- using SixLabors.ImageSharp.Processing.Overlays;
-
public class LineTests : FileTestBase
{
[Fact]
public void ImageShouldBeOverlayedByPath()
{
string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines");
- using (Image image = new Image(500, 500))
+ using (var image = new Image(500, 500))
{
image.Mutate(x => x
.BackgroundColor(Rgba32.Blue)
@@ -46,13 +46,13 @@ namespace SixLabors.ImageSharp.Tests.Drawing
public void ImageShouldBeOverlayedByPath_NoAntialias()
{
string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines");
- using (Image image = new Image(500, 500))
+ using (var image = new Image(500, 500))
{
image.Mutate(x => x
.BackgroundColor(Rgba32.Blue)
.DrawLines(
new GraphicsOptions(false),
- Rgba32.HotPink,
+ Rgba32.HotPink,
5,
new SixLabors.Primitives.PointF[] {
new Vector2(10, 10),
@@ -76,7 +76,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing
public void ImageShouldBeOverlayedByPathDashed()
{
string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines");
- using (Image image = new Image(500, 500))
+ using (var image = new Image(500, 500))
{
image.Mutate(x => x
.BackgroundColor(Rgba32.Blue)
@@ -94,7 +94,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing
public void ImageShouldBeOverlayedByPathDotted()
{
string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines");
- using (Image image = new Image(500, 500))
+ using (var image = new Image(500, 500))
{
image.Mutate(x => x
.BackgroundColor(Rgba32.Blue)
@@ -112,7 +112,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing
public void ImageShouldBeOverlayedByPathDashDot()
{
string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines");
- using (Image image = new Image(500, 500))
+ using (var image = new Image(500, 500))
{
image.Mutate(x => x
.BackgroundColor(Rgba32.Blue)
@@ -130,7 +130,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing
public void ImageShouldBeOverlayedByPathDashDotDot()
{
string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines");
- Image image = new Image(500, 500);
+ var image = new Image(500, 500);
image.Mutate(x => x
.BackgroundColor(Rgba32.Blue)
@@ -147,9 +147,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing
{
string path = TestEnvironment.CreateOutputDirectory("Drawing", "Lines");
- Rgba32 color = new Rgba32(Rgba32.HotPink.R, Rgba32.HotPink.G, Rgba32.HotPink.B, 150);
+ var color = new Rgba32(Rgba32.HotPink.R, Rgba32.HotPink.G, Rgba32.HotPink.B, 150);
- Image image = new Image