Browse Source

Merge remote-tracking branch 'origin/master' into webp

pull/1552/head
Brian Popow 6 years ago
parent
commit
653b26a3a4
  1. 15
      src/ImageSharp/Advanced/IPixelSource.cs
  2. 2
      src/ImageSharp/ColorSpaces/Cmyk.cs
  3. 4
      src/ImageSharp/ColorSpaces/Companding/LCompanding.cs
  4. 6
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs
  5. 3
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs
  6. 6
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs
  7. 6
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs
  8. 4
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs
  9. 6
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyy.cs
  10. 6
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs
  11. 6
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Cmyk.cs
  12. 6
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsl.cs
  13. 6
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsv.cs
  14. 4
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs
  15. 6
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs
  16. 6
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.YCbCr.cs
  17. 5
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs
  18. 5
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverterOptions.cs
  19. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyChromaticityCoordinates.cs
  20. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CIeLchToCieLabConverter.cs
  21. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieLchConverter.cs
  22. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieXyzConverter.cs
  23. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLchuvToCieLuvConverter.cs
  24. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieLchuvConverter.cs
  25. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieXyzConverter.cs
  26. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndCieXyyConverter.cs
  27. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndHunterLabConverterBase.cs
  28. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndLmsConverter.cs
  29. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToCieLabConverter.cs
  30. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToCieLuvConverter.cs
  31. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToHunterLabConverter.cs
  32. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToLinearRgbConverter.cs
  33. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CmykAndRgbConverter.cs
  34. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HslAndRgbConverter.cs
  35. 4
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HsvAndRgbConverter.cs
  36. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs
  37. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbAndCieXyzConverterBase.cs
  38. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToCieXyzConverter.cs
  39. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToRgbConverter.cs
  40. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/RgbToLinearRgbConverter.cs
  41. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/YCbCrAndRgbConverter.cs
  42. 0
      src/ImageSharp/ColorSpaces/Conversion/Implementation/IChromaticAdaptation.cs
  43. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/LmsAdaptationMatrix.cs
  44. 4
      src/ImageSharp/ColorSpaces/Conversion/Implementation/RGBPrimariesChromaticityCoordinates.cs
  45. 5
      src/ImageSharp/ColorSpaces/Conversion/Implementation/VonKriesChromaticAdaptation.cs
  46. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs
  47. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/LWorkingSpace.cs
  48. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec2020WorkingSpace.cs
  49. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec709WorkingSpace.cs
  50. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpace.cs
  51. 4
      src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/SRgbWorkingSpace.cs
  52. 6
      src/ImageSharp/ColorSpaces/LinearRgb.cs
  53. 6
      src/ImageSharp/ColorSpaces/Rgb.cs
  54. 6
      src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs
  55. 6
      src/ImageSharp/Common/Extensions/ComparableExtensions.cs
  56. 12
      src/ImageSharp/Common/Helpers/DenseMatrixUtils.cs
  57. 2
      src/ImageSharp/Common/Helpers/ImageMaths.cs
  58. 7
      src/ImageSharp/Common/Helpers/SimdUtils.FallbackIntrinsics128.cs
  59. 2
      src/ImageSharp/Common/Helpers/SimdUtils.cs
  60. 18
      src/ImageSharp/Common/Helpers/Vector4Utilities.cs
  61. 49
      src/ImageSharp/Formats/Gif/GifDecoderCore.cs
  62. 3
      src/ImageSharp/Formats/Gif/GifEncoderCore.cs
  63. 24
      src/ImageSharp/Formats/Gif/LzwDecoder.cs
  64. 179
      src/ImageSharp/Formats/Gif/LzwEncoder.cs
  65. 32
      src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs
  66. 2
      src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt
  67. 2
      src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs
  68. 4
      src/ImageSharp/Formats/Png/Zlib/DeflaterConstants.cs
  69. 2
      src/ImageSharp/Formats/Png/Zlib/DeflaterEngine.cs
  70. 36
      src/ImageSharp/Formats/Tga/ImageExtensions.cs
  71. 1
      src/ImageSharp/Formats/Tga/TgaDecoder.cs
  72. 555
      src/ImageSharp/Formats/Tga/TgaDecoderCore.cs
  73. 20
      src/ImageSharp/Formats/Tga/TgaEncoderCore.cs
  74. 28
      src/ImageSharp/Formats/Tga/TgaImageOrigin.cs
  75. 5
      src/ImageSharp/Formats/Tga/TgaMetadata.cs
  76. 6
      src/ImageSharp/GeometryUtilities.cs
  77. 125
      src/ImageSharp/Image.FromBytes.cs
  78. 99
      src/ImageSharp/Image.FromFile.cs
  79. 68
      src/ImageSharp/Image.FromStream.cs
  80. 12
      src/ImageSharp/ImageExtensions.cs
  81. 28
      src/ImageSharp/IndexedImageFrame{TPixel}.cs
  82. 2
      src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs
  83. 2
      src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs
  84. 2
      src/ImageSharp/PixelFormats/PixelImplementations/Bgra4444.cs
  85. 2
      src/ImageSharp/PixelFormats/PixelImplementations/Bgra5551.cs
  86. 2
      src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs
  87. 2
      src/ImageSharp/PixelFormats/PixelImplementations/L16.cs
  88. 2
      src/ImageSharp/PixelFormats/PixelImplementations/L8.cs
  89. 2
      src/ImageSharp/PixelFormats/PixelImplementations/La16.cs
  90. 2
      src/ImageSharp/PixelFormats/PixelImplementations/La32.cs
  91. 2
      src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs
  92. 2
      src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort4.cs
  93. 2
      src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs
  94. 2
      src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs
  95. 2
      src/ImageSharp/PixelFormats/PixelImplementations/Rgba1010102.cs
  96. 4
      src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs
  97. 4
      src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs
  98. 2
      src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs
  99. 2
      src/ImageSharp/PixelFormats/PixelImplementations/Short4.cs
  100. 4
      src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs

15
src/ImageSharp/Advanced/IPixelSource.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Memory;
@ -6,6 +6,17 @@ using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Advanced
{
/// <summary>
/// Encapsulates the basic properties and methods required to manipulate images.
/// </summary>
internal interface IPixelSource
{
/// <summary>
/// Gets the pixel buffer.
/// </summary>
Buffer2D<byte> PixelBuffer { get; }
}
/// <summary>
/// Encapsulates the basic properties and methods required to manipulate images.
/// </summary>
@ -18,4 +29,4 @@ namespace SixLabors.ImageSharp.Advanced
/// </summary>
Buffer2D<TPixel> PixelBuffer { get; }
}
}
}

2
src/ImageSharp/ColorSpaces/Cmyk.cs

@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
[MethodImpl(InliningOptions.ShortMethod)]
public Cmyk(Vector4 vector)
{
vector = Vector4.Clamp(vector, Min, Max);
vector = Vector4Utilities.FastClamp(vector, Min, Max);
this.C = vector.X;
this.M = vector.Y;
this.Y = vector.Z;

4
src/ImageSharp/ColorSpaces/Companding/LCompanding.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
@ -35,4 +35,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding
public static float Compress(float channel)
=> channel <= CieConstants.Epsilon ? (channel * CieConstants.Kappa) / 100F : (1.16F * MathF.Pow(channel, 0.3333333F)) - 0.16F;
}
}
}

6
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs

@ -1,8 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <content>
@ -157,4 +155,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
return this.ToRgb(linearOutput);
}
}
}
}

3
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs

@ -1,10 +1,9 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{

6
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs

@ -1,12 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <content>
@ -447,4 +445,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
}
}
}
}
}

6
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs

@ -1,12 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <content>
@ -447,4 +445,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
}
}
}
}
}

4
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs

@ -1,12 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <content>

6
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyy.cs

@ -1,12 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <content>
@ -440,4 +438,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
}
}
}
}
}

6
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs

@ -1,12 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <content>
@ -475,4 +473,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
return this.linearRgbToCieXyzConverter = new LinearRgbToCieXyzConverter(workingSpace);
}
}
}
}

6
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Cmyk.cs

@ -1,12 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <content>
@ -440,4 +438,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
}
}
}
}
}

6
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsl.cs

@ -1,12 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <content>
@ -440,4 +438,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
}
}
}
}
}

6
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsv.cs

@ -1,12 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <content>
@ -440,4 +438,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
}
}
}
}
}

4
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs

@ -1,12 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <content>

6
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs

@ -1,12 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <content>
@ -438,4 +436,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
return this.Adapt(rgb);
}
}
}
}

6
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.YCbCr.cs

@ -1,12 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <content>
@ -407,4 +405,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="YCbCr"/></returns>
public YCbCr ToYCbCr(in Rgb color) => YCbCrAndRgbConverter.Convert(color);
}
}
}

5
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs

@ -1,8 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
@ -58,4 +57,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
this.cieXyzToLinearRgbConverter = new CieXyzToLinearRgbConverter(this.targetRgbWorkingSpace);
}
}
}
}

5
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverterOptions.cs

@ -1,8 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
@ -52,4 +51,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
public Matrix4x4 LmsAdaptationMatrix { get; set; } = CieXyzAndLmsConverter.DefaultTransformationMatrix;
}
}
}

6
src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs → src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyChromaticityCoordinates.cs

@ -1,11 +1,11 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
// ReSharper disable CompareOfFloatsByEqualityOperator
namespace SixLabors.ImageSharp.ColorSpaces
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Represents the coordinates of CIEXY chromaticity space.
@ -76,4 +76,4 @@ namespace SixLabors.ImageSharp.ColorSpaces
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(CieXyChromaticityCoordinates other) => this.X.Equals(other.X) && this.Y.Equals(other.Y);
}
}
}

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CIeLchToCieLabConverter.cs

@ -4,7 +4,7 @@
using System;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Converts from <see cref="CieLch"/> to <see cref="CieLab"/>.

6
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieLchConverter.cs

@ -1,10 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Converts from <see cref="CieLab"/> to <see cref="CieLch"/>.
@ -38,4 +38,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
return new CieLch(l, c, hDegrees, input.WhitePoint);
}
}
}
}

6
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieXyzConverter.cs

@ -1,10 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Converts from <see cref="CieLab"/> to <see cref="CieXyz"/>.
@ -41,4 +41,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
return new CieXyz(xyz);
}
}
}
}

6
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLchuvToCieLuvConverter.cs

@ -1,10 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Converts from <see cref="CieLch"/> to <see cref="CieLab"/>.
@ -30,4 +30,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
return new CieLuv(l, u, v, input.WhitePoint);
}
}
}
}

6
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieLchuvConverter.cs

@ -1,10 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Converts from <see cref="CieLab"/> to <see cref="CieLch"/>.
@ -38,4 +38,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
return new CieLchuv(l, c, hDegrees, input.WhitePoint);
}
}
}
}

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieXyzConverter.cs

@ -3,7 +3,7 @@
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Converts from <see cref="CieLuv"/> to <see cref="CieXyz"/>.

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndCieXyyConverter.cs

@ -4,7 +4,7 @@
using System;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Color converter between CIE XYZ and CIE xyY.

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndHunterLabConverterBase.cs

@ -3,7 +3,7 @@
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// The base class for converting between <see cref="HunterLab"/> and <see cref="CieXyz"/> color spaces.

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndLmsConverter.cs

@ -4,7 +4,7 @@
using System.Numerics;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Color converter between <see cref="CieXyz"/> and <see cref="Lms"/>

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToCieLabConverter.cs

@ -4,7 +4,7 @@
using System;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Converts from <see cref="CieXyz"/> to <see cref="CieLab"/>.

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToCieLuvConverter.cs

@ -4,7 +4,7 @@
using System;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Converts from <see cref="CieXyz"/> to <see cref="CieLuv"/>.

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToHunterLabConverter.cs

@ -4,7 +4,7 @@
using System;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Color converter between <see cref="CieXyz"/> and <see cref="HunterLab"/>

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzToLinearRgbConverter.cs

@ -4,7 +4,7 @@
using System.Numerics;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Color converter between <see cref="CieXyz"/> and <see cref="LinearRgb"/>

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CmykAndRgbConverter.cs

@ -5,7 +5,7 @@ using System;
using System.Numerics;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Color converter between <see cref="Cmyk"/> and <see cref="Rgb"/>.

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HslAndRgbConverter.cs

@ -4,7 +4,7 @@
using System;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Color converter between HSL and Rgb

4
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HsvAndRgbConverter.cs

@ -4,7 +4,7 @@
using System;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Color converter between HSV and Rgb
@ -127,4 +127,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
return new Hsv(h, s, v);
}
}
}
}

6
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs

@ -1,10 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Color converter between <see cref="HunterLab"/> and <see cref="CieXyz"/>
@ -36,4 +36,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
return new CieXyz(x, y, z);
}
}
}
}

6
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbAndCieXyzConverterBase.cs

@ -1,9 +1,9 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Provides base methods for converting between <see cref="LinearRgb"/> and <see cref="CieXyz"/> color spaces.
@ -74,4 +74,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
};
}
}
}
}

6
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToCieXyzConverter.cs

@ -1,10 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Color converter between <see cref="LinearRgb"/> and <see cref="CieXyz"/>
@ -50,4 +50,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
return new CieXyz(vector);
}
}
}
}

6
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToRgbConverter.cs

@ -1,9 +1,9 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Color converter between <see cref="LinearRgb"/> and <see cref="Rgb"/>.
@ -25,4 +25,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
workingSpace: input.WorkingSpace);
}
}
}
}

6
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/RgbToLinearRgbConverter.cs

@ -1,9 +1,9 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Color converter between Rgb and LinearRgb.
@ -25,4 +25,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
workingSpace: input.WorkingSpace);
}
}
}
}

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/YCbCrAndRgbConverter.cs

@ -5,7 +5,7 @@ using System;
using System.Numerics;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Color converter between <see cref="YCbCr"/> and <see cref="Rgb"/>

0
src/ImageSharp/ColorSpaces/Conversion/IChromaticAdaptation.cs → src/ImageSharp/ColorSpaces/Conversion/Implementation/IChromaticAdaptation.cs

6
src/ImageSharp/ColorSpaces/Conversion/Implementation/LmsAdaptationMatrix.cs

@ -1,9 +1,9 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Matrices used for transformation from <see cref="CieXyz"/> to <see cref="Lms"/>, defining the cone response domain.
@ -131,4 +131,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
M44 = 1F
});
}
}
}

4
src/ImageSharp/ColorSpaces/Conversion/Implementation/RGBPrimariesChromaticityCoordinates.cs

