Skip to content

Commit

Permalink
Add .NET 8 target and migrate to System.Text.Json
Browse files Browse the repository at this point in the history
New features:
* Now multi-targets both .NET 8 and .NET Standard 2.0
* Trimming and AOT are now supported on .NET 8
* Switched to using System.Text.Json instead of Newtonsoft.Json
* Added support for RecyclableMemoryStream 3.x
* Dropped 2 dependencies: Microsoft.CSharp and Newtonsoft.Json

Breaking changes:

Check your code for usage of deprecated methods and fix them.
The next release will involve cleanup of all deprecated methods (both the ones deprecated for years and the ones deprecated in this release).

Removed the following APIs (not frequently used)
```
public static dynamic? DeserializeDynamic(this IJsonResponseProvider p)

public static T? Deserialize<T>(this IJsonResponseProvider p) where T : class
```

Deprecated lots of APIs, including the following:
```
* All ToImageflowDynamic() methods on objects. Use ToJsonNode() instead.
* JobContext.Execute<T>
* JobContext.SendMessage<T>

```
  • Loading branch information
lilith committed Jan 29, 2024
1 parent 5b1f325 commit 5647fd7
Show file tree
Hide file tree
Showing 43 changed files with 1,740 additions and 587 deletions.
30 changes: 30 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
## Changelog

## v0.11 (2024-01-29)

New features:
* Now multi-targets both .NET 8 and .NET Standard 2.0
* Trimming and AOT are now supported on .NET 8
* Switched to using System.Text.Json instead of Newtonsoft.Json
* Added support for RecyclableMemoryStream 3.x
* Dropped 2 dependencies: Microsoft.CSharp and Newtonsoft.Json

Breaking changes:

Check your code for usage of deprecated methods and fix them.
The next release will involve cleanup of all deprecated methods (both the ones deprecated for years and the ones deprecated in this release).

Removed the following APIs (not frequently used)
```
public static dynamic? DeserializeDynamic(this IJsonResponseProvider p)
public static T? Deserialize<T>(this IJsonResponseProvider p) where T : class
```

