Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
4e21188
Fix all known quantizing issues
JimBobSquarePants Feb 26, 2025
19ea815
Use explicit ReadOnlySpan to fix CI build with preview lang
JimBobSquarePants Feb 26, 2025
e733495
remove old unused type
JimBobSquarePants Feb 26, 2025
05c5525
Threshold on the way out also.
JimBobSquarePants Feb 27, 2025
c573228
Upstream fixes.
JimBobSquarePants Mar 17, 2025
4aae44f
Pass readonly region
JimBobSquarePants Mar 18, 2025
6322bcb
Use different cache types and begin to make quantizers own clearing p…
JimBobSquarePants Mar 26, 2025
86b9917
Upstream V3 changes.
JimBobSquarePants Mar 27, 2025
a84160b
Add new benchmarks
JimBobSquarePants Mar 27, 2025
dca98af
Update test ref images to match caching
JimBobSquarePants Mar 27, 2025
32da5cd
Fix build, simplify utilities
JimBobSquarePants Mar 27, 2025
2c6acea
Set langversion to 12
JimBobSquarePants Mar 27, 2025
16b4eb6
Simplify API and clone options.
JimBobSquarePants Mar 28, 2025
93f8bdf
ImageMagick.NET to GIF encoder benchmark
JimBobSquarePants Apr 2, 2025
b989843
Simplify GifEncoderCore, seal palette quantizers
JimBobSquarePants Apr 4, 2025
4f1f64b
Merge branch 'main' into js/fix-2866-v4
JimBobSquarePants Apr 7, 2025
87f6c04
Merge branch 'main' into js/fix-2866-v4
JimBobSquarePants Apr 28, 2025
b09ea41
Fix build
JimBobSquarePants Apr 28, 2025
a99e6cf
Revert to original CoarseCache
JimBobSquarePants Apr 29, 2025
583d89e
Update ref images, tweak lite cache to match original (unused)
JimBobSquarePants Apr 30, 2025
5f971c7
Merge branch 'main' into js/fix-2866-v4
JimBobSquarePants May 14, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@
<!-- Import the shared global .props file -->
<Import Project="$(MSBuildThisFileDirectory)shared-infrastructure\msbuild\props\SixLabors.Global.props" />

<PropertyGroup Condition="$(SIXLABORS_TESTING_PREVIEW) == true">
<!-- Workaround various issues bound to implicit language features. -->
<LangVersion>preview</LangVersion>
<PropertyGroup>
<LangVersion>12.0</LangVersion>
</PropertyGroup>

<!--
Expand Down
17 changes: 16 additions & 1 deletion src/ImageSharp/Advanced/AotCompilerTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,11 @@ private static void Seed<TPixel>()
AotCompileResamplers<TPixel>();
AotCompileQuantizers<TPixel>();
AotCompilePixelSamplingStrategys<TPixel>();
AotCompilePixelMaps<TPixel>();
AotCompileDithers<TPixel>();
AotCompileMemoryManagers<TPixel>();

Unsafe.SizeOf<TPixel>();
_ = Unsafe.SizeOf<TPixel>();

// TODO: Do the discovery work to figure out what works and what doesn't.
}
Expand Down Expand Up @@ -514,6 +515,20 @@ private static void AotCompilePixelSamplingStrategys<TPixel>()
default(ExtensivePixelSamplingStrategy).EnumeratePixelRegions(default(ImageFrame<TPixel>));
}

/// <summary>
/// This method pre-seeds the all <see cref="IColorIndexCache{T}" /> in the AoT compiler.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
[Preserve]
private static void AotCompilePixelMaps<TPixel>()
where TPixel : unmanaged, IPixel<TPixel>
{
default(EuclideanPixelMap<TPixel, HybridCache>).GetClosestColor(default, out _);
default(EuclideanPixelMap<TPixel, AccurateCache>).GetClosestColor(default, out _);
default(EuclideanPixelMap<TPixel, CoarseCache>).GetClosestColor(default, out _);
default(EuclideanPixelMap<TPixel, NullCache>).GetClosestColor(default, out _);
}

/// <summary>
/// This method pre-seeds the all <see cref="IDither" /> in the AoT compiler.
/// </summary>
Expand Down
29 changes: 29 additions & 0 deletions src/ImageSharp/Common/InlineArray.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.

// <auto-generated />

using System;
using System.Runtime.CompilerServices;

namespace SixLabors.ImageSharp;

/// <summary>
/// Represents a safe, fixed sized buffer of 4 elements.
/// </summary>
[InlineArray(4)]
internal struct InlineArray4<T>
{
private T t;
}

/// <summary>
/// Represents a safe, fixed sized buffer of 16 elements.
/// </summary>
[InlineArray(16)]
internal struct InlineArray16<T>
{
private T t;
}


38 changes: 38 additions & 0 deletions src/ImageSharp/Common/InlineArray.tt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.

// <auto-generated />

using System;
using System.Runtime.CompilerServices;

namespace SixLabors.ImageSharp;

<#GenerateInlineArrays();#>