@ -1,9 +1,9 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Represents the chromaticity coordinates of RGB primaries.

5
src/ImageSharp/ColorSpaces/Conversion/VonKriesChromaticAdaptation.cs → src/ImageSharp/ColorSpaces/Conversion/Implementation/VonKriesChromaticAdaptation.cs

@ -1,11 +1,10 @@
// Copyright (c) Six Labors and contributors.
// 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;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
@ -99,4 +98,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
}
}
}
}
}

6
src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs

@ -1,11 +1,11 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.ColorSpaces.Companding;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// The gamma working space.
@ -63,4 +63,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
this.ChromaticityCoordinates,
this.Gamma);
}
}
}

6
src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/LWorkingSpace.cs

@ -1,10 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.ColorSpaces.Companding;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// L* working space.
@ -29,4 +29,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
[MethodImpl(InliningOptions.ShortMethod)]
public override float Expand(float channel) => LCompanding.Expand(channel);
}
}
}

6
src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec2020WorkingSpace.cs

@ -1,10 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.ColorSpaces.Companding;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Rec. 2020 (ITU-R Recommendation BT.2020F) working space.
@ -29,4 +29,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
[MethodImpl(InliningOptions.ShortMethod)]
public override float Expand(float channel) => Rec2020Companding.Expand(channel);
}
}
}

6
src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/Rec709WorkingSpace.cs

@ -1,10 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.ColorSpaces.Companding;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Rec. 709 (ITU-R Recommendation BT.709) working space.
@ -29,4 +29,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
[MethodImpl(InliningOptions.ShortMethod)]
public override float Expand(float channel) => Rec709Companding.Expand(channel);
}
}
}

6
src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpace.cs

@ -1,9 +1,9 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// Base class for all implementations of <see cref="RgbWorkingSpace"/>.
@ -81,4 +81,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
return HashCode.Combine(this.WhitePoint, this.ChromaticityCoordinates);
}
}
}
}

4
src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/SRgbWorkingSpace.cs

@ -1,10 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.ColorSpaces.Companding;
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
/// <summary>
/// The sRgb working space.

6
src/ImageSharp/ColorSpaces/LinearRgb.cs

@ -1,10 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
using SixLabors.ImageSharp.ColorSpaces.Conversion;
namespace SixLabors.ImageSharp.ColorSpaces
{
@ -143,4 +143,4 @@ namespace SixLabors.ImageSharp.ColorSpaces
&& this.B.Equals(other.B);
}
}
}
}

6
src/ImageSharp/ColorSpaces/Rgb.cs

@ -1,10 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
using SixLabors.ImageSharp.ColorSpaces.Conversion;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.ColorSpaces
@ -164,4 +164,4 @@ namespace SixLabors.ImageSharp.ColorSpaces
&& this.B.Equals(other.B);
}
}
}
}

6
src/ImageSharp/ColorSpaces/RgbWorkingSpaces.cs

@ -1,8 +1,8 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.ColorSpaces.Companding;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
using SixLabors.ImageSharp.ColorSpaces.Conversion;
// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.ColorSpaces
@ -112,4 +112,4 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// </summary>
public static readonly RgbWorkingSpace WideGamutRgb = new GammaWorkingSpace(2.2F, Illuminants.D50, new RgbPrimariesChromaticityCoordinates(new CieXyChromaticityCoordinates(0.7350F, 0.2650F), new CieXyChromaticityCoordinates(0.1150F, 0.8260F), new CieXyChromaticityCoordinates(0.1570F, 0.0180F)));
}
}
}

6
src/ImageSharp/Common/Extensions/ComparableExtensions.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp
/// <summary>
/// Restricts a <see cref="byte"/> to be within a specified range.
/// </summary>
/// <param name="value">The The value to clamp.</param>
/// <param name="value">The value to clamp.</param>
/// <param name="min">The minimum value. If value is less than min, min will be returned.</param>
/// <param name="max">The maximum value. If value is greater than max, max will be returned.</param>
/// <returns>
@ -137,4 +137,4 @@ namespace SixLabors.ImageSharp
return value;
}
}
}
}

12
src/ImageSharp/Common/Helpers/DenseMatrixUtils.cs

@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp
ref Vector4 target = ref Unsafe.Add(ref targetRowRef, column);
vector.W = target.W;
Vector4Utils.UnPremultiply(ref vector);
Vector4Utilities.UnPremultiply(ref vector);
target = vector;
}
@ -105,7 +105,7 @@ namespace SixLabors.ImageSharp
out Vector4 vector);
ref Vector4 target = ref Unsafe.Add(ref targetRowRef, column);
Vector4Utils.UnPremultiply(ref vector);
Vector4Utilities.UnPremultiply(ref vector);
target = vector;
}
@ -140,7 +140,7 @@ namespace SixLabors.ImageSharp
{
int offsetX = (sourceOffsetColumnBase + x - radiusX).Clamp(minColumn, maxColumn);
var currentColor = sourceRowSpan[offsetX].ToVector4();
Vector4Utils.Premultiply(ref currentColor);
Vector4Utilities.Premultiply(ref currentColor);
vectorX += matrixX[y, x] * currentColor;
vectorY += matrixY[y, x] * currentColor;
@ -193,7 +193,7 @@ namespace SixLabors.ImageSharp
ref Vector4 target = ref Unsafe.Add(ref targetRowRef, column);
vector.W = target.W;
Vector4Utils.UnPremultiply(ref vector);
Vector4Utilities.UnPremultiply(ref vector);
target = vector;
}
@ -238,7 +238,7 @@ namespace SixLabors.ImageSharp
ref vector);
ref Vector4 target = ref Unsafe.Add(ref targetRowRef, column);
Vector4Utils.UnPremultiply(ref vector);
Vector4Utilities.UnPremultiply(ref vector);
target = vector;
}
@ -270,7 +270,7 @@ namespace SixLabors.ImageSharp
{
int offsetX = (sourceOffsetColumnBase + x - radiusX).Clamp(minColumn, maxColumn);
var currentColor = sourceRowSpan[offsetX].ToVector4();
Vector4Utils.Premultiply(ref currentColor);
Vector4Utilities.Premultiply(ref currentColor);
vector += matrix[y, x] * currentColor;
}
}

2
src/ImageSharp/Common/Helpers/ImageMaths.cs

@ -359,7 +359,7 @@ namespace SixLabors.ImageSharp
}
}
return height;
return width;
}
topLeft.Y = GetMinY(bitmap);

7
src/ImageSharp/Common/Helpers/SimdUtils.FallbackIntrinsics128.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
@ -125,10 +125,7 @@ namespace SixLabors.ImageSharp
Vector4 s = Unsafe.Add(ref sBase, i);
s *= maxBytes;
s += half;
// I'm not sure if Vector4.Clamp() is properly implemented with intrinsics.
s = Vector4.Max(Vector4.Zero, s);
s = Vector4.Min(maxBytes, s);
s = Vector4Utilities.FastClamp(s, Vector4.Zero, maxBytes);
ref ByteVector4 d = ref Unsafe.Add(ref dBase, i);
d.X = (byte)s.X;

2
src/ImageSharp/Common/Helpers/SimdUtils.cs

@ -28,7 +28,7 @@ namespace SixLabors.ImageSharp
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static Vector4 PseudoRound(this Vector4 v)
{
var sign = Vector4.Clamp(v, new Vector4(-1), new Vector4(1));
var sign = Vector4Utilities.FastClamp(v, new Vector4(-1), new Vector4(1));
return v + (sign * 0.5f);
}

18
src/ImageSharp/Common/Helpers/Vector4Utils.cs → src/ImageSharp/Common/Helpers/Vector4Utilities.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
@ -11,8 +11,20 @@ namespace SixLabors.ImageSharp
/// <summary>
/// Utility methods for the <see cref="Vector4"/> struct.
/// </summary>
internal static class Vector4Utils
internal static class Vector4Utilities
{
/// <summary>
/// Restricts a vector between a minimum and a maximum value.
/// 5x Faster then <see cref="Vector4.Clamp(Vector4, Vector4, Vector4)"/>.
/// </summary>
/// <param name="x">The vector to restrict.</param>
/// <param name="min">The minimum value.</param>
/// <param name="max">The maximum value.</param>
/// <returns>The <see cref="Vector4"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static Vector4 FastClamp(Vector4 x, Vector4 min, Vector4 max)
=> Vector4.Min(Vector4.Max(x, min), max);
/// <summary>
/// Pre-multiplies the "x", "y", "z" components of a vector by its "w" component leaving the "w" component intact.
/// </summary>
@ -107,4 +119,4 @@ namespace SixLabors.ImageSharp
}
}
}
}
}

49
src/ImageSharp/Formats/Gif/GifDecoderCore.cs

@ -353,7 +353,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
this.ReadImageDescriptor();
IManagedByteBuffer localColorTable = null;
IManagedByteBuffer indices = null;
Buffer2D<byte> indices = null;
try
{
// Determine the color table for this frame. If there is a local one, use it otherwise use the global color table.
@ -364,11 +364,11 @@ namespace SixLabors.ImageSharp.Formats.Gif
this.stream.Read(localColorTable.Array, 0, length);
}
indices = this.configuration.MemoryAllocator.AllocateManagedByteBuffer(this.imageDescriptor.Width * this.imageDescriptor.Height, AllocationOptions.Clean);
indices = this.configuration.MemoryAllocator.Allocate2D<byte>(this.imageDescriptor.Width, this.imageDescriptor.Height, AllocationOptions.Clean);
this.ReadFrameIndices(this.imageDescriptor, indices.GetSpan());
this.ReadFrameIndices(indices);
ReadOnlySpan<Rgb24> colorTable = MemoryMarshal.Cast<byte, Rgb24>((localColorTable ?? this.globalColorTable).GetSpan());
this.ReadFrameColors(ref image, ref previousFrame, indices.GetSpan(), colorTable, this.imageDescriptor);
this.ReadFrameColors(ref image, ref previousFrame, indices, colorTable, this.imageDescriptor);
// Skip any remaining blocks
this.SkipBlock();
@ -383,16 +383,13 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <summary>
/// Reads the frame indices marking the color to use for each pixel.
/// </summary>
/// <param name="imageDescriptor">The <see cref="GifImageDescriptor"/>.</param>
/// <param name="indices">The pixel array to write to.</param>
/// <param name="indices">The 2D pixel buffer to write to.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ReadFrameIndices(in GifImageDescriptor imageDescriptor, Span<byte> indices)
private void ReadFrameIndices(Buffer2D<byte> indices)
{
int dataSize = this.stream.ReadByte();
using (var lzwDecoder = new LzwDecoder(this.configuration.MemoryAllocator, this.stream))
{
lzwDecoder.DecodePixels(imageDescriptor.Width, imageDescriptor.Height, dataSize, indices);
}
using var lzwDecoder = new LzwDecoder(this.configuration.MemoryAllocator, this.stream);
lzwDecoder.DecodePixels(dataSize, indices);
}
/// <summary>
@ -404,10 +401,9 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <param name="indices">The indexed pixels.</param>
/// <param name="colorTable">The color table containing the available colors.</param>
/// <param name="descriptor">The <see cref="GifImageDescriptor"/></param>
private void ReadFrameColors<TPixel>(ref Image<TPixel> image, ref ImageFrame<TPixel> previousFrame, Span<byte> indices, ReadOnlySpan<Rgb24> colorTable, in GifImageDescriptor descriptor)
private void ReadFrameColors<TPixel>(ref Image<TPixel> image, ref ImageFrame<TPixel> previousFrame, Buffer2D<byte> indices, ReadOnlySpan<Rgb24> colorTable, in GifImageDescriptor descriptor)
where TPixel : unmanaged, IPixel<TPixel>
{
ref byte indicesRef = ref MemoryMarshal.GetReference(indices);
int imageWidth = this.logicalScreenDescriptor.Width;
int imageHeight = this.logicalScreenDescriptor.Height;
@ -440,13 +436,20 @@ namespace SixLabors.ImageSharp.Formats.Gif
this.RestoreToBackground(imageFrame);
}
int i = 0;
int interlacePass = 0; // The interlace pass
int interlaceIncrement = 8; // The interlacing line increment
int interlaceY = 0; // The current interlaced line
for (int y = descriptor.Top; y < descriptor.Top + descriptor.Height; y++)
int descriptorTop = descriptor.Top;
int descriptorBottom = descriptorTop + descriptor.Height;
int descriptorLeft = descriptor.Left;
int descriptorRight = descriptorLeft + descriptor.Width;
bool transFlag = this.graphicsControlExtension.TransparencyFlag;
byte transIndex = this.graphicsControlExtension.TransparencyIndex;
for (int y = descriptorTop; y < descriptorBottom && y < imageHeight; y++)
{
ref byte indicesRowRef = ref MemoryMarshal.GetReference(indices.GetRowSpan(y - descriptorTop));
// Check if this image is interlaced.
int writeY; // the target y offset to write to
if (descriptor.InterlaceFlag)
@ -482,35 +485,29 @@ namespace SixLabors.ImageSharp.Formats.Gif
}
ref TPixel rowRef = ref MemoryMarshal.GetReference(imageFrame.GetPixelRowSpan(writeY));
bool transFlag = this.graphicsControlExtension.TransparencyFlag;
if (!transFlag)
{
// #403 The left + width value can be larger than the image width
for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width && x < imageWidth; x++)
for (int x = descriptorLeft; x < descriptorRight && x < imageWidth; x++)
{
int index = Unsafe.Add(ref indicesRef, i);
int index = Unsafe.Add(ref indicesRowRef, x - descriptorLeft);
ref TPixel pixel = ref Unsafe.Add(ref rowRef, x);
Rgb24 rgb = colorTable[index];
pixel.FromRgb24(rgb);
i++;
}
}
else
{
byte transIndex = this.graphicsControlExtension.TransparencyIndex;
for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width && x < imageWidth; x++)
for (int x = descriptorLeft; x < descriptorRight && x < imageWidth; x++)
{
int index = Unsafe.Add(ref indicesRef, i);
int index = Unsafe.Add(ref indicesRowRef, x - descriptorLeft);
if (transIndex != index)
{
ref TPixel pixel = ref Unsafe.Add(ref rowRef, x);
Rgb24 rgb = colorTable[index];
pixel.FromRgb24(rgb);
}
i++;
}
}
}

3
src/ImageSharp/Formats/Gif/GifEncoderCore.cs

@ -6,6 +6,7 @@ using System.Buffers;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats;
@ -471,7 +472,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
where TPixel : unmanaged, IPixel<TPixel>
{
using var encoder = new LzwEncoder(this.memoryAllocator, (byte)this.bitDepth);
encoder.Encode(image.GetPixelBufferSpan(), stream);
encoder.Encode(((IPixelSource)image).PixelBuffer, stream);
}
}
}

