Skip to content

Commit

Permalink
Merge pull request #56 from imazen/memory
Browse files Browse the repository at this point in the history
Rewrite internals and add new APIs and deprecation warnings.
  • Loading branch information
lilith authored Mar 8, 2024
2 parents ae68b97 + 7b8e19d commit 0d39641
Show file tree
Hide file tree
Showing 95 changed files with 8,503 additions and 9,519 deletions.
460 changes: 460 additions & 0 deletions .editorconfig

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion .github/workflows/dotnet-core.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ jobs:
test_aot: true
- os: ubuntu-latest
SystemTextJsonVersion: 8.0.1
RecyclableMemoryStreamVersion: 3.0.0
- os: windows-latest
pack: true
docs: true
Expand Down
2 changes: 1 addition & 1 deletion AUTHORS.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
Imageflow.NET contains code contributed by:

Nathanael Jones <[email protected]>
Lilith River <[email protected]>
22 changes: 22 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
## Changelog

## v0.13

This release makes user-facing changes with deprecation warnings. Please review your build warnings to avoid breakage in the future.

* There are new classes for attaching source image data to jobs; use MemorySource.* over ByteSource and BufferedStreamSource.* instead of StreamSource.
* Microsoft.IO.RecyclableMemoryStream 3.x is now required
* System.Buffers and System.Memory 4.x+ are now required on .NET 4.x / .NET Standard 2.0
* InputWatermark.Source is now IMemorySource instead of IBytesSource

It also makes lots of internal changes to increase performance, eliminate unnecessary allocations/copies, and improve compatibility with AOT and trimming.

It is now possible to provide ReadOnlyMemory<byte> data and IOwnedMemory<byte> data, without copying to a byte[] array. The new IAsyncMemorySource interface allows for asynchronous data sources, and the new IMemorySource interface allows for synchronous data sources.

## v0.12 (2024-02-06)

* Fix compatibility with RecyclableMemoryStream 3.x, drop compatibility with 1.x
* Remove default constructor on BuildJobResult and BuildEncodeResult; these are not user-created types.

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

New features:
Expand All @@ -21,6 +39,10 @@ public static dynamic? DeserializeDynamic(this IJsonResponseProvider p)
public static T? Deserialize<T>(this IJsonResponseProvider p) where T : class
```

To accommodate the shift to `System.Text.Json`, interface members `ToJsonNode()` have been added to `IEncoderPreset` and `IWatermarkConstraintBox`. Nobody should be implementing these anyway, other than the Imageflow library itself.

The `object` parameter in `BuildItemBase` protected constructor has been changed to `System.Text.Json.Nodes.JsonNode`.

Deprecated lots of APIs, including the following:
```
* All ToImageflowDynamic() methods on objects. Use ToJsonNode() instead.
Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<PackageTags>Image;Resize;Optimize;Crop;Gif;Jpg;Jpeg;Bitmap;Png;Core;WebP;ImageResizer;Imageflow;Rotate;Imaging;Crunch</PackageTags>

<RestoreLockedMode>false</RestoreLockedMode>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>




Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@



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.
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/9.

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.
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. There are also new classes for attaching source image data to jobs; use MemorySource.* over ByteSource and BufferedStreamSource.* instead of StreamSource.

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