<#+
private static int[] Lengths = new int[] {4, 16 };

void GenerateInlineArrays()
{
foreach (int length in Lengths)
{
#>
/// <summary>
/// Represents a safe, fixed sized buffer of <#=length#> elements.
/// </summary>
[InlineArray(<#=length#>)]
internal struct InlineArray<#=length#><T>
{
private T t;
}

<#+
}
}
#>
4 changes: 4 additions & 0 deletions src/ImageSharp/Formats/AlphaAwareImageEncoder.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.

using SixLabors.ImageSharp.Processing.Processors.Quantization;

namespace SixLabors.ImageSharp.Formats;

/// <summary>
Expand All @@ -10,6 +12,8 @@ public abstract class AlphaAwareImageEncoder : ImageEncoder
{
/// <summary>
/// Gets or initializes the mode that determines how transparent pixels are handled during encoding.
/// This overrides any other settings that may affect the encoding of transparent pixels
/// including those passed via <see cref="QuantizerOptions"/>.
/// </summary>
public TransparentColorMode TransparentColorMode { get; init; }
}
7 changes: 5 additions & 2 deletions src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -362,10 +362,13 @@ private void WriteImage<TPixel>(
ImageFrame<TPixel>? clonedFrame = null;
try
{
if (EncodingUtilities.ShouldClearTransparentPixels<TPixel>(this.transparentColorMode))
// No need to clone when quantizing. The quantizer will do it for us.
// TODO: We should really try to avoid the clone entirely.
int bpp = this.bitsPerPixel != null ? (int)this.bitsPerPixel : 32;
if (bpp > 8 && EncodingUtilities.ShouldReplaceTransparentPixels<TPixel>(this.transparentColorMode))
{
clonedFrame = image.Frames.RootFrame.Clone();
EncodingUtilities.ClearTransparentPixels(clonedFrame, Color.Transparent);
EncodingUtilities.ReplaceTransparentPixels(clonedFrame);
}

ImageFrame<TPixel> encodingFrame = clonedFrame ?? image.Frames.RootFrame;
Expand Down
3 changes: 1 addition & 2 deletions src/ImageSharp/Formats/Bmp/BmpMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,5 @@ public FormatConnectingMetadata ToFormatConnectingMetadata()
/// <inheritdoc/>
public void AfterImageApply<TPixel>(Image<TPixel> destination)
where TPixel : unmanaged, IPixel<TPixel>
{
}
=> this.ColorTable = null;
}
3 changes: 1 addition & 2 deletions src/ImageSharp/Formats/Cur/CurFrameMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ public static CurFrameMetadata FromFormatConnectingFrameMetadata(FormatConnectin
Compression = compression,
EncodingWidth = ClampEncodingDimension(metadata.EncodingWidth),
EncodingHeight = ClampEncodingDimension(metadata.EncodingHeight),
ColorTable = compression == IconFrameCompression.Bmp ? metadata.ColorTable : null
};
}

Expand All @@ -113,7 +112,6 @@ public FormatConnectingFrameMetadata ToFormatConnectingFrameMetadata()
=> new()
{
PixelTypeInfo = this.GetPixelTypeInfo(),
ColorTable = this.ColorTable,
EncodingWidth = this.EncodingWidth,
EncodingHeight = this.EncodingHeight
};
Expand All @@ -126,6 +124,7 @@ public void AfterFrameApply<TPixel>(ImageFrame<TPixel> source, ImageFrame<TPixel
float ratioY = destination.Height / (float)source.Height;
this.EncodingWidth = ScaleEncodingDimension(this.EncodingWidth, destination.Width, ratioX);
this.EncodingHeight = ScaleEncodingDimension(this.EncodingHeight, destination.Height, ratioY);
this.ColorTable = null;
}

/// <inheritdoc/>
Expand Down
9 changes: 3 additions & 6 deletions src/ImageSharp/Formats/Cur/CurMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,7 @@ public static CurMetadata FromFormatConnectingMetadata(FormatConnectingMetadata
return new CurMetadata
{
BmpBitsPerPixel = bbpp,
Compression = compression,
ColorTable = compression == IconFrameCompression.Bmp ? metadata.ColorTable : null
Compression = compression
};
}

Expand Down Expand Up @@ -145,15 +144,13 @@ public FormatConnectingMetadata ToFormatConnectingMetadata()
EncodingType = this.Compression == IconFrameCompression.Bmp && this.BmpBitsPerPixel <= BmpBitsPerPixel.Bit8
? EncodingType.Lossy
: EncodingType.Lossless,
PixelTypeInfo = this.GetPixelTypeInfo(),
ColorTable = this.ColorTable
PixelTypeInfo = this.GetPixelTypeInfo()
};

/// <inheritdoc/>
public void AfterImageApply<TPixel>(Image<TPixel> destination)
where TPixel : unmanaged, IPixel<TPixel>
{
}
=> this.ColorTable = null;

/// <inheritdoc/>
IDeepCloneable IDeepCloneable.DeepClone() => this.DeepClone();
Expand Down
Loading
Loading