24
src/ImageSharp/Formats/Gif/LzwDecoder.cs

@ -65,15 +65,15 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <summary>
/// Decodes and decompresses all pixel indices from the stream.
/// </summary>
/// <param name="width">The width of the pixel index array.</param>
/// <param name="height">The height of the pixel index array.</param>
/// <param name="dataSize">Size of the data.</param>
/// <param name="pixels">The pixel array to decode to.</param>
public void DecodePixels(int width, int height, int dataSize, Span<byte> pixels)
public void DecodePixels(int dataSize, Buffer2D<byte> pixels)
{
Guard.MustBeLessThan(dataSize, int.MaxValue, nameof(dataSize));
// The resulting index table length.
int width = pixels.Width;
int height = pixels.Height;
int length = width * height;
// Calculate the clear code. The value of the clear code is 2 ^ dataSize
@ -105,17 +105,28 @@ namespace SixLabors.ImageSharp.Formats.Gif
ref int prefixRef = ref MemoryMarshal.GetReference(this.prefix.GetSpan());
ref int suffixRef = ref MemoryMarshal.GetReference(this.suffix.GetSpan());
ref int pixelStackRef = ref MemoryMarshal.GetReference(this.pixelStack.GetSpan());
ref byte pixelsRef = ref MemoryMarshal.GetReference(pixels);
for (code = 0; code < clearCode; code++)
{
Unsafe.Add(ref suffixRef, code) = (byte)code;
}
Span<byte> buffer = stackalloc byte[255];
Span<byte> buffer = stackalloc byte[byte.MaxValue];
int y = 0;
int x = 0;
int rowMax = width;
ref byte pixelsRowRef = ref MemoryMarshal.GetReference(pixels.GetRowSpan(y));
while (xyz < length)
{
// Reset row reference.
if (xyz == rowMax)
{
x = 0;
pixelsRowRef = ref MemoryMarshal.GetReference(pixels.GetRowSpan(++y));
rowMax = (y * width) + width;
}
if (top == 0)
{
if (bits < codeSize)
@ -209,7 +220,8 @@ namespace SixLabors.ImageSharp.Formats.Gif
top--;
// Clear missing pixels
Unsafe.Add(ref pixelsRef, xyz++) = (byte)Unsafe.Add(ref pixelStackRef, top);
xyz++;
Unsafe.Add(ref pixelsRowRef, x++) = (byte)Unsafe.Add(ref pixelStackRef, top);
}
}

179
src/ImageSharp/Formats/Gif/LzwEncoder.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
@ -41,13 +41,33 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// </summary>
private const int HashSize = 5003;
/// <summary>
/// The amount to shift each code.
/// </summary>
private const int HashShift = 4;
/// <summary>
/// Mask used when shifting pixel values
/// </summary>
private static readonly int[] Masks =
{
0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF,
0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF
0b0,
0b1,
0b11,
0b111,
0b1111,
0b11111,
0b111111,
0b1111111,
0b11111111,
0b111111111,
0b1111111111,
0b11111111111,
0b111111111111,
0b1111111111111,
0b11111111111111,
0b111111111111111,
0b1111111111111111
};
/// <summary>
@ -80,16 +100,6 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// </summary>
private readonly byte[] accumulators = new byte[256];
/// <summary>
/// For dynamic table sizing
/// </summary>
private readonly int hsize = HashSize;
/// <summary>
/// The current position within the pixelArray.
/// </summary>
private int position;
/// <summary>
/// Number of bits/code
/// </summary>
@ -177,15 +187,13 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <summary>
/// Encodes and compresses the indexed pixels to the stream.
/// </summary>
/// <param name="indexedPixels">The span of indexed pixels.</param>
/// <param name="indexedPixels">The 2D buffer of indexed pixels.</param>
/// <param name="stream">The stream to write to.</param>
public void Encode(ReadOnlySpan<byte> indexedPixels, Stream stream)
public void Encode(Buffer2D<byte> indexedPixels, Stream stream)
{
// Write "initial code size" byte
stream.WriteByte((byte)this.initialCodeSize);
this.position = 0;
// Compress and write the pixel data
this.Compress(indexedPixels, this.initialCodeSize + 1, stream);
@ -199,10 +207,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <param name="bitCount">The number of bits</param>
/// <returns>See <see cref="int"/></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int GetMaxcode(int bitCount)
{
return (1 << bitCount) - 1;
}
private static int GetMaxcode(int bitCount) => (1 << bitCount) - 1;
/// <summary>
/// Add a character to the end of the current packet, and if it is 254 characters,
@ -239,25 +244,16 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// Reset the code table.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ResetCodeTable()
{
this.hashTable.GetSpan().Fill(-1);
}
private void ResetCodeTable() => this.hashTable.GetSpan().Fill(-1);
/// <summary>
/// Compress the packets to the stream.
/// </summary>
/// <param name="indexedPixels">The span of indexed pixels.</param>
/// <param name="indexedPixels">The 2D buffer of indexed pixels.</param>
/// <param name="initialBits">The initial bits.</param>
/// <param name="stream">The stream to write to.</param>
private void Compress(ReadOnlySpan<byte> indexedPixels, int initialBits, Stream stream)
private void Compress(Buffer2D<byte> indexedPixels, int initialBits, Stream stream)
{
int fcode;
int c;
int ent;
int hsizeReg;
int hshift;
// Set up the globals: globalInitialBits - initial number of bits
this.globalInitialBits = initialBits;
@ -265,92 +261,82 @@ namespace SixLabors.ImageSharp.Formats.Gif
this.clearFlag = false;
this.bitCount = this.globalInitialBits;
this.maxCode = GetMaxcode(this.bitCount);
this.clearCode = 1 << (initialBits - 1);
this.eofCode = this.clearCode + 1;
this.freeEntry = this.clearCode + 2;
this.accumulatorCount = 0; // Clear packet
this.accumulatorCount = 0; // clear packet
ent = this.NextPixel(indexedPixels);
// TODO: PERF: It looks like hshift could be calculated once statically.
hshift = 0;
for (fcode = this.hsize; fcode < 65536; fcode *= 2)
{
++hshift;
}
hshift = 8 - hshift; // set hash code range bound
hsizeReg = this.hsize;
this.ResetCodeTable(); // clear hash table
this.ResetCodeTable(); // Clear hash table
this.Output(this.clearCode, stream);
ref int hashTableRef = ref MemoryMarshal.GetReference(this.hashTable.GetSpan());
ref int codeTableRef = ref MemoryMarshal.GetReference(this.codeTable.GetSpan());
while (this.position < indexedPixels.Length)
{
c = this.NextPixel(indexedPixels);
int entry = indexedPixels[0, 0];
fcode = (c << MaxBits) + ent;
int i = (c << hshift) ^ ent /* = 0 */;
for (int y = 0; y < indexedPixels.Height; y++)
{
ref byte rowSpanRef = ref MemoryMarshal.GetReference(indexedPixels.GetRowSpan(y));
int offsetX = y == 0 ? 1 : 0;
if (Unsafe.Add(ref hashTableRef, i) == fcode)
for (int x = offsetX; x < indexedPixels.Width; x++)
{
ent = Unsafe.Add(ref codeTableRef, i);
continue;
}
int code = Unsafe.Add(ref rowSpanRef, x);
int freeCode = (code << MaxBits) + entry;
int hashIndex = (code << HashShift) ^ entry;
// Non-empty slot
if (Unsafe.Add(ref hashTableRef, i) >= 0)
{
int disp = 1;
if (i != 0)
if (Unsafe.Add(ref hashTableRef, hashIndex) == freeCode)
{
disp = hsizeReg - i;
entry = Unsafe.Add(ref codeTableRef, hashIndex);
continue;
}
do
// Non-empty slot
if (Unsafe.Add(ref hashTableRef, hashIndex) >= 0)
{
if ((i -= disp) < 0)
int disp = 1;
if (hashIndex != 0)
{
disp = HashSize - hashIndex;
}
do
{
i += hsizeReg;
if ((hashIndex -= disp) < 0)
{
hashIndex += HashSize;
}
if (Unsafe.Add(ref hashTableRef, hashIndex) == freeCode)
{
entry = Unsafe.Add(ref codeTableRef, hashIndex);
break;
}
}
while (Unsafe.Add(ref hashTableRef, hashIndex) >= 0);
if (Unsafe.Add(ref hashTableRef, i) == fcode)
if (Unsafe.Add(ref hashTableRef, hashIndex) == freeCode)
{
ent = Unsafe.Add(ref codeTableRef, i);
break;
continue;
}
}
while (Unsafe.Add(ref hashTableRef, i) >= 0);
if (Unsafe.Add(ref hashTableRef, i) == fcode)
this.Output(entry, stream);
entry = code;
if (this.freeEntry < MaxMaxCode)
{
continue;
Unsafe.Add(ref codeTableRef, hashIndex) = this.freeEntry++; // code -> hashtable
Unsafe.Add(ref hashTableRef, hashIndex) = freeCode;
}
else
{
this.ClearBlock(stream);
}
}
this.Output(ent, stream);
ent = c;
if (this.freeEntry < MaxMaxCode)
{
Unsafe.Add(ref codeTableRef, i) = this.freeEntry++; // code -> hashtable
Unsafe.Add(ref hashTableRef, i) = fcode;
}
else
{
this.ClearBlock(stream);
}
}
// Put out the final code.
this.Output(ent, stream);
// Output the final code.
this.Output(entry, stream);
this.Output(this.eofCode, stream);
}
@ -366,19 +352,6 @@ namespace SixLabors.ImageSharp.Formats.Gif
this.accumulatorCount = 0;
}
/// <summary>
/// Reads the next pixel from the image.
/// </summary>
/// <param name="indexedPixels">The span of indexed pixels.</param>
/// <returns>
/// The <see cref="int"/>
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private int NextPixel(ReadOnlySpan<byte> indexedPixels)
{
return indexedPixels[this.position++] & 0xFF;
}
/// <summary>
/// Output the current code to the stream.
/// </summary>

32
src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs

@ -99,22 +99,22 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
var CMax4 = new Vector4(maximum);
var COff4 = new Vector4(MathF.Ceiling(maximum / 2));
this.V0L = Vector4.Clamp(this.V0L + COff4, CMin4, CMax4);
this.V0R = Vector4.Clamp(this.V0R + COff4, CMin4, CMax4);
this.V1L = Vector4.Clamp(this.V1L + COff4, CMin4, CMax4);
this.V1R = Vector4.Clamp(this.V1R + COff4, CMin4, CMax4);
this.V2L = Vector4.Clamp(this.V2L + COff4, CMin4, CMax4);
this.V2R = Vector4.Clamp(this.V2R + COff4, CMin4, CMax4);
this.V3L = Vector4.Clamp(this.V3L + COff4, CMin4, CMax4);
this.V3R = Vector4.Clamp(this.V3R + COff4, CMin4, CMax4);
this.V4L = Vector4.Clamp(this.V4L + COff4, CMin4, CMax4);
this.V4R = Vector4.Clamp(this.V4R + COff4, CMin4, CMax4);
this.V5L = Vector4.Clamp(this.V5L + COff4, CMin4, CMax4);
this.V5R = Vector4.Clamp(this.V5R + COff4, CMin4, CMax4);
this.V6L = Vector4.Clamp(this.V6L + COff4, CMin4, CMax4);
this.V6R = Vector4.Clamp(this.V6R + COff4, CMin4, CMax4);
this.V7L = Vector4.Clamp(this.V7L + COff4, CMin4, CMax4);
this.V7R = Vector4.Clamp(this.V7R + COff4, CMin4, CMax4);
this.V0L = Vector4Utilities.FastClamp(this.V0L + COff4, CMin4, CMax4);
this.V0R = Vector4Utilities.FastClamp(this.V0R + COff4, CMin4, CMax4);
this.V1L = Vector4Utilities.FastClamp(this.V1L + COff4, CMin4, CMax4);
this.V1R = Vector4Utilities.FastClamp(this.V1R + COff4, CMin4, CMax4);
this.V2L = Vector4Utilities.FastClamp(this.V2L + COff4, CMin4, CMax4);
this.V2R = Vector4Utilities.FastClamp(this.V2R + COff4, CMin4, CMax4);
this.V3L = Vector4Utilities.FastClamp(this.V3L + COff4, CMin4, CMax4);
this.V3R = Vector4Utilities.FastClamp(this.V3R + COff4, CMin4, CMax4);
this.V4L = Vector4Utilities.FastClamp(this.V4L + COff4, CMin4, CMax4);
this.V4R = Vector4Utilities.FastClamp(this.V4R + COff4, CMin4, CMax4);
this.V5L = Vector4Utilities.FastClamp(this.V5L + COff4, CMin4, CMax4);
this.V5R = Vector4Utilities.FastClamp(this.V5R + COff4, CMin4, CMax4);
this.V6L = Vector4Utilities.FastClamp(this.V6L + COff4, CMin4, CMax4);
this.V6R = Vector4Utilities.FastClamp(this.V6R + COff4, CMin4, CMax4);
this.V7L = Vector4Utilities.FastClamp(this.V7L + COff4, CMin4, CMax4);
this.V7R = Vector4Utilities.FastClamp(this.V7R + COff4, CMin4, CMax4);
}
/// <summary>

2
src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt

@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
for (int j = 0; j < 2; j++)
{
char side = j == 0 ? 'L' : 'R';
Write($"this.V{i}{side} = Vector4.Clamp(this.V{i}{side} + COff4, CMin4, CMax4);\r\n");
Write($"this.V{i}{side} = Vector4Utilities.FastClamp(this.V{i}{side} + COff4, CMin4, CMax4);\r\n");
}
}
PopIndent();

2
src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs

