Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to Imagesharp v3 #305

Merged
merged 39 commits into from
Mar 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
a1b8421
Update to ImageSharp v3 builds
JimBobSquarePants Feb 14, 2023
209298f
Remove unused namespaces
JimBobSquarePants Feb 14, 2023
581b9e0
Update ImageSharp and fix build
JimBobSquarePants Feb 20, 2023
9e835f4
Update TestServerFixture.cs
JimBobSquarePants Feb 20, 2023
edb5b5b
Try installing and running the s3ver locally
JimBobSquarePants Feb 20, 2023
548ec45
Skip macOS to test other environments
JimBobSquarePants Feb 20, 2023
e5349d8
Revert action changes
JimBobSquarePants Feb 20, 2023
5a1ac6a
Skip to see if Azurite works
JimBobSquarePants Feb 20, 2023
1a71bcf
Skip config for testing
JimBobSquarePants Feb 20, 2023
0c176ac
Try using a different port
JimBobSquarePants Feb 20, 2023
85d84f7
Try specifying localhost
JimBobSquarePants Feb 20, 2023
b86a433
Use default configuration
JimBobSquarePants Feb 20, 2023
97bea07
Test OnBeforeLoadAsync
JimBobSquarePants Feb 20, 2023
2239a9a
Update to latest build
JimBobSquarePants Feb 27, 2023
43aa837
Update QualityWebProcessor.cs
JimBobSquarePants Feb 27, 2023
d1ffdf8
Add Parsing of TargetRectangle to ResizeWebProcessor
stefannikolei Mar 1, 2023
5f0f77b
Remove nullabel disable
stefannikolei Mar 1, 2023
558e582
Remove nullable disable in Resolvers
stefannikolei Mar 1, 2023
d38cf39
Remove nullable disable in providers
stefannikolei Mar 1, 2023
5942354
Remove nullable disable from Processors
stefannikolei Mar 1, 2023
d80b750
Remove nullable disable from Middleware
stefannikolei Mar 1, 2023
844a4dc
Remove nullable disable from DependencyInjection
stefannikolei Mar 1, 2023
bd96955
Remove nullable disable from Commands
stefannikolei Mar 1, 2023
1422dd0
Remove nullable disable from converters
stefannikolei Mar 1, 2023
5b6086d
Remove nullable disable from caching
stefannikolei Mar 1, 2023
603f3e5
Remove x + y from targetrectangle
stefannikolei Mar 3, 2023
e83c10c
Only create rectangle when mode = manual
stefannikolei Mar 3, 2023
cd276a3
Merge pull request #306 from stefannikolei/stefannikolei/addTargetRec…
JimBobSquarePants Mar 5, 2023
044517c
Merge branch 'js/imagesharpV3' into stefannikolei/nullable/remove_nul…
JimBobSquarePants Mar 5, 2023
338e5f4
Merge remote-tracking branch 'upstream/js/imagesharpV3' into stefanni…
JimBobSquarePants Mar 5, 2023
057099b
Merge branch 'stefannikolei/nullable/remove_nullable-disable' of http…
JimBobSquarePants Mar 5, 2023
f349ad1
Cleanup return
JimBobSquarePants Mar 5, 2023
5ee6d62
Optimize ColorConverter
JimBobSquarePants Mar 5, 2023
885e259
Cleanup
JimBobSquarePants Mar 5, 2023
438daf0
Merge pull request #307 from stefannikolei/stefannikolei/nullable/rem…
JimBobSquarePants Mar 5, 2023
2821506
.NET 7 fixes
JimBobSquarePants Mar 5, 2023
5535823
Fix last nullable issues
JimBobSquarePants Mar 5, 2023
4052958
Fix readme and workflow
JimBobSquarePants Mar 5, 2023
bc1e923
Fix color converter
JimBobSquarePants Mar 5, 2023
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: 3 additions & 2 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,19 @@
# Set explicit file behavior to:
# treat as text
# normalize to Unix-style line endings and
# use a union merge when resoling conflicts
# use a union merge when resolving conflicts
###############################################################################
*.csproj text eol=lf merge=union
*.dbproj text eol=lf merge=union
*.fsproj text eol=lf merge=union
*.ncrunchproject text eol=lf merge=union
*.vbproj text eol=lf merge=union
*.shproj text eol=lf merge=union
###############################################################################
# Set explicit file behavior to:
# treat as text
# normalize to Windows-style line endings and
# use a union merge when resoling conflicts
# use a union merge when resolving conflicts
###############################################################################
*.sln text eol=crlf merge=union
###############################################################################
Expand Down
14 changes: 10 additions & 4 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,15 @@ jobs:
shell: pwsh
run: ./ci-pack.ps1