Expand Down Expand Up @@ -48,7 +48,7 @@ public async void TestGetImageInfo()
var imageBytes = Convert.FromBase64String(
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX/TQBcNTh/AAAAAXRSTlPM0jRW/QAAAApJREFUeJxjYgAAAAYAAzY3fKgAAAAASUVORK5CYII=");

var info = await ImageJob.GetImageInfo(new BytesSource(imageBytes));
var info = await ImageJob.GetImageInfo(new MemorySource(imageBytes));

Assert.Equal(info.ImageWidth, 1);
Assert.Equal(info.ImageHeight, 1);
Expand Down Expand Up @@ -149,7 +149,7 @@ public async Task TestBuildCommandString()
{

var r = await b.BuildCommandString(
new BytesSource(imageBytes), // or new StreamSource(Stream stream, bool disposeStream)
new MemorySource(imageBytes), // or new StreamSource(Stream stream, bool disposeStream)
new BytesDestination(), // or new StreamDestination
"width=3&height=2&mode=stretch&scale=both&format=webp&webp.quality=80")
.Finish().InProcessAsync();
Expand Down
2 changes: 2 additions & 0 deletions src/.idea/.idea.Imageflow.both/.idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/Imageflow.AllPlatforms/Imageflow.AllPlatforms.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<IsPackable>true</IsPackable>
<PackageIcon>icon.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>

<ItemGroup>
Expand Down
20 changes: 11 additions & 9 deletions src/Imageflow.AllPlatforms/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@
},
"Microsoft.IO.RecyclableMemoryStream": {
"type": "Transitive",
"resolved": "2.3.2",
"contentHash": "Oh1qXXFdJFcHozvb4H6XYLf2W0meZFuG0A+TfapFPj9z5fd4vxiARGEhAaLj/6XWQaMYIv4SH/9Q6H78Hw0E2Q==",
"resolved": "3.0.0",
"contentHash": "irv0HuqoH8Ig5i2fO+8dmDNdFdsrO+DoQcedwIlb810qpZHBNQHZLW7C/AHBQDgLLpw2T96vmMAy/aE4Yj55Sg==",
"dependencies": {
"System.Memory": "4.5.5"
}
Expand Down Expand Up @@ -116,7 +116,9 @@
"imageflow.net": {
"type": "Project",
"dependencies": {
"Microsoft.IO.RecyclableMemoryStream": "[2.*, 4.0.0)",
"Microsoft.IO.RecyclableMemoryStream": "[3.*, 4.0.0)",
"System.Buffers": "[4.*, )",
"System.Memory": "[4.*, )",
"System.Text.Json": "[6.*, )"
}
}
Expand Down Expand Up @@ -148,14 +150,14 @@
},
"Microsoft.NET.ILLink.Tasks": {
"type": "Direct",
"requested": "[8.0.1, )",
"resolved": "8.0.1",
"contentHash": "ADdJXuKNjwZDfBmybMnpvwd5CK3gp92WkWqqeQhW4W+q4MO3Qaa9QyW2DcFLAvCDMcCWxT5hRXqGdv13oon7nA=="
"requested": "[8.0.2, )",
"resolved": "8.0.2",
"contentHash": "hKTrehpfVzOhAz0mreaTAZgbz0DrMEbWq4n3hAo8Ks6WdxdqQhNPvzOqn9VygKuWf1bmxPdraqzTaXriO/sn0A=="
},
"Microsoft.IO.RecyclableMemoryStream": {
"type": "Transitive",
"resolved": "2.3.2",
"contentHash": "Oh1qXXFdJFcHozvb4H6XYLf2W0meZFuG0A+TfapFPj9z5fd4vxiARGEhAaLj/6XWQaMYIv4SH/9Q6H78Hw0E2Q=="
"resolved": "3.0.0",
"contentHash": "irv0HuqoH8Ig5i2fO+8dmDNdFdsrO+DoQcedwIlb810qpZHBNQHZLW7C/AHBQDgLLpw2T96vmMAy/aE4Yj55Sg=="
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
Expand All @@ -182,7 +184,7 @@
"imageflow.net": {
"type": "Project",
"dependencies": {
"Microsoft.IO.RecyclableMemoryStream": "[2.*, 4.0.0)",
"Microsoft.IO.RecyclableMemoryStream": "[3.*, 4.0.0)",
"System.Text.Json": "[6.*, )"
}
}
Expand Down
7 changes: 0 additions & 7 deletions src/Imageflow/Bindings/IAssertReady.cs

This file was deleted.

96 changes: 48 additions & 48 deletions src/Imageflow/Bindings/ImageInfo.cs
Original file line number Diff line number Diff line change
@@ -1,55 +1,55 @@
using System.Text.Json.Nodes;
using System.Text.Json.Nodes;

using Imageflow.Fluent;

namespace Imageflow.Bindings
namespace Imageflow.Bindings;

public class ImageInfo
{
public class ImageInfo
private ImageInfo(JsonNode imageInfo)
{
private ImageInfo(JsonNode imageInfo)
{
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(JsonNode imageInfo)
{
return new ImageInfo(imageInfo);
}

public PixelFormat FrameDecodesInto { get; private init; }
public long ImageWidth { get; private init; }
public long ImageHeight { get; private init; }
public string PreferredMimeType { get; private init; }
public string PreferredExtension { get; private init; }
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(JsonNode imageInfo)
{
return new ImageInfo(imageInfo);
}

public PixelFormat FrameDecodesInto { get; private init; }
public long ImageWidth { get; private init; }
public long ImageHeight { get; private init; }
public string PreferredMimeType { get; private init; }
public string PreferredExtension { get; private init; }

}
15 changes: 7 additions & 8 deletions src/Imageflow/Bindings/ImageflowAssertionFailed.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
namespace Imageflow.Bindings
{
/// <inheritdoc />
/// <summary>
/// For bugs
/// </summary>
public class ImageflowAssertionFailed(string message) : Exception(message);
}
namespace Imageflow.Bindings;

/// <inheritdoc />
/// <summary>
/// For bugs
/// </summary>
public class ImageflowAssertionFailed(string message) : Exception(message);
Loading

0 comments on commit 0d39641

Please sign in to comment.