@ -589,7 +589,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
private static Vector4 DivideRound(Vector4 dividend, Vector4 divisor)
{
// sign(dividend) = max(min(dividend, 1), -1)
var sign = Vector4.Clamp(dividend, NegativeOne, Vector4.One);
var sign = Vector4Utilities.FastClamp(dividend, NegativeOne, Vector4.One);
// AlmostRound(dividend/divisor) = dividend/divisor + 0.5*sign(dividend)
return (dividend / divisor) + (sign * Offset);

4
src/ImageSharp/Formats/Png/Zlib/DeflaterConstants.cs

@ -3,15 +3,13 @@
// <auto-generated/>
using System;
using System.Collections.Generic;
using System.Text;
namespace SixLabors.ImageSharp.Formats.Png.Zlib
{
/// <summary>
/// This class contains constants used for deflation.
/// </summary>
public static class DeflaterConstants
internal static class DeflaterConstants
{
/// <summary>
/// Set to true to enable debugging

2
src/ImageSharp/Formats/Png/Zlib/DeflaterEngine.cs

@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
/// <summary>
/// Strategies for deflater
/// </summary>
public enum DeflateStrategy
internal enum DeflateStrategy
{
/// <summary>
/// The default strategy

36
src/ImageSharp/Formats/Tga/ImageExtensions.cs

@ -0,0 +1,36 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.IO;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats.Tga;
namespace SixLabors.ImageSharp
{
/// <summary>
/// Extension methods for the <see cref="Image"/> type.
/// </summary>
public static partial class ImageExtensions
{
/// <summary>
/// Saves the image to the given stream with the tga format.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="stream">The stream to save the image to.</param>
/// <exception cref="System.ArgumentNullException">Thrown if the stream is null.</exception>
public static void SaveAsTga(this Image source, Stream stream) => SaveAsTga(source, stream, null);
/// <summary>
/// Saves the image to the given stream with the tga format.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="stream">The stream to save the image to.</param>
/// <param name="encoder">The options for the encoder.</param>
/// <exception cref="System.ArgumentNullException">Thrown if the stream is null.</exception>
public static void SaveAsTga(this Image source, Stream stream, TgaEncoder encoder) =>
source.Save(
stream,
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(TgaFormat.Instance));
}
}

1
src/ImageSharp/Formats/Tga/TgaDecoder.cs

@ -1,7 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.IO;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;

555
src/ImageSharp/Formats/Tga/TgaDecoderCore.cs

@ -12,8 +12,16 @@ using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Tga
{
/// <summary>
/// Performs the tga decoding operation.
/// </summary>
internal sealed class TgaDecoderCore
{
/// <summary>
/// A scratch buffer to reduce allocations.
/// </summary>
private readonly byte[] scratchBuffer = new byte[4];
/// <summary>
/// The metadata.
/// </summary>
@ -49,6 +57,11 @@ namespace SixLabors.ImageSharp.Formats.Tga
/// </summary>
private readonly ITgaDecoderOptions options;
/// <summary>
/// Indicates whether there is a alpha channel present.
/// </summary>
private bool hasAlpha;
/// <summary>
/// Initializes a new instance of the <see cref="TgaDecoderCore"/> class.
/// </summary>
@ -80,7 +93,7 @@ namespace SixLabors.ImageSharp.Formats.Tga
{
try
{
bool inverted = this.ReadFileHeader(stream);
TgaImageOrigin origin = this.ReadFileHeader(stream);
this.currentStream.Skip(this.fileHeader.IdLength);
// Parse the color map, if present.
@ -97,7 +110,7 @@ namespace SixLabors.ImageSharp.Formats.Tga
var image = Image.CreateUninitialized<TPixel>(this.configuration, this.fileHeader.Width, this.fileHeader.Height, this.metadata);
Buffer2D<TPixel> pixels = image.GetRootFramePixelBuffer();
if (this.fileHeader.ColorMapType is 1)
if (this.fileHeader.ColorMapType == 1)
{
if (this.fileHeader.CMapLength <= 0)
{
@ -115,7 +128,7 @@ namespace SixLabors.ImageSharp.Formats.Tga
{
this.currentStream.Read(palette.Array, this.fileHeader.CMapStart, colorMapSizeInBytes);
if (this.fileHeader.ImageType is TgaImageType.RleColorMapped)
if (this.fileHeader.ImageType == TgaImageType.RleColorMapped)
{
this.ReadPalettedRle(
this.fileHeader.Width,
@ -123,7 +136,7 @@ namespace SixLabors.ImageSharp.Formats.Tga
pixels,
palette.Array,
colorMapPixelSizeInBytes,
inverted);
origin);
}
else
{
@ -133,7 +146,7 @@ namespace SixLabors.ImageSharp.Formats.Tga
pixels,
palette.Array,
colorMapPixelSizeInBytes,
inverted);
origin);
}
}
@ -152,11 +165,11 @@ namespace SixLabors.ImageSharp.Formats.Tga
case 8:
if (this.fileHeader.ImageType.IsRunLengthEncoded())
{
this.ReadRle(this.fileHeader.Width, this.fileHeader.Height, pixels, 1, inverted);
this.ReadRle(this.fileHeader.Width, this.fileHeader.Height, pixels, 1, origin);
}
else
{
this.ReadMonoChrome(this.fileHeader.Width, this.fileHeader.Height, pixels, inverted);
this.ReadMonoChrome(this.fileHeader.Width, this.fileHeader.Height, pixels, origin);
}
break;
@ -165,11 +178,11 @@ namespace SixLabors.ImageSharp.Formats.Tga
case 16:
if (this.fileHeader.ImageType.IsRunLengthEncoded())
{
this.ReadRle(this.fileHeader.Width, this.fileHeader.Height, pixels, 2, inverted);
this.ReadRle(this.fileHeader.Width, this.fileHeader.Height, pixels, 2, origin);
}
else
{
this.ReadBgra16(this.fileHeader.Width, this.fileHeader.Height, pixels, inverted);
this.ReadBgra16(this.fileHeader.Width, this.fileHeader.Height, pixels, origin);
}
break;
@ -177,11 +190,11 @@ namespace SixLabors.ImageSharp.Formats.Tga
case 24:
if (this.fileHeader.ImageType.IsRunLengthEncoded())
{
this.ReadRle(this.fileHeader.Width, this.fileHeader.Height, pixels, 3, inverted);
this.ReadRle(this.fileHeader.Width, this.fileHeader.Height, pixels, 3, origin);
}
else
{
this.ReadBgr24(this.fileHeader.Width, this.fileHeader.Height, pixels, inverted);
this.ReadBgr24(this.fileHeader.Width, this.fileHeader.Height, pixels, origin);
}
break;
@ -189,17 +202,17 @@ namespace SixLabors.ImageSharp.Formats.Tga
case 32:
if (this.fileHeader.ImageType.IsRunLengthEncoded())
{
this.ReadRle(this.fileHeader.Width, this.fileHeader.Height, pixels, 4, inverted);
this.ReadRle(this.fileHeader.Width, this.fileHeader.Height, pixels, 4, origin);
}
else
{
this.ReadBgra32(this.fileHeader.Width, this.fileHeader.Height, pixels, inverted);
this.ReadBgra32(this.fileHeader.Width, this.fileHeader.Height, pixels, origin);
}
break;
default:
TgaThrowHelper.ThrowNotSupportedException("Does not support this kind of tga files.");
TgaThrowHelper.ThrowNotSupportedException("ImageSharp does not support this kind of tga files.");
break;
}
@ -220,56 +233,73 @@ namespace SixLabors.ImageSharp.Formats.Tga
/// <param name="pixels">The <see cref="Buffer2D{TPixel}"/> to assign the palette to.</param>
/// <param name="palette">The color palette.</param>
/// <param name="colorMapPixelSizeInBytes">Color map size of one entry in bytes.</param>
/// <param name="inverted">Indicates, if the origin of the image is top left rather the bottom left (the default).</param>
private void ReadPaletted<TPixel>(int width, int height, Buffer2D<TPixel> pixels, byte[] palette, int colorMapPixelSizeInBytes, bool inverted)
/// <param name="origin">The image origin.</param>
private void ReadPaletted<TPixel>(int width, int height, Buffer2D<TPixel> pixels, byte[] palette, int colorMapPixelSizeInBytes, TgaImageOrigin origin)
where TPixel : unmanaged, IPixel<TPixel>
{
using (IManagedByteBuffer row = this.memoryAllocator.AllocateManagedByteBuffer(width, AllocationOptions.Clean))
TPixel color = default;
bool invertX = InvertX(origin);
for (int y = 0; y < height; y++)
{
TPixel color = default;
Span<byte> rowSpan = row.GetSpan();
int newY = InvertY(y, height, origin);
Span<TPixel> pixelRow = pixels.GetRowSpan(newY);
for (int y = 0; y < height; y++)
switch (colorMapPixelSizeInBytes)
{
this.currentStream.Read(row);
int newY = Invert(y, height, inverted);
Span<TPixel> pixelRow = pixels.GetRowSpan(newY);
switch (colorMapPixelSizeInBytes)
{
case 2:
case 2:
if (invertX)
{
for (int x = width - 1; x >= 0; x--)
{
this.ReadPalettedBgra16Pixel(palette, colorMapPixelSizeInBytes, x, color, pixelRow);
}
}
else
{
for (int x = 0; x < width; x++)
{
int colorIndex = rowSpan[x];
// Set alpha value to 1, to treat it as opaque for Bgra5551.
Bgra5551 bgra = Unsafe.As<byte, Bgra5551>(ref palette[colorIndex * colorMapPixelSizeInBytes]);
bgra.PackedValue = (ushort)(bgra.PackedValue | 0x8000);
color.FromBgra5551(bgra);
pixelRow[x] = color;
this.ReadPalettedBgra16Pixel(palette, colorMapPixelSizeInBytes, x, color, pixelRow);
}
}
break;
break;
case 3:
case 3:
if (invertX)
{
for (int x = width - 1; x >= 0; x--)
{
this.ReadPalettedBgr24Pixel(palette, colorMapPixelSizeInBytes, x, color, pixelRow);
}
}
else
{
for (int x = 0; x < width; x++)
{
int colorIndex = rowSpan[x];
color.FromBgr24(Unsafe.As<byte, Bgr24>(ref palette[colorIndex * colorMapPixelSizeInBytes]));
pixelRow[x] = color;
this.ReadPalettedBgr24Pixel(palette, colorMapPixelSizeInBytes, x, color, pixelRow);
}
}
break;
break;
case 4:
case 4:
if (invertX)
{
for (int x = width - 1; x >= 0; x--)
{
this.ReadPalettedBgra32Pixel(palette, colorMapPixelSizeInBytes, x, color, pixelRow);
}
}
else
{
for (int x = 0; x < width; x++)
{
int colorIndex = rowSpan[x];
color.FromBgra32(Unsafe.As<byte, Bgra32>(ref palette[colorIndex * colorMapPixelSizeInBytes]));
pixelRow[x] = color;
this.ReadPalettedBgra32Pixel(palette, colorMapPixelSizeInBytes, x, color, pixelRow);
}
}
break;
}
break;
}
}
}
@ -283,8 +313,8 @@ namespace SixLabors.ImageSharp.Formats.Tga
/// <param name="pixels">The <see cref="Buffer2D{TPixel}"/> to assign the palette to.</param>
/// <param name="palette">The color palette.</param>
/// <param name="colorMapPixelSizeInBytes">Color map size of one entry in bytes.</param>
/// <param name="inverted">Indicates, if the origin of the image is top left rather the bottom left (the default).</param>
private void ReadPalettedRle<TPixel>(int width, int height, Buffer2D<TPixel> pixels, byte[] palette, int colorMapPixelSizeInBytes, bool inverted)
/// <param name="origin">The image origin.</param>
private void ReadPalettedRle<TPixel>(int width, int height, Buffer2D<TPixel> pixels, byte[] palette, int colorMapPixelSizeInBytes, TgaImageOrigin origin)
where TPixel : unmanaged, IPixel<TPixel>
{
int bytesPerPixel = 1;
@ -296,7 +326,7 @@ namespace SixLabors.ImageSharp.Formats.Tga
for (int y = 0; y < height; y++)
{
int newY = Invert(y, height, inverted);
int newY = InvertY(y, height, origin);
Span<TPixel> pixelRow = pixels.GetRowSpan(newY);
int rowStartIdx = y * width * bytesPerPixel;
for (int x = 0; x < width; x++)
@ -308,10 +338,7 @@ namespace SixLabors.ImageSharp.Formats.Tga
color.FromL8(Unsafe.As<byte, L8>(ref palette[bufferSpan[idx] * colorMapPixelSizeInBytes]));
break;
case 2:
// Set alpha value to 1, to treat it as opaque for Bgra5551.
Bgra5551 bgra = Unsafe.As<byte, Bgra5551>(ref palette[bufferSpan[idx] * colorMapPixelSizeInBytes]);
bgra.PackedValue = (ushort)(bgra.PackedValue | 0x8000);
color.FromBgra5551(bgra);
this.ReadPalettedBgra16Pixel(palette, bufferSpan[idx], colorMapPixelSizeInBytes, ref color);
break;
case 3:
color.FromBgr24(Unsafe.As<byte, Bgr24>(ref palette[bufferSpan[idx] * colorMapPixelSizeInBytes]));
@ -321,7 +348,8 @@ namespace SixLabors.ImageSharp.Formats.Tga
break;
}
pixelRow[x] = color;
int newX = InvertX(x, width, origin);
pixelRow[newX] = color;
}
}
}
@ -334,22 +362,43 @@ namespace SixLabors.ImageSharp.Formats.Tga
/// <param name="width">The width of the image.</param>
/// <param name="height">The height of the image.</param>
/// <param name="pixels">The <see cref="Buffer2D{TPixel}"/> to assign the palette to.</param>
/// <param name="inverted">Indicates, if the origin of the image is top left rather the bottom left (the default).</param>
private void ReadMonoChrome<TPixel>(int width, int height, Buffer2D<TPixel> pixels, bool inverted)
/// <param name="origin">the image origin.</param>
private void ReadMonoChrome<TPixel>(int width, int height, Buffer2D<TPixel> pixels, TgaImageOrigin origin)
where TPixel : unmanaged, IPixel<TPixel>
{
using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 1, 0))
bool invertX = InvertX(origin);
if (invertX)
{
TPixel color = default;
for (int y = 0; y < height; y++)
{
this.currentStream.Read(row);
int newY = Invert(y, height, inverted);
int newY = InvertY(y, height, origin);
Span<TPixel> pixelSpan = pixels.GetRowSpan(newY);
PixelOperations<TPixel>.Instance.FromL8Bytes(
this.configuration,
row.GetSpan(),
pixelSpan,
width);
for (int x = width - 1; x >= 0; x--)
{
this.ReadL8Pixel(color, x, pixelSpan);
}
}
return;
}
using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 1, 0))
{
bool invertY = InvertY(origin);
if (invertY)
{
for (int y = height - 1; y >= 0; y--)
{
this.ReadL8Row(width, pixels, row, y);
}
}
else
{
for (int y = 0; y < height; y++)
{
this.ReadL8Row(width, pixels, row, y);
}
}
}
}
@ -361,30 +410,64 @@ namespace SixLabors.ImageSharp.Formats.Tga
/// <param name="width">The width of the image.</param>
/// <param name="height">The height of the image.</param>
/// <param name="pixels">The <see cref="Buffer2D{TPixel}"/> to assign the palette to.</param>
/// <param name="inverted">Indicates, if the origin of the image is top left rather the bottom left (the default).</param>
private void ReadBgra16<TPixel>(int width, int height, Buffer2D<TPixel> pixels, bool inverted)
/// <param name="origin">The image origin.</param>
private void ReadBgra16<TPixel>(int width, int height, Buffer2D<TPixel> pixels, TgaImageOrigin origin)
where TPixel : unmanaged, IPixel<TPixel>
{
TPixel color = default;
bool invertX = InvertX(origin);
using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 2, 0))
{
for (int y = 0; y < height; y++)
{
this.currentStream.Read(row);
Span<byte> rowSpan = row.GetSpan();
int newY = InvertY(y, height, origin);
Span<TPixel> pixelSpan = pixels.GetRowSpan(newY);
// We need to set each alpha component value to fully opaque.
for (int x = 1; x < rowSpan.Length; x += 2)
if (invertX)
{
rowSpan[x] = (byte)(rowSpan[x] | (1 << 7));
for (int x = width - 1; x >= 0; x--)
{
this.currentStream.Read(this.scratchBuffer, 0, 2);
if (!this.hasAlpha)
{
this.scratchBuffer[1] |= 1 << 7;
}
if (this.fileHeader.ImageType == TgaImageType.BlackAndWhite)
{
color.FromLa16(Unsafe.As<byte, La16>(ref this.scratchBuffer[0]));
}
else
{
color.FromBgra5551(Unsafe.As<byte, Bgra5551>(ref this.scratchBuffer[0]));
}
pixelSpan[x] = color;
}
}
else
{
this.currentStream.Read(row);
Span<byte> rowSpan = row.GetSpan();
int newY = Invert(y, height, inverted);
Span<TPixel> pixelSpan = pixels.GetRowSpan(newY);
PixelOperations<TPixel>.Instance.FromBgra5551Bytes(
this.configuration,
rowSpan,
pixelSpan,
width);
if (!this.hasAlpha)
{
// We need to set the alpha component value to fully opaque.
for (int x = 1; x < rowSpan.Length; x += 2)
{
rowSpan[x] |= 1 << 7;
}
}
if (this.fileHeader.ImageType == TgaImageType.BlackAndWhite)
{
PixelOperations<TPixel>.Instance.FromLa16Bytes(this.configuration, rowSpan, pixelSpan, width);
}
else
{
PixelOperations<TPixel>.Instance.FromBgra5551Bytes(this.configuration, rowSpan, pixelSpan, width);
}
}
}
}
}
@ -396,22 +479,44 @@ namespace SixLabors.ImageSharp.Formats.Tga
/// <param name="width">The width of the image.</param>
/// <param name="height">The height of the image.</param>
/// <param name="pixels">The <see cref="Buffer2D{TPixel}"/> to assign the palette to.</param>
/// <param name="inverted">Indicates, if the origin of the image is top left rather the bottom left (the default).</param>
private void ReadBgr24<TPixel>(int width, int height, Buffer2D<TPixel> pixels, bool inverted)
/// <param name="origin">The image origin.</param>
private void ReadBgr24<TPixel>(int width, int height, Buffer2D<TPixel> pixels, TgaImageOrigin origin)
where TPixel : unmanaged, IPixel<TPixel>
{
using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 3, 0))
bool invertX = InvertX(origin);
if (invertX)
{
TPixel color = default;
for (int y = 0; y < height; y++)
{
this.currentStream.Read(row);
int newY = Invert(y, height, inverted);
int newY = InvertY(y, height, origin);
Span<TPixel> pixelSpan = pixels.GetRowSpan(newY);
PixelOperations<TPixel>.Instance.FromBgr24Bytes(
this.configuration,
row.GetSpan(),
pixelSpan,
width);
for (int x = width - 1; x >= 0; x--)
{
this.ReadBgr24Pixel(color, x, pixelSpan);
}
}
return;
}
using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 3, 0))
{
bool invertY = InvertY(origin);
if (invertY)
{
for (int y = height - 1; y >= 0; y--)
{
this.ReadBgr24Row(width, pixels, row, y);
}
}
else
{
for (int y = 0; y < height; y++)
{
this.ReadBgr24Row(width, pixels, row, y);
}
}
}
}
@ -423,22 +528,52 @@ namespace SixLabors.ImageSharp.Formats.Tga
/// <param name="width">The width of the image.</param>
/// <param name="height">The height of the image.</param>
/// <param name="pixels">The <see cref="Buffer2D{TPixel}"/> to assign the palette to.</param>
/// <param name="inverted">Indicates, if the origin of the image is top left rather the bottom left (the default).</param>
private void ReadBgra32<TPixel>(int width, int height, Buffer2D<TPixel> pixels, bool inverted)
/// <param name="origin">The image origin.</param>
private void ReadBgra32<TPixel>(int width, int height, Buffer2D<TPixel> pixels, TgaImageOrigin origin)
where TPixel : unmanaged, IPixel<TPixel>
{
using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 4, 0))
TPixel color = default;
bool invertX = InvertX(origin);
if (this.tgaMetadata.AlphaChannelBits == 8 && !invertX)
{
for (int y = 0; y < height; y++)
using (IManagedByteBuffer row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 4, 0))
{
this.currentStream.Read(row);
int newY = Invert(y, height, inverted);
Span<TPixel> pixelSpan = pixels.GetRowSpan(newY);
PixelOperations<TPixel>.Instance.FromBgra32Bytes(
this.configuration,
row.GetSpan(),
pixelSpan,
width);
if (InvertY(origin))
{
for (int y = height - 1; y >= 0; y--)
{
this.ReadBgra32Row(width, pixels, row, y);
}
}
else
{
for (int y = 0; y < height; y++)
{
this.ReadBgra32Row(width, pixels, row, y);
}
}
}
return;
}
for (int y = 0; y < height; y++)
{
int newY = InvertY(y, height, origin);
Span<TPixel> pixelRow = pixels.GetRowSpan(newY);
if (invertX)
{
for (int x = width - 1; x >= 0; x--)
{
this.ReadBgra32Pixel(x, color, pixelRow);
}
}
else
{
for (int x = 0; x < width; x++)
{
this.ReadBgra32Pixel(x, color, pixelRow);
}
}
}
}
@ -451,18 +586,19 @@ namespace SixLabors.ImageSharp.Formats.Tga
/// <param name="height">The height of the image.</param>
/// <param name="pixels">The <see cref="Buffer2D{TPixel}"/> to assign the palette to.</param>
/// <param name="bytesPerPixel">The bytes per pixel.</param>
/// <param name="inverted">Indicates, if the origin of the image is top left rather the bottom left (the default).</param>
private void ReadRle<TPixel>(int width, int height, Buffer2D<TPixel> pixels, int bytesPerPixel, bool inverted)
/// <param name="origin">The image origin.</param>
private void ReadRle<TPixel>(int width, int height, Buffer2D<TPixel> pixels, int bytesPerPixel, TgaImageOrigin origin)
where TPixel : unmanaged, IPixel<TPixel>
{
TPixel color = default;
var alphaBits = this.tgaMetadata.AlphaChannelBits;
using (IMemoryOwner<byte> buffer = this.memoryAllocator.Allocate<byte>(width * height * bytesPerPixel, AllocationOptions.Clean))
{
Span<byte> bufferSpan = buffer.GetSpan();
this.UncompressRle(width, height, bufferSpan, bytesPerPixel);
for (int y = 0; y < height; y++)
{
int newY = Invert(y, height, inverted);
int newY = InvertY(y, height, origin);
Span<TPixel> pixelRow = pixels.GetRowSpan(newY);
int rowStartIdx = y * width * bytesPerPixel;
for (int x = 0; x < width; x++)
@ -474,19 +610,41 @@ namespace SixLabors.ImageSharp.Formats.Tga
color.FromL8(Unsafe.As<byte, L8>(ref bufferSpan[idx]));
break;
case 2:
// Set alpha value to 1, to treat it as opaque for Bgra5551.
bufferSpan[idx + 1] = (byte)(bufferSpan[idx + 1] | 128);
color.FromBgra5551(Unsafe.As<byte, Bgra5551>(ref bufferSpan[idx]));
if (!this.hasAlpha)
{
// Set alpha value to 1, to treat it as opaque for Bgra5551.
bufferSpan[idx + 1] = (byte)(bufferSpan[idx + 1] | 128);
}
if (this.fileHeader.ImageType == TgaImageType.RleBlackAndWhite)
{
color.FromLa16(Unsafe.As<byte, La16>(ref bufferSpan[idx]));
}
else
{
color.FromBgra5551(Unsafe.As<byte, Bgra5551>(ref bufferSpan[idx]));
}
break;
case 3:
color.FromBgr24(Unsafe.As<byte, Bgr24>(ref bufferSpan[idx]));
break;
case 4:
color.FromBgra32(Unsafe.As<byte, Bgra32>(ref bufferSpan[idx]));
if (this.hasAlpha)
{
color.FromBgra32(Unsafe.As<byte, Bgra32>(ref bufferSpan[idx]));
}
else
{
var alpha = alphaBits == 0 ? byte.MaxValue : bufferSpan[idx + 3];
color.FromBgra32(new Bgra32(bufferSpan[idx + 2], bufferSpan[idx + 1], bufferSpan[idx], (byte)alpha));
}
break;
}
pixelRow[x] = color;
int newX = InvertX(x, width, origin);
pixelRow[newX] = color;
}
}
}
@ -506,6 +664,104 @@ namespace SixLabors.ImageSharp.Formats.Tga
this.metadata);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ReadL8Row<TPixel>(int width, Buffer2D<TPixel> pixels, IManagedByteBuffer row, int y)
where TPixel : unmanaged, IPixel<TPixel>
{
this.currentStream.Read(row);
Span<TPixel> pixelSpan = pixels.GetRowSpan(y);
PixelOperations<TPixel>.Instance.FromL8Bytes(this.configuration, row.GetSpan(), pixelSpan, width);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ReadL8Pixel<TPixel>(TPixel color, int x, Span<TPixel> pixelSpan)
where TPixel : unmanaged, IPixel<TPixel>
{
var pixelValue = (byte)this.currentStream.ReadByte();
color.FromL8(Unsafe.As<byte, L8>(ref pixelValue));
pixelSpan[x] = color;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ReadBgr24Pixel<TPixel>(TPixel color, int x, Span<TPixel> pixelSpan)
where TPixel : unmanaged, IPixel<TPixel>
{
this.currentStream.Read(this.scratchBuffer, 0, 3);
color.FromBgr24(Unsafe.As<byte, Bgr24>(ref this.scratchBuffer[0]));
pixelSpan[x] = color;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ReadBgr24Row<TPixel>(int width, Buffer2D<TPixel> pixels, IManagedByteBuffer row, int y)
where TPixel : unmanaged, IPixel<TPixel>
{
this.currentStream.Read(row);
Span<TPixel> pixelSpan = pixels.GetRowSpan(y);
PixelOperations<TPixel>.Instance.FromBgr24Bytes(this.configuration, row.GetSpan(), pixelSpan, width);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ReadBgra32Pixel<TPixel>(int x, TPixel color, Span<TPixel> pixelRow)
where TPixel : unmanaged, IPixel<TPixel>
{
this.currentStream.Read(this.scratchBuffer, 0, 4);
var alpha = this.tgaMetadata.AlphaChannelBits == 0 ? byte.MaxValue : this.scratchBuffer[3];
color.FromBgra32(new Bgra32(this.scratchBuffer[2], this.scratchBuffer[1], this.scratchBuffer[0], alpha));
pixelRow[x] = color;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ReadBgra32Row<TPixel>(int width, Buffer2D<TPixel> pixels, IManagedByteBuffer row, int y)
where TPixel : unmanaged, IPixel<TPixel>
{
this.currentStream.Read(row);
Span<TPixel> pixelSpan = pixels.GetRowSpan(y);
PixelOperations<TPixel>.Instance.FromBgra32Bytes(this.configuration, row.GetSpan(), pixelSpan, width);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ReadPalettedBgra16Pixel<TPixel>(byte[] palette, int colorMapPixelSizeInBytes, int x, TPixel color, Span<TPixel> pixelRow)
where TPixel : unmanaged, IPixel<TPixel>
{
int colorIndex = this.currentStream.ReadByte();
this.ReadPalettedBgra16Pixel(palette, colorIndex, colorMapPixelSizeInBytes, ref color);
pixelRow[x] = color;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ReadPalettedBgra16Pixel<TPixel>(byte[] palette, int index, int colorMapPixelSizeInBytes, ref TPixel color)
where TPixel : unmanaged, IPixel<TPixel>
{
Bgra5551 bgra = default;
bgra.FromBgra5551(Unsafe.As<byte, Bgra5551>(ref palette[index * colorMapPixelSizeInBytes]));
if (!this.hasAlpha)
{
// Set alpha value to 1, to treat it as opaque.
bgra.PackedValue = (ushort)(bgra.PackedValue | 0x8000);
}
color.FromBgra5551(bgra);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ReadPalettedBgr24Pixel<TPixel>(byte[] palette, int colorMapPixelSizeInBytes, int x, TPixel color, Span<TPixel> pixelRow)
where TPixel : unmanaged, IPixel<TPixel>
{
int colorIndex = this.currentStream.ReadByte();
color.FromBgr24(Unsafe.As<byte, Bgr24>(ref palette[colorIndex * colorMapPixelSizeInBytes]));
pixelRow[x] = color;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ReadPalettedBgra32Pixel<TPixel>(byte[] palette, int colorMapPixelSizeInBytes, int x, TPixel color, Span<TPixel> pixelRow)
where TPixel : unmanaged, IPixel<TPixel>
{
int colorIndex = this.currentStream.ReadByte();
color.FromBgra32(Unsafe.As<byte, Bgra32>(ref palette[colorIndex * colorMapPixelSizeInBytes]));
pixelRow[x] = color;
}
/// <summary>
/// Produce uncompressed tga data from a run length encoded stream.
/// </summary>
@ -554,18 +810,80 @@ namespace SixLabors.ImageSharp.Formats.Tga
/// Returns the y- value based on the given height.
/// </summary>
/// <param name="y">The y- value representing the current row.</param>
/// <param name="height">The height of the bitmap.</param>
/// <param name="inverted">Whether the bitmap is inverted.</param>
/// <param name="height">The height of the image.</param>
/// <param name="origin">The image origin.</param>
/// <returns>The <see cref="int"/> representing the inverted value.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int Invert(int y, int height, bool inverted) => (!inverted) ? height - y - 1 : y;
private static int InvertY(int y, int height, TgaImageOrigin origin)
{
if (InvertY(origin))
{
return height - y - 1;
}
return y;
}
/// <summary>
/// Indicates whether the y coordinates needs to be inverted, to keep a top left origin.
/// </summary>
/// <param name="origin">The image origin.</param>
/// <returns>True, if y coordinate needs to be inverted.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool InvertY(TgaImageOrigin origin)
{
switch (origin)
{
case TgaImageOrigin.BottomLeft:
case TgaImageOrigin.BottomRight:
return true;
default:
return false;
}
}
/// <summary>
/// Returns the x- value based on the given width.
/// </summary>
/// <param name="x">The x- value representing the current column.</param>
/// <param name="width">The width of the image.</param>
/// <param name="origin">The image origin.</param>
/// <returns>The <see cref="int"/> representing the inverted value.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int InvertX(int x, int width, TgaImageOrigin origin)
{
if (InvertX(origin))
{
return width - x - 1;
}
return x;
}
/// <summary>
/// Indicates whether the x coordinates needs to be inverted, to keep a top left origin.
/// </summary>
/// <param name="origin">The image origin.</param>
/// <returns>True, if x coordinate needs to be inverted.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool InvertX(TgaImageOrigin origin)
{
switch (origin)
{
case TgaImageOrigin.TopRight:
case TgaImageOrigin.BottomRight:
return true;
default:
return false;
}
}
/// <summary>
/// Reads the tga file header from the stream.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> containing image data.</param>
/// <returns>true, if the image origin is top left.</returns>
private bool ReadFileHeader(Stream stream)
/// <returns>The image origin.</returns>
private TgaImageOrigin ReadFileHeader(Stream stream)
{
this.currentStream = stream;
@ -577,13 +895,18 @@ namespace SixLabors.ImageSharp.Formats.Tga
this.tgaMetadata = this.metadata.GetTgaMetadata();
this.tgaMetadata.BitsPerPixel = (TgaBitsPerPixel)this.fileHeader.PixelDepth;
// Bit at position 5 of the descriptor indicates, that the origin is top left instead of bottom right.
if ((this.fileHeader.ImageDescriptor & (1 << 5)) != 0)
var alphaBits = this.fileHeader.ImageDescriptor & 0xf;
if (alphaBits != 0 && alphaBits != 1 && alphaBits != 8)
{
return true;
TgaThrowHelper.ThrowImageFormatException("Invalid alpha channel bits");
}
return false;
this.tgaMetadata.AlphaChannelBits = (byte)alphaBits;
this.hasAlpha = alphaBits > 0;
// Bits 4 and 5 describe the image origin.
var origin = (TgaImageOrigin)((this.fileHeader.ImageDescriptor & 0x30) >> 4);
return origin;
}
}
}

20
src/ImageSharp/Formats/Tga/TgaEncoderCore.cs

@ -78,8 +78,24 @@ namespace SixLabors.ImageSharp.Formats.Tga
imageType = this.compression is TgaCompression.RunLength ? TgaImageType.RleBlackAndWhite : TgaImageType.BlackAndWhite;
}
// If compression is used, set bit 5 of the image descriptor to indicate an left top origin.
byte imageDescriptor = (byte)(this.compression is TgaCompression.RunLength ? 32 : 0);
byte imageDescriptor = 0;
if (this.compression is TgaCompression.RunLength)
{
// If compression is used, set bit 5 of the image descriptor to indicate a left top origin.
imageDescriptor |= 0x20;
}
if (this.bitsPerPixel is TgaBitsPerPixel.Pixel32)
{
// Indicate, that 8 bit are used for the alpha channel.
imageDescriptor |= 0x8;
}
if (this.bitsPerPixel is TgaBitsPerPixel.Pixel16)
{
// Indicate, that 1 bit is used for the alpha channel.
imageDescriptor |= 0x1;
}
var fileHeader = new TgaFileHeader(
idLength: 0,

28
src/ImageSharp/Formats/Tga/TgaImageOrigin.cs

@ -0,0 +1,28 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Formats.Tga
{
internal enum TgaImageOrigin
{
/// <summary>
/// Bottom left origin.
/// </summary>
BottomLeft = 0,
/// <summary>
/// Bottom right origin.
/// </summary>
BottomRight = 1,
/// <summary>
/// Top left origin.
/// </summary>
TopLeft = 2,
/// <summary>
/// Top right origin.
/// </summary>
TopRight = 3,
}
}

5
src/ImageSharp/Formats/Tga/TgaMetadata.cs

@ -29,6 +29,11 @@ namespace SixLabors.ImageSharp.Formats.Tga
/// </summary>
public TgaBitsPerPixel BitsPerPixel { get; set; } = TgaBitsPerPixel.Pixel24;
/// <summary>
/// Gets or sets the the number of alpha bits per pixel.
/// </summary>
public byte AlphaChannelBits { get; set; } = 0;
/// <inheritdoc/>
public IDeepCloneable DeepClone() => new TgaMetadata(this);
}

6
src/ImageSharp/GeometryUtilities.cs

@ -1,10 +1,10 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
namespace SixLabors
namespace SixLabors.ImageSharp
{
/// <summary>
/// Utility class for common geometric functions.
@ -31,4 +31,4 @@ namespace SixLabors
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float RadianToDegree(float radian) => radian / (MathF.PI / 180F);
}
}
}

125
src/ImageSharp/Image.FromBytes.cs

@ -26,14 +26,55 @@ namespace SixLabors.ImageSharp
/// <summary>
/// By reading the header on the provided byte array this calculates the images format.
/// </summary>
/// <param name="config">The configuration.</param>
/// <param name="configuration">The configuration.</param>
/// <param name="data">The byte array containing encoded image data to read the header from.</param>
/// <returns>The mime type or null if none found.</returns>
public static IImageFormat DetectFormat(Configuration config, byte[] data)
public static IImageFormat DetectFormat(Configuration configuration, byte[] data)
{
using (var stream = new MemoryStream(data))
Guard.NotNull(configuration, nameof(configuration));
using (var stream = new MemoryStream(data, 0, data.Length, false, true))
{
return DetectFormat(configuration, stream);
}
}
/// <summary>
/// Reads the raw image information from the specified stream without fully decoding it.
/// </summary>
/// <param name="data">The byte array containing encoded image data to read the header from.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector not found.
/// </returns>
public static IImageInfo Identify(byte[] data) => Identify(data, out IImageFormat _);
/// <summary>
/// Reads the raw image information from the specified stream without fully decoding it.
/// </summary>
/// <param name="data">The byte array containing encoded image data to read the header from.</param>
/// <param name="format">The format type of the decoded image.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector not found.
/// </returns>
public static IImageInfo Identify(byte[] data, out IImageFormat format) => Identify(Configuration.Default, data, out format);
/// <summary>
/// Reads the raw image information from the specified stream without fully decoding it.
/// </summary>
/// <param name="configuration">The configuration.</param>
/// <param name="data">The byte array containing encoded image data to read the header from.</param>
/// <param name="format">The format type of the decoded image.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector is not found.
/// </returns>
public static IImageInfo Identify(Configuration configuration, byte[] data, out IImageFormat format)
{
Guard.NotNull(configuration, nameof(configuration));
using (var stream = new MemoryStream(data, 0, data.Length, false, true))
{
return DetectFormat(config, stream);
return Identify(configuration, stream, out format);
}
}
@ -68,33 +109,33 @@ namespace SixLabors.ImageSharp
/// <summary>
/// Load a new instance of <see cref="Image{TPixel}"/> from the given encoded byte array.
/// </summary>
/// <param name="config">The configuration options.</param>
/// <param name="configuration">The configuration options.</param>
/// <param name="data">The byte array containing encoded image data.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(Configuration config, byte[] data)
public static Image<TPixel> Load<TPixel>(Configuration configuration, byte[] data)
where TPixel : unmanaged, IPixel<TPixel>
{
using (var stream = new MemoryStream(data, 0, data.Length, false, true))
{
return Load<TPixel>(config, stream);
return Load<TPixel>(configuration, stream);
}
}
/// <summary>
/// Load a new instance of <see cref="Image{TPixel}"/> from the given encoded byte array.
/// </summary>
/// <param name="config">The configuration options.</param>
/// <param name="configuration">The configuration options.</param>
/// <param name="data">The byte array containing encoded image data.</param>
/// <param name="format">The <see cref="IImageFormat"/> of the decoded image.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(Configuration config, byte[] data, out IImageFormat format)
public static Image<TPixel> Load<TPixel>(Configuration configuration, byte[] data, out IImageFormat format)
where TPixel : unmanaged, IPixel<TPixel>
{
using (var stream = new MemoryStream(data, 0, data.Length, false, true))
{
return Load<TPixel>(config, stream, out format);
return Load<TPixel>(configuration, stream, out format);
}
}
@ -117,17 +158,17 @@ namespace SixLabors.ImageSharp
/// <summary>
/// Load a new instance of <see cref="Image{TPixel}"/> from the given encoded byte array.
/// </summary>
/// <param name="config">The Configuration.</param>
/// <param name="configuration">The Configuration.</param>
/// <param name="data">The byte array containing encoded image data.</param>
/// <param name="decoder">The decoder.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(Configuration config, byte[] data, IImageDecoder decoder)
public static Image<TPixel> Load<TPixel>(Configuration configuration, byte[] data, IImageDecoder decoder)
where TPixel : unmanaged, IPixel<TPixel>
{
using (var stream = new MemoryStream(data, 0, data.Length, false, true))
{
return Load<TPixel>(config, stream, decoder);
return Load<TPixel>(configuration, stream, decoder);
}
}
@ -144,18 +185,18 @@ namespace SixLabors.ImageSharp
/// <summary>
/// By reading the header on the provided byte array this calculates the images format.
/// </summary>
/// <param name="config">The configuration.</param>
/// <param name="configuration">The configuration.</param>
/// <param name="data">The byte array containing encoded image data to read the header from.</param>
/// <returns>The mime type or null if none found.</returns>
public static IImageFormat DetectFormat(Configuration config, ReadOnlySpan<byte> data)
public static IImageFormat DetectFormat(Configuration configuration, ReadOnlySpan<byte> data)
{
int maxHeaderSize = config.MaxHeaderSize;
int maxHeaderSize = configuration.MaxHeaderSize;
if (maxHeaderSize <= 0)
{
return null;
}
foreach (IImageFormatDetector detector in config.ImageFormatsManager.FormatDetectors)
foreach (IImageFormatDetector detector in configuration.ImageFormatsManager.FormatDetectors)
{
IImageFormat f = detector.DetectFormat(data);
@ -203,18 +244,18 @@ namespace SixLabors.ImageSharp
/// <summary>
/// Load a new instance of <see cref="Image{TPixel}"/> from the given encoded byte span.
/// </summary>
/// <param name="config">The configuration options.</param>
/// <param name="configuration">The configuration options.</param>
/// <param name="data">The byte span containing encoded image data.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static unsafe Image<TPixel> Load<TPixel>(Configuration config, ReadOnlySpan<byte> data)
public static unsafe Image<TPixel> Load<TPixel>(Configuration configuration, ReadOnlySpan<byte> data)
where TPixel : unmanaged, IPixel<TPixel>
{
fixed (byte* ptr = &data.GetPinnableReference())
{
using (var stream = new UnmanagedMemoryStream(ptr, data.Length))
{
return Load<TPixel>(config, stream);
return Load<TPixel>(configuration, stream);
}
}
}
@ -222,13 +263,13 @@ namespace SixLabors.ImageSharp
/// <summary>
/// Load a new instance of <see cref="Image{TPixel}"/> from the given encoded byte span.
/// </summary>
/// <param name="config">The Configuration.</param>
/// <param name="configuration">The Configuration.</param>
/// <param name="data">The byte span containing image data.</param>
/// <param name="decoder">The decoder.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static unsafe Image<TPixel> Load<TPixel>(
Configuration config,
Configuration configuration,
ReadOnlySpan<byte> data,
IImageDecoder decoder)
where TPixel : unmanaged, IPixel<TPixel>
@ -237,7 +278,7 @@ namespace SixLabors.ImageSharp
{
using (var stream = new UnmanagedMemoryStream(ptr, data.Length))
{
return Load<TPixel>(config, stream, decoder);
return Load<TPixel>(configuration, stream, decoder);
}
}
}
@ -245,13 +286,13 @@ namespace SixLabors.ImageSharp
/// <summary>
/// Load a new instance of <see cref="Image{TPixel}"/> from the given encoded byte span.
/// </summary>
/// <param name="config">The configuration options.</param>
/// <param name="configuration">The configuration options.</param>
/// <param name="data">The byte span containing image data.</param>
/// <param name="format">The <see cref="IImageFormat"/> of the decoded image.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static unsafe Image<TPixel> Load<TPixel>(
Configuration config,
Configuration configuration,
ReadOnlySpan<byte> data,
out IImageFormat format)
where TPixel : unmanaged, IPixel<TPixel>
@ -260,7 +301,7 @@ namespace SixLabors.ImageSharp
{
using (var stream = new UnmanagedMemoryStream(ptr, data.Length))
{
return Load<TPixel>(config, stream, out format);
return Load<TPixel>(configuration, stream, out format);
}
}
}
@ -285,38 +326,38 @@ namespace SixLabors.ImageSharp
/// <summary>
/// Load a new instance of <see cref="Image"/> from the given encoded byte array.
/// </summary>
/// <param name="config">The config for the decoder.</param>
/// <param name="configuration">The configuration for the decoder.</param>
/// <param name="data">The byte array containing encoded image data.</param>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(Configuration config, byte[] data) => Load(config, data, out _);
public static Image Load(Configuration configuration, byte[] data) => Load(configuration, data, out _);
/// <summary>
/// Load a new instance of <see cref="Image"/> from the given encoded byte array.
/// </summary>
/// <param name="config">The config for the decoder.</param>
/// <param name="configuration">The configuration for the decoder.</param>
/// <param name="data">The byte array containing image data.</param>
/// <param name="decoder">The decoder.</param>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(Configuration config, byte[] data, IImageDecoder decoder)
public static Image Load(Configuration configuration, byte[] data, IImageDecoder decoder)
{
using (var stream = new MemoryStream(data, 0, data.Length, false, true))
{
return Load(config, stream, decoder);
return Load(configuration, stream, decoder);
}
}
/// <summary>
/// Load a new instance of <see cref="Image"/> from the given encoded byte array.
/// </summary>
/// <param name="config">The config for the decoder.</param>
/// <param name="configuration">The configuration for the decoder.</param>
/// <param name="data">The byte array containing image data.</param>
/// <param name="format">The mime type of the decoded image.</param>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(Configuration config, byte[] data, out IImageFormat format)
public static Image Load(Configuration configuration, byte[] data, out IImageFormat format)
{
using (var stream = new MemoryStream(data, 0, data.Length, false, true))
{
return Load(config, stream, out format);
return Load(configuration, stream, out format);
}
}
@ -348,20 +389,20 @@ namespace SixLabors.ImageSharp
/// <summary>
/// Decodes a new instance of <see cref="Image"/> from the given encoded byte span.
/// </summary>
/// <param name="config">The configuration options.</param>
/// <param name="configuration">The configuration options.</param>
/// <param name="data">The byte span containing image data.</param>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(Configuration config, ReadOnlySpan<byte> data) => Load(config, data, out _);
public static Image Load(Configuration configuration, ReadOnlySpan<byte> data) => Load(configuration, data, out _);
/// <summary>
/// Load a new instance of <see cref="Image"/> from the given encoded byte span.
/// </summary>
/// <param name="config">The Configuration.</param>
/// <param name="configuration">The Configuration.</param>
/// <param name="data">The byte span containing image data.</param>
/// <param name="decoder">The decoder.</param>
/// <returns>The <see cref="Image"/>.</returns>
public static unsafe Image Load(
Configuration config,
Configuration configuration,
ReadOnlySpan<byte> data,
IImageDecoder decoder)
{
@ -369,7 +410,7 @@ namespace SixLabors.ImageSharp
{
using (var stream = new UnmanagedMemoryStream(ptr, data.Length))
{
return Load(config, stream, decoder);
return Load(configuration, stream, decoder);
}
}
}
@ -377,12 +418,12 @@ namespace SixLabors.ImageSharp
/// <summary>
/// Load a new instance of <see cref="Image"/> from the given encoded byte span.
/// </summary>
/// <param name="config">The configuration options.</param>
/// <param name="configuration">The configuration options.</param>
/// <param name="data">The byte span containing image data.</param>
/// <param name="format">The <see cref="IImageFormat"/> of the decoded image.</param>>
/// <returns>The <see cref="Image"/>.</returns>
public static unsafe Image Load(
Configuration config,
Configuration configuration,
ReadOnlySpan<byte> data,
out IImageFormat format)
{
@ -390,7 +431,7 @@ namespace SixLabors.ImageSharp
{
using (var stream = new UnmanagedMemoryStream(ptr, data.Length))
{
return Load(config, stream, out format);
return Load(configuration, stream, out format);
}
}
}

99
src/ImageSharp/Image.FromFile.cs

@ -26,15 +26,55 @@ namespace SixLabors.ImageSharp
/// <summary>
/// By reading the header on the provided file this calculates the images mime type.
/// </summary>
/// <param name="config">The configuration.</param>
/// <param name="configuration">The configuration.</param>
/// <param name="filePath">The image file to open and to read the header from.</param>
/// <returns>The mime type or null if none found.</returns>
public static IImageFormat DetectFormat(Configuration config, string filePath)
public static IImageFormat DetectFormat(Configuration configuration, string filePath)
{
config = config ?? Configuration.Default;
using (Stream file = config.FileSystem.OpenRead(filePath))
Guard.NotNull(configuration, nameof(configuration));
using (Stream file = configuration.FileSystem.OpenRead(filePath))
{
return DetectFormat(config, file);
return DetectFormat(configuration, file);
}
}
/// <summary>
/// Reads the raw image information from the specified stream without fully decoding it.
/// </summary>
/// <param name="filePath">The image file to open and to read the header from.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector not found.
/// </returns>
public static IImageInfo Identify(string filePath) => Identify(filePath, out IImageFormat _);
/// <summary>
/// Reads the raw image information from the specified stream without fully decoding it.
/// </summary>
/// <param name="filePath">The image file to open and to read the header from.</param>
/// <param name="format">The format type of the decoded image.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector not found.
/// </returns>
public static IImageInfo Identify(string filePath, out IImageFormat format) => Identify(Configuration.Default, filePath, out format);
/// <summary>
/// Reads the raw image information from the specified stream without fully decoding it.
/// </summary>
/// <param name="configuration">The configuration.</param>
/// <param name="filePath">The image file to open and to read the header from.</param>
/// <param name="format">The format type of the decoded image.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector is not found.
/// </returns>
public static IImageInfo Identify(Configuration configuration, string filePath, out IImageFormat format)
{
Guard.NotNull(configuration, nameof(configuration));
using (Stream file = configuration.FileSystem.OpenRead(filePath))
{
return Identify(configuration, file, out format);
}
}
@ -62,29 +102,30 @@ namespace SixLabors.ImageSharp
/// <summary>
/// Create a new instance of the <see cref="Image"/> class from the given file.
/// </summary>
/// <param name="config">The config for the decoder.</param>
/// <param name="configuration">The configuration for the decoder.</param>
/// <param name="path">The file path to the image.</param>
/// <exception cref="NotSupportedException">
/// Thrown if the stream is not readable nor seekable.
/// </exception>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(Configuration config, string path) => Load(config, path, out _);
public static Image Load(Configuration configuration, string path) => Load(configuration, path, out _);
/// <summary>
/// Create a new instance of the <see cref="Image"/> class from the given file.
/// </summary>
/// <param name="config">The Configuration.</param>
/// <param name="configuration">The Configuration.</param>
/// <param name="path">The file path to the image.</param>
/// <param name="decoder">The decoder.</param>
/// <exception cref="NotSupportedException">
/// Thrown if the stream is not readable nor seekable.
/// </exception>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(Configuration config, string path, IImageDecoder decoder)
public static Image Load(Configuration configuration, string path, IImageDecoder decoder)
{
using (Stream stream = config.FileSystem.OpenRead(path))
Guard.NotNull(configuration, nameof(configuration));
using (Stream stream = configuration.FileSystem.OpenRead(path))
{
return Load(config, stream, decoder);
return Load(configuration, stream, decoder);
}
}
@ -133,26 +174,27 @@ namespace SixLabors.ImageSharp
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given file.
/// </summary>
/// <param name="config">The configuration options.</param>
/// <param name="configuration">The configuration options.</param>
/// <param name="path">The file path to the image.</param>
/// <exception cref="NotSupportedException">
/// Thrown if the stream is not readable nor seekable.
/// </exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(Configuration config, string path)
public static Image<TPixel> Load<TPixel>(Configuration configuration, string path)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Stream stream = config.FileSystem.OpenRead(path))
Guard.NotNull(configuration, nameof(configuration));
using (Stream stream = configuration.FileSystem.OpenRead(path))
{
return Load<TPixel>(config, stream);
return Load<TPixel>(configuration, stream);
}
}
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given file.
/// </summary>
/// <param name="config">The configuration options.</param>
/// <param name="configuration">The configuration options.</param>
/// <param name="path">The file path to the image.</param>
/// <param name="format">The mime type of the decoded image.</param>
/// <exception cref="NotSupportedException">
@ -160,12 +202,13 @@ namespace SixLabors.ImageSharp
/// </exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(Configuration config, string path, out IImageFormat format)
public static Image<TPixel> Load<TPixel>(Configuration configuration, string path, out IImageFormat format)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Stream stream = config.FileSystem.OpenRead(path))
Guard.NotNull(configuration, nameof(configuration));
using (Stream stream = configuration.FileSystem.OpenRead(path))
{
return Load<TPixel>(config, stream, out format);
return Load<TPixel>(configuration, stream, out format);
}
}
@ -173,18 +216,19 @@ namespace SixLabors.ImageSharp
/// Create a new instance of the <see cref="Image"/> class from the given file.
/// The pixel type is selected by the decoder.
/// </summary>
/// <param name="config">The configuration options.</param>
/// <param name="configuration">The configuration options.</param>
/// <param name="path">The file path to the image.</param>
/// <param name="format">The mime type of the decoded image.</param>
/// <exception cref="NotSupportedException">
/// Thrown if the stream is not readable nor seekable.
/// </exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image Load(Configuration config, string path, out IImageFormat format)
public static Image Load(Configuration configuration, string path, out IImageFormat format)
{
using (Stream stream = config.FileSystem.OpenRead(path))
Guard.NotNull(configuration, nameof(configuration));
using (Stream stream = configuration.FileSystem.OpenRead(path))
{
return Load(config, stream, out format);
return Load(configuration, stream, out format);
}
}
@ -207,7 +251,7 @@ namespace SixLabors.ImageSharp
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given file.
/// </summary>
/// <param name="config">The Configuration.</param>
/// <param name="configuration">The Configuration.</param>
/// <param name="path">The file path to the image.</param>
/// <param name="decoder">The decoder.</param>
/// <exception cref="NotSupportedException">
@ -215,12 +259,13 @@ namespace SixLabors.ImageSharp
/// </exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(Configuration config, string path, IImageDecoder decoder)
public static Image<TPixel> Load<TPixel>(Configuration configuration, string path, IImageDecoder decoder)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Stream stream = config.FileSystem.OpenRead(path))
Guard.NotNull(configuration, nameof(configuration));
using (Stream stream = configuration.FileSystem.OpenRead(path))
{
return Load<TPixel>(config, stream, decoder);
return Load<TPixel>(configuration, stream, decoder);
}
}
}