- name: MyGet Publish
- name: Feedz Publish
shell: pwsh
run: |
dotnet nuget push .\artifacts\*.nupkg -k ${{secrets.MYGET_TOKEN}} -s https://www.myget.org/F/sixlabors/api/v2/package
dotnet nuget push .\artifacts\*.snupkg -k ${{secrets.MYGET_TOKEN}} -s https://www.myget.org/F/sixlabors/api/v3/index.json
# TODO: If github.ref starts with 'refs/tags' then it was tag push and we can optionally push out package to nuget.org
dotnet nuget push .\artifacts\*.nupkg -k ${{secrets.FEEDZ_TOKEN}} -s https://f.feedz.io/sixlabors/sixlabors/nuget/index.json --skip-duplicate
dotnet nuget push .\artifacts\*.snupkg -k ${{secrets.FEEDZ_TOKEN}} -s https://f.feedz.io/sixlabors/sixlabors/symbols --skip-duplicate

- name: NuGet Publish
if: ${{ startsWith(github.ref, 'refs/tags/') }}
shell: pwsh
run: |
dotnet nuget push .\artifacts\*.nupkg -k ${{secrets.NUGET_TOKEN}} -s https://api.nuget.org/v3/index.json --skip-duplicate
dotnet nuget push .\artifacts\*.snupkg -k ${{secrets.NUGET_TOKEN}} -s https://api.nuget.org/v3/index.json --skip-duplicate
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ For more information, see the [.NET Foundation Code of Conduct](https://dotnetfo

### Installation

Install stable releases via Nuget; development releases are available via MyGet.
Install stable releases via Nuget; development releases are available via Feedz.io.

| Package Name | Release (NuGet) | Nightly (MyGet) |
| Package Name | Release (NuGet) | Nightly (Feedz.io) |
|--------------------------------|-----------------|-----------------|
| `SixLabors.ImageSharp.Web` | [![NuGet](https://img.shields.io/nuget/v/SixLabors.ImageSharp.Web.svg)](https://www.nuget.org/packages/SixLabors.ImageSharp.Web/) | [![MyGet](https://img.shields.io/myget/sixlabors/vpre/SixLabors.ImageSharp.Web.svg)](https://www.myget.org/feed/sixlabors/package/nuget/SixLabors.ImageSharp.Web) |
| `SixLabors.ImageSharp.Web` | [![NuGet](https://img.shields.io/nuget/v/SixLabors.ImageSharp.Web.svg)](https://www.nuget.org/packages/SixLabors.ImageSharp.Web/) | [![feedz.io](https://img.shields.io/badge/endpoint.svg?url=https%3A%2F%2Ff.feedz.io%2Fsixlabors%2Fsixlabors%2Fshield%2FSixLabors.ImageSharp.Web%2Flatest)](https://f.feedz.io/sixlabors/sixlabors/nuget/index.json) |

## Manual build

Expand Down
2 changes: 1 addition & 1 deletion ci-pack.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ dotnet clean -c Release
$repositoryUrl = "https://github.com/$env:GITHUB_REPOSITORY"

# Building for packing and publishing.
dotnet pack -c Release --output "$PSScriptRoot/artifacts" /p:RepositoryUrl=$repositoryUrl
dotnet pack -c Release -p:PackageOutputPath="$PSScriptRoot/artifacts" -p:RepositoryUrl=$repositoryUrl
88 changes: 37 additions & 51 deletions samples/ImageSharp.Web.Sample/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,50 +30,44 @@ public class Startup
/// </summary>
/// <param name="services">The collection of service descriptors.</param>
public void ConfigureServices(IServiceCollection services)
{
services.AddImageSharp()
.SetRequestParser<QueryCollectionRequestParser>()
.Configure<PhysicalFileSystemCacheOptions>(options =>
{
options.CacheRootPath = null;
options.CacheFolder = "is-cache";
options.CacheFolderDepth = 8;
})
.SetCache<PhysicalFileSystemCache>()
.SetCacheKey<UriRelativeLowerInvariantCacheKey>()
.SetCacheHash<SHA256CacheHash>()
.Configure<PhysicalFileSystemProviderOptions>(options =>
{
options.ProviderRootPath = null;
})
.AddProvider<PhysicalFileSystemProvider>()
.AddProcessor<ResizeWebProcessor>()
.AddProcessor<FormatWebProcessor>()
.AddProcessor<BackgroundColorWebProcessor>()
.AddProcessor<QualityWebProcessor>()
.AddProcessor<AutoOrientWebProcessor>();
=> services.AddImageSharp()
.SetRequestParser<QueryCollectionRequestParser>()
.Configure<PhysicalFileSystemCacheOptions>(options =>
{
options.CacheRootPath = null;
options.CacheFolder = "is-cache";
options.CacheFolderDepth = 8;
})
.SetCache<PhysicalFileSystemCache>()
.SetCacheKey<UriRelativeLowerInvariantCacheKey>()
.SetCacheHash<SHA256CacheHash>()
.Configure<PhysicalFileSystemProviderOptions>(options => options.ProviderRootPath = null)
.AddProvider<PhysicalFileSystemProvider>()
.AddProcessor<ResizeWebProcessor>()
.AddProcessor<FormatWebProcessor>()
.AddProcessor<BackgroundColorWebProcessor>()
.AddProcessor<QualityWebProcessor>()
.AddProcessor<AutoOrientWebProcessor>();

// Add the default service and options.
//
// services.AddImageSharp();
// Add the default service and options.
//
// services.AddImageSharp();

// Or add the default service and custom options.
//
// this.ConfigureDefaultServicesAndCustomOptions(services);
// Or add the default service and custom options.
//
// this.ConfigureDefaultServicesAndCustomOptions(services);

// Or we can fine-grain control adding the default options and configure all other services.
//
// this.ConfigureCustomServicesAndDefaultOptions(services);
// Or we can fine-grain control adding the default options and configure all other services.
//
// this.ConfigureCustomServicesAndDefaultOptions(services);

// Or we can fine-grain control adding custom options and configure all other services
// There are also factory methods for each builder that will allow building from configuration files.
//
// this.ConfigureCustomServicesAndCustomOptions(services);
}
// Or we can fine-grain control adding custom options and configure all other services
// There are also factory methods for each builder that will allow building from configuration files.
//
// this.ConfigureCustomServicesAndCustomOptions(services);

private void ConfigureDefaultServicesAndCustomOptions(IServiceCollection services)
{
services.AddImageSharp(options =>
=> services.AddImageSharp(options =>
{
options.Configuration = Configuration.Default;
options.BrowserMaxAge = TimeSpan.FromDays(7);
Expand All @@ -84,18 +78,14 @@ private void ConfigureDefaultServicesAndCustomOptions(IServiceCollection service
options.OnProcessedAsync = _ => Task.CompletedTask;
options.OnPrepareResponseAsync = _ => Task.CompletedTask;
});
}

private void ConfigureCustomServicesAndDefaultOptions(IServiceCollection services)
{
services.AddImageSharp()
.RemoveProcessor<FormatWebProcessor>()
.RemoveProcessor<BackgroundColorWebProcessor>();
}
=> services.AddImageSharp()
.RemoveProcessor<FormatWebProcessor>()
.RemoveProcessor<BackgroundColorWebProcessor>();

private void ConfigureCustomServicesAndCustomOptions(IServiceCollection services)
{
services.AddImageSharp(options =>
=> services.AddImageSharp(options =>
{
options.Configuration = Configuration.Default;
options.BrowserMaxAge = TimeSpan.FromDays(7);
Expand All @@ -107,10 +97,7 @@ private void ConfigureCustomServicesAndCustomOptions(IServiceCollection services
options.OnPrepareResponseAsync = _ => Task.CompletedTask;
})
.SetRequestParser<QueryCollectionRequestParser>()
.Configure<PhysicalFileSystemCacheOptions>(options =>
{
options.CacheFolder = "different-cache";
})
.Configure<PhysicalFileSystemCacheOptions>(options => options.CacheFolder = "different-cache")
.SetCache<PhysicalFileSystemCache>()
.SetCacheKey<UriRelativeLowerInvariantCacheKey>()
.SetCacheHash<SHA256CacheHash>()
Expand All @@ -121,7 +108,6 @@ private void ConfigureCustomServicesAndCustomOptions(IServiceCollection services
.AddProcessor<FormatWebProcessor>()
.AddProcessor<BackgroundColorWebProcessor>()
.AddProcessor<QualityWebProcessor>();
}

/// <summary>
/// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
Expand Down
2 changes: 1 addition & 1 deletion shared-infrastructure
5 changes: 3 additions & 2 deletions src/ImageSharp.Web.Providers.AWS/AmazonS3ClientFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ internal static class AmazonS3ClientFactory
/// <returns>
/// A new <see cref="AmazonS3Client"/>.
/// </returns>
/// <exception cref="ArgumentException">Invalid configuration.</exception>
public static AmazonS3Client CreateClient(IAWSS3BucketClientOptions options)
{
if (!string.IsNullOrWhiteSpace(options.Endpoint))
Expand All @@ -33,14 +34,14 @@ public static AmazonS3Client CreateClient(IAWSS3BucketClientOptions options)
{
// AccessSecret can be empty.
Guard.NotNullOrWhiteSpace(options.Region, nameof(options.Region));
var region = RegionEndpoint.GetBySystemName(options.Region);
RegionEndpoint region = RegionEndpoint.GetBySystemName(options.Region);
AmazonS3Config config = new() { RegionEndpoint = region, UseAccelerateEndpoint = options.UseAccelerateEndpoint };
SetTimeout(config, options.Timeout);
return new AmazonS3Client(options.AccessKey, options.AccessSecret, config);
}
else if (!string.IsNullOrWhiteSpace(options.Region))
{
var region = RegionEndpoint.GetBySystemName(options.Region);
RegionEndpoint region = RegionEndpoint.GetBySystemName(options.Region);
AmazonS3Config config = new() { RegionEndpoint = region, UseAccelerateEndpoint = options.UseAccelerateEndpoint };
SetTimeout(config, options.Timeout);
return new AmazonS3Client(config);
Expand Down
1 change: 0 additions & 1 deletion src/ImageSharp.Web/AsyncHelper.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
#nullable disable

using System.Globalization;

Expand Down
1 change: 0 additions & 1 deletion src/ImageSharp.Web/Caching/HexEncoder.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
#nullable disable

using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
Expand Down
1 change: 0 additions & 1 deletion src/ImageSharp.Web/Caching/ICacheHash.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
#nullable disable

namespace SixLabors.ImageSharp.Web.Caching;

Expand Down
1 change: 0 additions & 1 deletion src/ImageSharp.Web/Caching/ICacheKey.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
#nullable disable

using Microsoft.AspNetCore.Http;
using SixLabors.ImageSharp.Web.Commands;
Expand Down
3 changes: 1 addition & 2 deletions src/ImageSharp.Web/Caching/IImageCache.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
#nullable disable

using SixLabors.ImageSharp.Web.Resolvers;

Expand All @@ -17,7 +16,7 @@ public interface IImageCache
/// </summary>
/// <param name="key">The cache key.</param>
/// <returns>The <see cref="IImageResolver"/>.</returns>
Task<IImageCacheResolver> GetAsync(string key);
Task<IImageCacheResolver?> GetAsync(string key);

/// <summary>
/// Sets the value associated with the specified key.
Expand Down
1 change: 0 additions & 1 deletion src/ImageSharp.Web/Caching/LegacyV1CacheKey.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
#nullable disable

using System.Globalization;
using System.Text;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
#nullable disable

using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;

namespace SixLabors.ImageSharp.Web.Caching;
Expand All @@ -26,6 +26,7 @@ namespace SixLabors.ImageSharp.Web.Caching;
/// 6. When cold is full, cold tail is moved to warm head or removed from dictionary on depending on WasAccessed.
/// </remarks>
internal class ConcurrentTLruCache<TKey, TValue>
where TKey : notnull
{
private readonly ConcurrentDictionary<TKey, LongTickCountLruItem<TKey, TValue>> dictionary;

Expand Down Expand Up @@ -97,9 +98,9 @@ public ConcurrentTLruCache(int concurrencyLevel, int capacity, IEqualityComparer
/// <param name="key">The key of the value to get.</param>
/// <param name="value">When this method returns, contains the object from the cache that has the specified key, or the default value of the type if the operation failed.</param>
/// <returns><see langword="true"/> if the key was found in the cache; otherwise, <see langword="false"/>.</returns>
public bool TryGet(TKey key, out TValue value)
public bool TryGet(TKey key, [NotNullWhen(true)] out TValue? value)
{
if (this.dictionary.TryGetValue(key, out LongTickCountLruItem<TKey, TValue> item))
if (this.dictionary.TryGetValue(key, out LongTickCountLruItem<TKey, TValue>? item))
{
return this.GetOrDiscard(item, out value);
}
Expand All @@ -111,7 +112,7 @@ public bool TryGet(TKey key, out TValue value)
// AggressiveInlining forces the JIT to inline policy.ShouldDiscard(). For LRU policy
// the first branch is completely eliminated due to JIT time constant propogation.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private bool GetOrDiscard(LongTickCountLruItem<TKey, TValue> item, out TValue value)
private bool GetOrDiscard(LongTickCountLruItem<TKey, TValue> item, out TValue? value)
{
if (this.policy.ShouldDiscard(item))
{
Expand All @@ -135,7 +136,7 @@ private bool GetOrDiscard(LongTickCountLruItem<TKey, TValue> item, out TValue va
/// in the cache, or the new value if the key was not in the dictionary.</returns>
public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory)
{
if (this.TryGet(key, out TValue value))
if (this.TryGet(key, out TValue? value))
{
return value;
}
Expand Down Expand Up @@ -164,7 +165,7 @@ public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory)
/// <returns>A task that represents the asynchronous <see cref="GetOrAdd(TKey, Func{TKey, TValue})"/> operation.</returns>
public async Task<TValue> GetOrAddAsync(TKey key, Func<TKey, Task<TValue>> valueFactory)
{
if (this.TryGet(key, out TValue value))
if (this.TryGet(key, out TValue? value))
{
return value;
}
Expand Down Expand Up @@ -202,7 +203,7 @@ public bool TryRemove(TKey key)
// and it will not be marked as removed. If key 1 is fetched while LruItem1* is still in the queue, there will
// be two queue entries for key 1, and neither is marked as removed. Thus when LruItem1 * ages out, it will
// incorrectly remove 1 from the dictionary, and this cycle can repeat.
if (this.dictionary.TryGetValue(key, out LongTickCountLruItem<TKey, TValue> existing))
if (this.dictionary.TryGetValue(key, out LongTickCountLruItem<TKey, TValue>? existing))
{
if (existing.WasRemoved)
{
Expand All @@ -219,7 +220,7 @@ public bool TryRemove(TKey key)
existing.WasRemoved = true;
}

if (this.dictionary.TryRemove(key, out LongTickCountLruItem<TKey, TValue> removedItem))
if (this.dictionary.TryRemove(key, out LongTickCountLruItem<TKey, TValue>? removedItem))
{
// Mark as not accessed, it will later be cycled out of the queues because it can never be fetched
// from the dictionary. Note: Hot/Warm/Cold count will reflect the removed item until it is cycled
Expand Down Expand Up @@ -261,7 +262,7 @@ private void CycleHot()
{
Interlocked.Decrement(ref this.hotCount);

if (this.hotQueue.TryDequeue(out LongTickCountLruItem<TKey, TValue> item))
if (this.hotQueue.TryDequeue(out LongTickCountLruItem<TKey, TValue>? item))
{
ItemDestination where = this.policy.RouteHot(item);
this.Move(item, where);
Expand All @@ -279,7 +280,7 @@ private void CycleWarm()
{
Interlocked.Decrement(ref this.warmCount);

if (this.warmQueue.TryDequeue(out LongTickCountLruItem<TKey, TValue> item))
if (this.warmQueue.TryDequeue(out LongTickCountLruItem<TKey, TValue>? item))
{
ItemDestination where = this.policy.RouteWarm(item);

Expand Down Expand Up @@ -308,7 +309,7 @@ private void CycleCold()
{
Interlocked.Decrement(ref this.coldCount);

if (this.coldQueue.TryDequeue(out LongTickCountLruItem<TKey, TValue> item))
if (this.coldQueue.TryDequeue(out LongTickCountLruItem<TKey, TValue>? item))
{
ItemDestination where = this.policy.RouteCold(item);

Expand Down Expand Up @@ -354,7 +355,7 @@ private void Move(LongTickCountLruItem<TKey, TValue> item, ItemDestination where
break;
}

if (this.dictionary.TryRemove(item.Key, out LongTickCountLruItem<TKey, TValue> removedItem))
if (this.dictionary.TryRemove(item.Key, out LongTickCountLruItem<TKey, TValue>? removedItem))
{
item.WasRemoved = true;
if (removedItem.Value is IDisposable d)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
#nullable disable

namespace SixLabors.ImageSharp.Web.Caching;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
#nullable disable

using System.Diagnostics;
using System.Runtime.CompilerServices;
Expand Down
Loading