Deprecated lots of APIs, including the following:
```
* All ToImageflowDynamic() methods on objects. Use ToJsonNode() instead.
* JobContext.Execute<T>
* JobContext.SendMessage<T>
```
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
[![Build status](https://ci.appveyor.com/api/projects/status/vqfofqe3bwqwdu4a?svg=true)](https://ci.appveyor.com/project/imazen/imageflow-dotnet)


Imageflow.NET is a .NET API for [Imageflow](https://github.com/imazen/imageflow), the fast image optimization and processing library for web servers. Imageflow focuses on security, quality, and performance - in that order. Imageflow.NET is a .NET Standard 2.0 library, and as such is compatible with .NET 4.6.2+, .NET Core 2.0+, and .NET 5/6/7.
Imageflow.NET is a .NET API for [Imageflow](https://github.com/imazen/imageflow), the fast image optimization and processing library for web servers. Imageflow focuses on security, quality, and performance - in that order. Imageflow.NET is a .NET 8.0 & .NET Standard 2.0 library, and as such is compatible with .NET 4.6.2+, .NET Core 2.0+, and .NET 5/6/7/8.

### On .NET Core 3.x and .NET 5/6/7 (or if using PackageReference on .NET 4.x)
Note: We recently switched from Newtonsoft to System.Text.Json to support AOT and trimming; see [CHANGES.md](https://github.com/imazen/imageflow-dotnet/blob/master/CHANGES.md) for details and some breaking changes.

### On .NET Core 3.x and .NET 5/6/7/8 (or if using PackageReference on .NET 4.x)

```
dotnet add package Imageflow.AllPlatforms
Expand Down
10 changes: 3 additions & 7 deletions src/Imageflow.AllPlatforms/Imageflow.AllPlatforms.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,12 @@

<TargetFrameworks>net8.0;netstandard2.0</TargetFrameworks>
<IsTrimmable Condition="'$(TargetFramework)' == 'net8.0'">true</IsTrimmable>
<EnableTrimAnalyzer Condition="'$(TargetFramework)' == 'net8.0'">true</EnableTrimAnalyzer>
<IsAotCompatible Condition="'$(TargetFramework)' == 'net8.0'">true</IsAotCompatible>
<IsPackable>true</IsPackable>
<PackageIcon>icon.png</PackageIcon>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="PolySharp" Version="1.*">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Imageflow\Imageflow.Net.csproj" />
</ItemGroup>
Expand Down
88 changes: 31 additions & 57 deletions src/Imageflow.AllPlatforms/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,25 +35,14 @@
"Microsoft.NETCore.Platforms": "1.1.0"
}
},
"PolySharp": {
"type": "Direct",
"requested": "[1.*, )",
"resolved": "1.14.1",
"contentHash": "mOOmFYwad3MIOL14VCjj02LljyF1GNw1wP0YVlxtcPvqdxjGGMNdNJJxHptlry3MOd8b40Flm8RPOM8JOlN2sQ=="
},
"Microsoft.Bcl.AsyncInterfaces": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw==",
"resolved": "6.0.0",
"contentHash": "UcSjPsst+DfAdJGVDsu346FX0ci0ah+lw3WRtn18NUwEqRt70HaOQ7lI72vy3+1LxtqI3T5GWwV39rQSrCzAeg==",
"dependencies": {
"System.Threading.Tasks.Extensions": "4.5.4"
}
},
"Microsoft.CSharp": {
"type": "Transitive",
"resolved": "4.7.0",
"contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA=="
},
"Microsoft.IO.RecyclableMemoryStream": {
"type": "Transitive",
"resolved": "1.2.2",
Expand All @@ -64,20 +53,15 @@
"resolved": "1.1.0",
"contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A=="
},
"Newtonsoft.Json": {
"type": "Transitive",
"resolved": "13.0.3",
"contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ=="
},
"System.Buffers": {
"type": "Transitive",
"resolved": "4.5.1",
"contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
},
"System.Memory": {
"type": "Transitive",
"resolved": "4.5.5",
"contentHash": "XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==",
"resolved": "4.5.4",
"contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==",
"dependencies": {
"System.Buffers": "4.5.1",
"System.Numerics.Vectors": "4.4.0",
Expand All @@ -86,8 +70,8 @@
},
"System.Numerics.Vectors": {
"type": "Transitive",
"resolved": "4.4.0",
"contentHash": "UiLzLW+Lw6HLed1Hcg+8jSRttrbuXv7DANVj0DkL9g6EnnzbL75EB7EWsw5uRbhxd/4YdG8li5XizGWepmG3PQ=="
"resolved": "4.5.0",
"contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ=="
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
Expand All @@ -96,24 +80,25 @@
},
"System.Text.Encodings.Web": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ==",
"resolved": "6.0.0",
"contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==",
"dependencies": {
"System.Buffers": "4.5.1",
"System.Memory": "4.5.5",
"System.Memory": "4.5.4",
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
}
},
"System.Text.Json": {
"type": "Transitive",
"resolved": "8.0.1",
"contentHash": "7AWk2za1hSEJBppe/Lg+uDcam2TrDqwIKa9XcPssSwyjC2xa39EKEGul3CO5RWNF+hMuZG4zlBDrvhBdDTg4lg==",
"resolved": "6.0.9",
"contentHash": "2j16oUgtIzl7Xtk7demG0i/v5aU/ZvULcAnJvPb63U3ZhXJ494UYcxuEj5Fs49i3XDrk5kU/8I+6l9zRCw3cJw==",
"dependencies": {
"Microsoft.Bcl.AsyncInterfaces": "8.0.0",
"Microsoft.Bcl.AsyncInterfaces": "6.0.0",
"System.Buffers": "4.5.1",
"System.Memory": "4.5.5",
"System.Memory": "4.5.4",
"System.Numerics.Vectors": "4.5.0",
"System.Runtime.CompilerServices.Unsafe": "6.0.0",
"System.Text.Encodings.Web": "8.0.0",
"System.Text.Encodings.Web": "6.0.0",
"System.Threading.Tasks.Extensions": "4.5.4"
}
},
Expand All @@ -128,10 +113,8 @@
"imageflow.net": {
"type": "Project",
"dependencies": {
"Microsoft.CSharp": "[4.*, )",
"Microsoft.IO.RecyclableMemoryStream": "[1.2.*, 3.0.0)",
"Newtonsoft.Json": "[13.0.3, 14.0.0)",
"System.Text.Json": "[8.0.1, )"
"Microsoft.IO.RecyclableMemoryStream": "[1.2.*, 4.0.0)",
"System.Text.Json": "[6.*, )"
}
}
},
Expand Down Expand Up @@ -166,47 +149,38 @@
"resolved": "8.0.1",
"contentHash": "ADdJXuKNjwZDfBmybMnpvwd5CK3gp92WkWqqeQhW4W+q4MO3Qaa9QyW2DcFLAvCDMcCWxT5hRXqGdv13oon7nA=="
},
"PolySharp": {
"type": "Direct",
"requested": "[1.*, )",
"resolved": "1.14.1",
"contentHash": "mOOmFYwad3MIOL14VCjj02LljyF1GNw1wP0YVlxtcPvqdxjGGMNdNJJxHptlry3MOd8b40Flm8RPOM8JOlN2sQ=="
},
"Microsoft.CSharp": {
"type": "Transitive",
"resolved": "4.7.0",
"contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA=="
},
"Microsoft.IO.RecyclableMemoryStream": {
"type": "Transitive",
"resolved": "1.2.2",
"contentHash": "LA4RBTStohA0hAAs6oKchmIC5M5Mjd5MwfB7vbbl+312N5kXj8abTGOgwZy6ASJYLCiqiiK5kHS0hDGEgfkB8g=="
},
"Newtonsoft.Json": {
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
"resolved": "13.0.3",
"contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ=="
"resolved": "6.0.0",
"contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
},
"System.Text.Encodings.Web": {
"type": "Transitive",
"resolved": "8.0.0",
"contentHash": "yev/k9GHAEGx2Rg3/tU6MQh4HGBXJs70y7j1LaM1i/ER9po+6nnQ6RRqTJn1E7Xu0fbIFK80Nh5EoODxrbxwBQ=="
"resolved": "6.0.0",
"contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==",
"dependencies": {
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
}
},
"System.Text.Json": {
"type": "Transitive",
"resolved": "8.0.1",
"contentHash": "7AWk2za1hSEJBppe/Lg+uDcam2TrDqwIKa9XcPssSwyjC2xa39EKEGul3CO5RWNF+hMuZG4zlBDrvhBdDTg4lg==",
"resolved": "6.0.9",
"contentHash": "2j16oUgtIzl7Xtk7demG0i/v5aU/ZvULcAnJvPb63U3ZhXJ494UYcxuEj5Fs49i3XDrk5kU/8I+6l9zRCw3cJw==",
"dependencies": {
"System.Text.Encodings.Web": "8.0.0"
"System.Runtime.CompilerServices.Unsafe": "6.0.0",
"System.Text.Encodings.Web": "6.0.0"
}
},
"imageflow.net": {
"type": "Project",
"dependencies": {
"Microsoft.CSharp": "[4.*, )",
"Microsoft.IO.RecyclableMemoryStream": "[1.2.*, 3.0.0)",
"Newtonsoft.Json": "[13.0.3, 14.0.0)",
"System.Text.Json": "[8.0.1, )"
"Microsoft.IO.RecyclableMemoryStream": "[1.2.*, 4.0.0)",
"System.Text.Json": "[6.*, )"
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/Imageflow.both.sln
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
..\Directory.Build.props = ..\Directory.Build.props
..\LICENSE.txt = ..\LICENSE.txt
..\SECURITY.md = ..\SECURITY.md
..\CHANGES.md = ..\CHANGES.md
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Imageflow.AllPlatforms", "Imageflow.AllPlatforms\Imageflow.AllPlatforms.csproj", "{88C05C97-B3B9-473F-804D-EC1CDF936953}"
Expand Down
1 change: 1 addition & 0 deletions src/Imageflow.both.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=framewise/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=imageflow/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
45 changes: 36 additions & 9 deletions src/Imageflow/Bindings/ImageInfo.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,46 @@
namespace Imageflow.Bindings
using System.Text.Json.Nodes;
using Imageflow.Fluent;

namespace Imageflow.Bindings
{
public class ImageInfo
{
private ImageInfo(dynamic imageInfo)
private ImageInfo(JsonNode imageInfo)
{
ImageWidth = imageInfo.image_width.Value;
ImageHeight = imageInfo.image_height.Value;
PreferredMimeType = imageInfo.preferred_mime_type.Value;
PreferredExtension = imageInfo.preferred_extension.Value;
FrameDecodesInto = Enum.Parse(typeof(Fluent.PixelFormat), imageInfo.frame_decodes_into.Value,
true);
var obj = imageInfo.AsObject();
// ImageWidth = imageInfo.image_width.Value;
// ImageHeight = imageInfo.image_height.Value;
// PreferredMimeType = imageInfo.preferred_mime_type.Value;
// PreferredExtension = imageInfo.preferred_extension.Value;
// FrameDecodesInto = Enum.Parse(typeof(Fluent.PixelFormat), imageInfo.frame_decodes_into.Value,
// true);
const string widthMsg = "Imageflow get_image_info responded with null image_info.image_width";
ImageWidth = obj.TryGetPropertyValue("image_width", out var imageWidthValue)
? imageWidthValue?.GetValue<long>() ?? throw new ImageflowAssertionFailed(widthMsg)
: throw new ImageflowAssertionFailed(widthMsg);

const string heightMsg = "Imageflow get_image_info responded with null image_info.image_height";
ImageHeight = obj.TryGetPropertyValue("image_height", out var imageHeightValue)
? imageHeightValue?.GetValue<long>() ?? throw new ImageflowAssertionFailed(heightMsg)
: throw new ImageflowAssertionFailed(heightMsg);

const string mimeMsg = "Imageflow get_image_info responded with null image_info.preferred_mime_type";
PreferredMimeType = obj.TryGetPropertyValue("preferred_mime_type", out var preferredMimeTypeValue)
? preferredMimeTypeValue?.GetValue<string>() ?? throw new ImageflowAssertionFailed(mimeMsg)
: throw new ImageflowAssertionFailed(mimeMsg);

const string extMsg = "Imageflow get_image_info responded with null image_info.preferred_extension";
PreferredExtension = obj.TryGetPropertyValue("preferred_extension", out var preferredExtensionValue)
? preferredExtensionValue?.GetValue<string>() ?? throw new ImageflowAssertionFailed(extMsg)
: throw new ImageflowAssertionFailed(extMsg);

const string frameMsg = "Imageflow get_image_info responded with null image_info.frame_decodes_into";
FrameDecodesInto = obj.TryGetPropertyValue("frame_decodes_into", out var frameDecodesIntoValue)
? PixelFormatParser.Parse(frameDecodesIntoValue?.GetValue<string>() ?? throw new ImageflowAssertionFailed(frameMsg))
: throw new ImageflowAssertionFailed(frameMsg);

}
internal static ImageInfo FromDynamic(dynamic imageInfo)
internal static ImageInfo FromDynamic(JsonNode imageInfo)
{
return new ImageInfo(imageInfo);
}
Expand Down
4 changes: 2 additions & 2 deletions src/Imageflow/Bindings/ImageflowException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ private static ErrorFetchResult TryGetErrorString(JobContextHandle c, ulong buff
}
}

internal static ImageflowException FromContext(JobContextHandle c, ulong defaultBufferSize = 2048)
internal static ImageflowException FromContext(JobContextHandle c, ulong defaultBufferSize = 2048, string? additionalInfo = null)
{
var result = ErrorFetchResult.BufferTooSmall;
for (var bufferSize = defaultBufferSize; bufferSize < MaxBufferSize; bufferSize *= 2)
Expand All @@ -59,7 +59,7 @@ internal static ImageflowException FromContext(JobContextHandle c, ulong default
switch (result)
{
case ErrorFetchResult.Success:
return new ImageflowException(message ?? "Unknown Imageflow error");
return new ImageflowException((message ?? "Unknown Imageflow Error") + (additionalInfo != null ? $"\nAdditional info: {additionalInfo}" : ""));
case ErrorFetchResult.ContextInvalid:
return new ImageflowException("Imageflow context (JobContextHandle) is invalid");
case ErrorFetchResult.NoError:
Expand Down
Loading

0 comments on commit 5647fd7

Please sign in to comment.