68
src/ImageSharp/Image.FromStream.cs

@ -26,15 +26,15 @@ namespace SixLabors.ImageSharp
/// <summary>
/// By reading the header on the provided stream this calculates the images format type.
/// </summary>
/// <param name="config">The configuration.</param>
/// <param name="configuration">The configuration.</param>
/// <param name="stream">The image stream to read the header from.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <returns>The format type or null if none found.</returns>
public static IImageFormat DetectFormat(Configuration config, Stream stream)
=> WithSeekableStream(config, stream, s => InternalDetectFormat(s, config));
public static IImageFormat DetectFormat(Configuration configuration, Stream stream)
=> WithSeekableStream(configuration, stream, s => InternalDetectFormat(s, configuration));
/// <summary>
/// By reading the header on the provided stream this reads the raw image information.
/// Reads the raw image information from the specified stream without fully decoding it.
/// </summary>
/// <param name="stream">The image stream to read the header from.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp
public static IImageInfo Identify(Stream stream) => Identify(stream, out IImageFormat _);
/// <summary>
/// By reading the header on the provided stream this reads the raw image information.
/// Reads the raw image information from the specified stream without fully decoding it.
/// </summary>
/// <param name="stream">The image stream to read the header from.</param>
/// <param name="format">The format type of the decoded image.</param>
@ -57,16 +57,16 @@ namespace SixLabors.ImageSharp
/// <summary>
/// Reads the raw image information from the specified stream without fully decoding it.
/// </summary>
/// <param name="config">The configuration.</param>
/// <param name="configuration">The configuration.</param>
/// <param name="stream">The image stream to read the information from.</param>
/// <param name="format">The format type of the decoded image.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector is not found.
/// </returns>
public static IImageInfo Identify(Configuration config, Stream stream, out IImageFormat format)
public static IImageInfo Identify(Configuration configuration, Stream stream, out IImageFormat format)
{
(IImageInfo info, IImageFormat format) data = WithSeekableStream(config, stream, s => InternalIdentity(s, config ?? Configuration.Default));
(IImageInfo info, IImageFormat format) data = WithSeekableStream(configuration, stream, s => InternalIdentity(s, configuration ?? Configuration.Default));
format = data.format;
return data.info;
@ -108,24 +108,24 @@ namespace SixLabors.ImageSharp
/// Decode a new instance of the <see cref="Image"/> class from the given stream.
/// The pixel format is selected by the decoder.
/// </summary>
/// <param name="config">The config for the decoder.</param>
/// <param name="configuration">The configuration for the decoder.</param>
/// <param name="stream">The stream containing image information.</param>
/// <param name="decoder">The decoder.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image cannot be loaded.</exception>
/// <returns>A new <see cref="Image"/>.</returns>>
public static Image Load(Configuration config, Stream stream, IImageDecoder decoder) =>
WithSeekableStream(config, stream, s => decoder.Decode(config, s));
public static Image Load(Configuration configuration, Stream stream, IImageDecoder decoder) =>
WithSeekableStream(configuration, stream, s => decoder.Decode(configuration, s));
/// <summary>
/// Decode a new instance of the <see cref="Image"/> class from the given stream.
/// </summary>
/// <param name="config">The config for the decoder.</param>
/// <param name="configuration">The configuration for the decoder.</param>
/// <param name="stream">The stream containing image information.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image cannot be loaded.</exception>
/// <returns>A new <see cref="Image"/>.</returns>>
public static Image Load(Configuration config, Stream stream) => Load(config, stream, out _);
public static Image Load(Configuration configuration, Stream stream) => Load(configuration, stream, out _);
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
@ -137,7 +137,7 @@ namespace SixLabors.ImageSharp
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>>
public static Image<TPixel> Load<TPixel>(Stream stream)
where TPixel : unmanaged, IPixel<TPixel>
=> Load<TPixel>(null, stream);
=> Load<TPixel>(Configuration.Default, stream);
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
@ -150,7 +150,7 @@ namespace SixLabors.ImageSharp
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>>
public static Image<TPixel> Load<TPixel>(Stream stream, out IImageFormat format)
where TPixel : unmanaged, IPixel<TPixel>
=> Load<TPixel>(null, stream, out format);
=> Load<TPixel>(Configuration.Default, stream, out format);
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
@ -168,45 +168,45 @@ namespace SixLabors.ImageSharp
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
/// </summary>
/// <param name="config">The Configuration.</param>
/// <param name="configuration">The Configuration.</param>
/// <param name="stream">The stream containing image information.</param>
/// <param name="decoder">The decoder.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image cannot be loaded.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>>
public static Image<TPixel> Load<TPixel>(Configuration config, Stream stream, IImageDecoder decoder)
public static Image<TPixel> Load<TPixel>(Configuration configuration, Stream stream, IImageDecoder decoder)
where TPixel : unmanaged, IPixel<TPixel>
=> WithSeekableStream(config, stream, s => decoder.Decode<TPixel>(config, s));
=> WithSeekableStream(configuration, stream, s => decoder.Decode<TPixel>(configuration, s));
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
/// </summary>
/// <param name="config">The configuration options.</param>
/// <param name="configuration">The configuration options.</param>
/// <param name="stream">The stream containing image information.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image cannot be loaded.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>>
public static Image<TPixel> Load<TPixel>(Configuration config, Stream stream)
public static Image<TPixel> Load<TPixel>(Configuration configuration, Stream stream)
where TPixel : unmanaged, IPixel<TPixel>
=> Load<TPixel>(config, stream, out IImageFormat _);
=> Load<TPixel>(configuration, stream, out IImageFormat _);
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
/// </summary>
/// <param name="config">The configuration options.</param>
/// <param name="configuration">The configuration options.</param>
/// <param name="stream">The stream containing image information.</param>
/// <param name="format">The format type of the decoded image.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image cannot be loaded.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>>
public static Image<TPixel> Load<TPixel>(Configuration config, Stream stream, out IImageFormat format)
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(Configuration configuration, Stream stream, out IImageFormat format)
where TPixel : unmanaged, IPixel<TPixel>
{
config = config ?? Configuration.Default;
(Image<TPixel> img, IImageFormat format) data = WithSeekableStream(config, stream, s => Decode<TPixel>(s, config));
Guard.NotNull(configuration, nameof(configuration));
(Image<TPixel> img, IImageFormat format) data = WithSeekableStream(configuration, stream, s => Decode<TPixel>(s, configuration));
format = data.format;
@ -218,7 +218,7 @@ namespace SixLabors.ImageSharp
var sb = new StringBuilder();
sb.AppendLine("Image cannot be loaded. Available decoders:");
foreach (KeyValuePair<IImageFormat, IImageDecoder> val in config.ImageFormatsManager.ImageDecoders)
foreach (KeyValuePair<IImageFormat, IImageDecoder> val in configuration.ImageFormatsManager.ImageDecoders)
{
sb.AppendLine($" - {val.Key.Name} : {val.Value.GetType().Name}");
}
@ -230,16 +230,16 @@ namespace SixLabors.ImageSharp
/// Decode a new instance of the <see cref="Image"/> class from the given stream.
/// The pixel format is selected by the decoder.
/// </summary>
/// <param name="config">The configuration options.</param>
/// <param name="configuration">The configuration options.</param>
/// <param name="stream">The stream containing image information.</param>
/// <param name="format">The format type of the decoded image.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image cannot be loaded.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image Load(Configuration config, Stream stream, out IImageFormat format)
public static Image Load(Configuration configuration, Stream stream, out IImageFormat format)
{
config = config ?? Configuration.Default;
(Image img, IImageFormat format) data = WithSeekableStream(config, stream, s => Decode(s, config));
Guard.NotNull(configuration, nameof(configuration));
(Image img, IImageFormat format) data = WithSeekableStream(configuration, stream, s => Decode(s, configuration));
format = data.format;
@ -251,7 +251,7 @@ namespace SixLabors.ImageSharp
var sb = new StringBuilder();
sb.AppendLine("Image cannot be loaded. Available decoders:");
foreach (KeyValuePair<IImageFormat, IImageDecoder> val in config.ImageFormatsManager.ImageDecoders)
foreach (KeyValuePair<IImageFormat, IImageDecoder> val in configuration.ImageFormatsManager.ImageDecoders)
{
sb.AppendLine($" - {val.Key.Name} : {val.Value.GetType().Name}");
}
@ -259,7 +259,7 @@ namespace SixLabors.ImageSharp
throw new UnknownImageFormatException(sb.ToString());
}
private static T WithSeekableStream<T>(Configuration config, Stream stream, Func<Stream, T> action)
private static T WithSeekableStream<T>(Configuration configuration, Stream stream, Func<Stream, T> action)
{
if (!stream.CanRead)
{
@ -268,7 +268,7 @@ namespace SixLabors.ImageSharp
if (stream.CanSeek)
{
if (config.ReadOrigin == ReadOrigin.Begin)
if (configuration.ReadOrigin == ReadOrigin.Begin)
{
stream.Position = 0;
}

12
src/ImageSharp/ImageExtensions.cs

@ -112,12 +112,12 @@ namespace SixLabors.ImageSharp
public static string ToBase64String<TPixel>(this Image<TPixel> source, IImageFormat format)
where TPixel : unmanaged, IPixel<TPixel>
{
using (var stream = new MemoryStream())
{
source.Save(stream, format);
stream.Flush();
return $"data:{format.DefaultMimeType};base64,{Convert.ToBase64String(stream.ToArray())}";
}
using var stream = new MemoryStream();
source.Save(stream, format);
// Always available.
stream.TryGetBuffer(out ArraySegment<byte> buffer);
return $"data:{format.DefaultMimeType};base64,{Convert.ToBase64String(buffer.Array, 0, (int)stream.Length)}";
}
}
}

28
src/ImageSharp/Processing/Processors/Quantization/IndexedImageFrame{TPixel}.cs → src/ImageSharp/IndexedImageFrame{TPixel}.cs

@ -4,19 +4,21 @@
using System;
using System.Buffers;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing.Processors.Quantization;
namespace SixLabors.ImageSharp.Processing.Processors.Quantization
namespace SixLabors.ImageSharp
{
/// <summary>
/// A pixel-specific image frame where each pixel buffer value represents an index in a color palette.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
public sealed class IndexedImageFrame<TPixel> : IDisposable
public sealed class IndexedImageFrame<TPixel> : IPixelSource, IDisposable
where TPixel : unmanaged, IPixel<TPixel>
{
private IMemoryOwner<byte> pixelsOwner;
private Buffer2D<byte> pixelBuffer;
private IMemoryOwner<TPixel> paletteOwner;
private bool isDisposed;
@ -39,7 +41,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
this.Configuration = configuration;
this.Width = width;
this.Height = height;
this.pixelsOwner = configuration.MemoryAllocator.AllocateManagedByteBuffer(width * height);
this.pixelBuffer = configuration.MemoryAllocator.Allocate2D<byte>(width, height);
// Copy the palette over. We want the lifetime of this frame to be independant of any palette source.
this.paletteOwner = configuration.MemoryAllocator.Allocate<TPixel>(palette.Length);
@ -67,16 +69,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// </summary>
public ReadOnlyMemory<TPixel> Palette { get; }
/// <summary>
/// Gets the pixels of this <see cref="IndexedImageFrame{TPixel}"/>.
/// </summary>
/// <returns>The <see cref="ReadOnlySpan{T}"/></returns>
[MethodImpl(InliningOptions.ShortMethod)]
public ReadOnlySpan<byte> GetPixelBufferSpan() => this.pixelsOwner.GetSpan(); // TODO: Buffer2D<byte>
/// <inheritdoc/>
Buffer2D<byte> IPixelSource.PixelBuffer => this.pixelBuffer;
/// <summary>
/// Gets the representation of the pixels as a <see cref="ReadOnlySpan{T}"/> of contiguous memory
/// at row <paramref name="rowIndex"/> beginning from the the first pixel on that row.
/// at row <paramref name="rowIndex"/> beginning from the first pixel on that row.
/// </summary>
/// <param name="rowIndex">The row index in the pixel buffer.</param>
/// <returns>The pixel row as a <see cref="ReadOnlySpan{T}"/>.</returns>
@ -87,7 +85,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// <summary>
/// <para>
/// Gets the representation of the pixels as a <see cref="Span{T}"/> of contiguous memory
/// at row <paramref name="rowIndex"/> beginning from the the first pixel on that row.
/// at row <paramref name="rowIndex"/> beginning from the first pixel on that row.
/// </para>
/// <para>
/// Note: Values written to this span are not sanitized against the palette length.
@ -98,7 +96,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// <returns>The pixel row as a <see cref="Span{T}"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public Span<byte> GetWritablePixelRowSpanUnsafe(int rowIndex)
=> this.pixelsOwner.GetSpan().Slice(rowIndex * this.Width, this.Width);
=> this.pixelBuffer.GetRowSpan(rowIndex);
/// <inheritdoc/>
public void Dispose()
@ -106,9 +104,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
if (!this.isDisposed)
{
this.isDisposed = true;
this.pixelsOwner.Dispose();
this.pixelBuffer.Dispose();
this.paletteOwner.Dispose();
this.pixelsOwner = null;
this.pixelBuffer = null;
this.paletteOwner = null;
}
}

2
src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs

@ -373,7 +373,7 @@ namespace SixLabors.ImageSharp.PixelFormats
{
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes);
this.R = (byte)vector.X;
this.G = (byte)vector.Y;

2
src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs

@ -296,7 +296,7 @@ namespace SixLabors.ImageSharp.PixelFormats
{
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes);
this.R = (byte)vector.X;
this.G = (byte)vector.Y;

2
src/ImageSharp/PixelFormats/PixelImplementations/Bgra4444.cs

@ -162,7 +162,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
private static ushort Pack(ref Vector4 vector)
{
vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One);
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One);
return (ushort)((((int)Math.Round(vector.W * 15F) & 0x0F) << 12)
| (((int)Math.Round(vector.X * 15F) & 0x0F) << 8)
| (((int)Math.Round(vector.Y * 15F) & 0x0F) << 4)

2
src/ImageSharp/PixelFormats/PixelImplementations/Bgra5551.cs

@ -163,7 +163,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
private static ushort Pack(ref Vector4 vector)
{
vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One);
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One);
return (ushort)(
(((int)Math.Round(vector.X * 31F) & 0x1F) << 10)
| (((int)Math.Round(vector.Y * 31F) & 0x1F) << 5)

2
src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs

@ -171,7 +171,7 @@ namespace SixLabors.ImageSharp.PixelFormats
const float Max = 255F;
// Clamp the value between min and max values
vector = Vector4.Clamp(vector, Vector4.Zero, new Vector4(Max));
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, new Vector4(Max));
uint byte4 = (uint)Math.Round(vector.X) & 0xFF;
uint byte3 = ((uint)Math.Round(vector.Y) & 0xFF) << 0x8;

2
src/ImageSharp/PixelFormats/PixelImplementations/L16.cs

@ -176,7 +176,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
internal void ConvertFromRgbaScaledVector4(Vector4 vector)
{
vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * Max;
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One) * Max;
this.PackedValue = ImageMaths.Get16BitBT709Luminance(
vector.X,
vector.Y,

2
src/ImageSharp/PixelFormats/PixelImplementations/L8.cs

@ -156,7 +156,7 @@ namespace SixLabors.ImageSharp.PixelFormats
{
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes);
this.PackedValue = ImageMaths.Get8BitBT709Luminance((byte)vector.X, (byte)vector.Y, (byte)vector.Z);
}
}

2
src/ImageSharp/PixelFormats/PixelImplementations/La16.cs

@ -219,7 +219,7 @@ namespace SixLabors.ImageSharp.PixelFormats
{
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes);
this.L = ImageMaths.Get8BitBT709Luminance((byte)vector.X, (byte)vector.Y, (byte)vector.Z);
this.A = (byte)vector.W;
}

2
src/ImageSharp/PixelFormats/PixelImplementations/La32.cs

@ -233,7 +233,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
internal void ConvertFromRgbaScaledVector4(Vector4 vector)
{
vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * Max;
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One) * Max;
this.L = ImageMaths.Get16BitBT709Luminance(
vector.X,
vector.Y,

2
src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs

@ -174,7 +174,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
private static uint Pack(ref Vector4 vector)
{
vector = Vector4.Clamp(vector, MinusOne, Vector4.One) * Half;
vector = Vector4Utilities.FastClamp(vector, MinusOne, Vector4.One) * Half;
uint byte4 = ((uint)MathF.Round(vector.X) & 0xFF) << 0;
uint byte3 = ((uint)MathF.Round(vector.Y) & 0xFF) << 8;

2
src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort4.cs

@ -177,7 +177,7 @@ namespace SixLabors.ImageSharp.PixelFormats
private static ulong Pack(ref Vector4 vector)
{
vector *= Max;
vector = Vector4.Clamp(vector, Min, Max);
vector = Vector4Utilities.FastClamp(vector, Min, Max);
// Round rather than truncate.
ulong word4 = ((ulong)MathF.Round(vector.X) & 0xFFFF) << 0x00;

2
src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs

@ -254,7 +254,7 @@ namespace SixLabors.ImageSharp.PixelFormats
{
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes);
this.R = (byte)vector.X;
this.G = (byte)vector.Y;

2
src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs

@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromVector4(Vector4 vector)
{
vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * Max;
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One) * Max;
this.R = (ushort)MathF.Round(vector.X);
this.G = (ushort)MathF.Round(vector.Y);
this.B = (ushort)MathF.Round(vector.Z);

2
src/ImageSharp/PixelFormats/PixelImplementations/Rgba1010102.cs

@ -163,7 +163,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
private static uint Pack(ref Vector4 vector)
{
vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * Multiplier;
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One) * Multiplier;
return (uint)(
(((int)Math.Round(vector.X) & 0x03FF) << 0)

4
src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs

@ -452,7 +452,7 @@ namespace SixLabors.ImageSharp.PixelFormats
{
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes);
return new Rgba32((byte)vector.X, (byte)vector.Y, (byte)vector.Z, (byte)vector.W);
}
@ -491,7 +491,7 @@ namespace SixLabors.ImageSharp.PixelFormats
{
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes);
this.R = (byte)vector.X;
this.G = (byte)vector.Y;

4
src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs

@ -127,7 +127,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba64(Vector4 vector)
{
vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * Max;
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One) * Max;
this.R = (ushort)MathF.Round(vector.X);
this.G = (ushort)MathF.Round(vector.Y);
this.B = (ushort)MathF.Round(vector.Z);
@ -209,7 +209,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromVector4(Vector4 vector)
{
vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * Max;
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One) * Max;
this.R = (ushort)MathF.Round(vector.X);
this.G = (ushort)MathF.Round(vector.Y);
this.B = (ushort)MathF.Round(vector.Z);

2
src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs

@ -111,7 +111,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromVector4(Vector4 vector)
{
vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One);
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One);
this.R = vector.X;
this.G = vector.Y;
this.B = vector.Z;

2
src/ImageSharp/PixelFormats/PixelImplementations/Short4.cs

@ -183,7 +183,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
private static ulong Pack(ref Vector4 vector)
{
vector = Vector4.Clamp(vector, Min, Max);
vector = Vector4Utilities.FastClamp(vector, Min, Max);
// Clamp the value between min and max values
ulong word4 = ((ulong)Math.Round(vector.X) & 0xFFFF) << 0x00;

4
src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs

@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils
if (modifiers.IsDefined(PixelConversionModifiers.Premultiply))
{
Vector4Utils.Premultiply(vectors);
Vector4Utilities.Premultiply(vectors);
}
}
@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils
{
if (modifiers.IsDefined(PixelConversionModifiers.Premultiply))
{
Vector4Utils.UnPremultiply(vectors);
Vector4Utilities.UnPremultiply(vectors);
}
if (modifiers.IsDefined(PixelConversionModifiers.SRgbCompand))

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save