Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
JackLewis-digirati committed Mar 26, 2024
1 parent 90492d6 commit c4faa62
Show file tree
Hide file tree
Showing 38 changed files with 1,351 additions and 665 deletions.
8 changes: 8 additions & 0 deletions src/protagonist/DLCS.Core/FileSystem/FileSystem.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace DLCS.Core.FileSystem;

Expand Down Expand Up @@ -45,4 +47,10 @@ public long GetFileSize(string path)
}

public void SetLastWriteTimeUtc(string path, DateTime dateTime) => File.SetLastWriteTimeUtc(path, dateTime);

public async Task CreateFileFromStream(string path, Stream stream, CancellationToken cancellationToken = default)
{
await using var fileStream = new FileStream(path, FileMode.Create);
await stream.CopyToAsync(fileStream, cancellationToken);
}
}
4 changes: 4 additions & 0 deletions src/protagonist/DLCS.Core/FileSystem/IFileSystem.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace DLCS.Core.FileSystem;

Expand All @@ -14,4 +17,5 @@ public interface IFileSystem
bool FileExists(string path);
long GetFileSize(string path);
void SetLastWriteTimeUtc(string path, DateTime dateTime);
Task CreateFileFromStream(string path, Stream stream, CancellationToken cancellationToken = default);
}
134 changes: 90 additions & 44 deletions src/protagonist/DLCS.Model.Tests/Assets/AssetXTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,23 @@ public class AssetXTests
public void GetAvailableThumbSizes_IncludeUnavailable_Correct_MaxUnauthorisedNoRoles()
{
// Arrange
var thumbnailPolicy = new ThumbnailPolicy
{
Id = "TestPolicy",
Name = "TestPolicy",
Sizes = "800,400,200,100"
var asset = new Asset {Width = 5000, Height = 2500, MaxUnauthorised = 500,
ImageDeliveryChannels = new List<ImageDeliveryChannel>
{
new()
{
DeliveryChannelPolicyId = 1,
Channel = AssetDeliveryChannels.Thumbnails,
DeliveryChannelPolicy = new DeliveryChannelPolicy
{
PolicyData = "[\"800,800\",\"400,400\",\"200,200\",\"100,100\"]"
}
}
}
};

var asset = new Asset {Width = 5000, Height = 2500, MaxUnauthorised = 500};

// Act
var sizes = asset.GetAvailableThumbSizes(thumbnailPolicy, out var maxDimensions, true);
var sizes = asset.GetAvailableThumbSizes(out var maxDimensions, true);

// Assert
sizes.Should().BeEquivalentTo(new List<Size>
Expand All @@ -43,17 +49,25 @@ public void GetAvailableThumbSizes_IncludeUnavailable_Correct_MaxUnauthorisedNoR
public void GetAvailableThumbSizes_NotIncludeUnavailable_Correct_MaxUnauthorisedNoRoles()
{
// Arrange
var thumbnailPolicy = new ThumbnailPolicy
var asset = new Asset
{
Id = "TestPolicy",
Name = "TestPolicy",
Sizes = "800,400,200,100"
Width = 5000, Height = 2500, MaxUnauthorised = 500,
ImageDeliveryChannels = new List<ImageDeliveryChannel>
{
new()
{
DeliveryChannelPolicyId = 1,
Channel = AssetDeliveryChannels.Thumbnails,
DeliveryChannelPolicy = new DeliveryChannelPolicy
{
PolicyData = "[\"800,800\",\"400,400\",\"200,200\",\"100,100\"]"
}
}
}
};

var asset = new Asset {Width = 5000, Height = 2500, MaxUnauthorised = 500};

// Act
var sizes = asset.GetAvailableThumbSizes(thumbnailPolicy, out var maxDimensions, false);
var sizes = asset.GetAvailableThumbSizes(out var maxDimensions, false);

// Assert
sizes.Should().BeEquivalentTo(new List<Size>
Expand All @@ -71,17 +85,25 @@ public void GetAvailableThumbSizes_NotIncludeUnavailable_Correct_MaxUnauthorised
public void GetAvailableThumbSizes_IncludeUnavailable_Correct_IfRolesNoMaxUnauthorised()
{
// Arrange
var thumbnailPolicy = new ThumbnailPolicy
var asset = new Asset
{
Id = "TestPolicy",
Name = "TestPolicy",
Sizes = "800,400,200,100",
Width = 5000, Height = 2500, Roles = "GoodGuys", MaxUnauthorised = -1,
ImageDeliveryChannels = new List<ImageDeliveryChannel>
{
new()
{
DeliveryChannelPolicyId = 1,
Channel = AssetDeliveryChannels.Thumbnails,
DeliveryChannelPolicy = new DeliveryChannelPolicy
{
PolicyData = "[\"800,800\",\"400,400\",\"200,200\",\"100,100\"]"
}
}
}
};

var asset = new Asset {Width = 5000, Height = 2500, Roles = "GoodGuys", MaxUnauthorised = -1};

// Act
var sizes = asset.GetAvailableThumbSizes(thumbnailPolicy, out var maxDimensions, true);
var sizes = asset.GetAvailableThumbSizes(out var maxDimensions, true);

// Assert
sizes.Should().BeEquivalentTo(new List<Size>
Expand Down Expand Up @@ -110,7 +132,7 @@ public void GetAvailableThumbSizes_NotIncludeUnavailable_Correct_IfRolesNoMaxUna
var asset = new Asset {Width = 5000, Height = 2500, Roles = "GoodGuys", MaxUnauthorised = -1};

// Act
var sizes = asset.GetAvailableThumbSizes(thumbnailPolicy, out var maxDimensions, false);
var sizes = asset.GetAvailableThumbSizes(out var maxDimensions, false);

// Assert
sizes.Should().BeNullOrEmpty();
Expand All @@ -123,17 +145,25 @@ public void GetAvailableThumbSizes_NotIncludeUnavailable_Correct_IfRolesNoMaxUna
public void GetAvailableThumbSizes_RestrictsAvailableSizes_IfHasRolesAndMaxUnauthorised()
{
// Arrange
var thumbnailPolicy = new ThumbnailPolicy
var asset = new Asset
{
Id = "TestPolicy",
Name = "TestPolicy",
Sizes = "800,400,200,100",
Width = 2500, Height = 5000, Roles = "GoodGuys", MaxUnauthorised = 399,
ImageDeliveryChannels = new List<ImageDeliveryChannel>
{
new()
{
DeliveryChannelPolicyId = 1,
Channel = AssetDeliveryChannels.Thumbnails,
DeliveryChannelPolicy = new DeliveryChannelPolicy
{
PolicyData = "[\"800,800\",\"400,400\",\"200,200\",\"100,100\"]"
}
}
}
};

var asset = new Asset {Width = 2500, Height = 5000, Roles = "GoodGuys", MaxUnauthorised = 399};

// Act
var sizes = asset.GetAvailableThumbSizes(thumbnailPolicy, out var maxDimensions);
var sizes = asset.GetAvailableThumbSizes(out var maxDimensions);

// Assert
sizes.Should().BeEquivalentTo(new List<Size>
Expand All @@ -150,17 +180,25 @@ public void GetAvailableThumbSizes_RestrictsAvailableSizes_IfHasRolesAndMaxUnaut
public void GetAvailableThumbSizes_ReturnsAvailableAndUnavailableSizes_ButReturnsMaxDimensionsOfAvailableOnly_IfIncludeUnavailable()
{
// Arrange
var thumbnailPolicy = new ThumbnailPolicy
var asset = new Asset
{
Id = "TestPolicy",
Name = "TestPolicy",
Sizes = "800,400,200,100",
Width = 2500, Height = 5000, Roles = "GoodGuys", MaxUnauthorised = 399,
ImageDeliveryChannels = new List<ImageDeliveryChannel>
{
new()
{
DeliveryChannelPolicyId = 1,
Channel = AssetDeliveryChannels.Thumbnails,
DeliveryChannelPolicy = new DeliveryChannelPolicy
{
PolicyData = "[\"800,800\",\"400,400\",\"200,200\",\"100,100\"]"
}
}
}
};

var asset = new Asset {Width = 2500, Height = 5000, Roles = "GoodGuys", MaxUnauthorised = 399};

// Act
var sizes = asset.GetAvailableThumbSizes(thumbnailPolicy, out var maxDimensions, true);
var sizes = asset.GetAvailableThumbSizes(out var maxDimensions, true);

// Assert
sizes.Should().BeEquivalentTo(new List<Size>
Expand All @@ -179,17 +217,25 @@ public void GetAvailableThumbSizes_ReturnsAvailableAndUnavailableSizes_ButReturn
public void GetAvailableThumbSizes_HandlesImageBeingSmallerThanThumbnail()
{
// Arrange
var thumbnailPolicy = new ThumbnailPolicy
var asset = new Asset
{
Id = "TestPolicy",
Name = "TestPolicy",
Sizes = "800,400,200,100"
Width = 300, Height = 150,
ImageDeliveryChannels = new List<ImageDeliveryChannel>
{
new()
{
DeliveryChannelPolicyId = 1,
Channel = AssetDeliveryChannels.Thumbnails,
DeliveryChannelPolicy = new DeliveryChannelPolicy
{
PolicyData = "[\"800,800\",\"400,400\",\"200,200\",\"100,100\"]"
}
}
}
};

var asset = new Asset { Width = 300, Height = 150 };

// Act
var sizes = asset.GetAvailableThumbSizes(thumbnailPolicy, out var maxDimensions, true);
var sizes = asset.GetAvailableThumbSizes(out var maxDimensions, true);

// Assert
sizes.Should().BeEquivalentTo(new List<Size>
Expand Down
10 changes: 1 addition & 9 deletions src/protagonist/DLCS.Model/Assets/Asset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,15 +124,7 @@ public Asset(AssetId assetId)
Customer = assetId.Customer;
Space = assetId.Space;
}

public Asset WithThumbnailPolicy(ThumbnailPolicy? thumbnailPolicy)
{
FullThumbnailPolicy = Family == AssetFamily.Image
? thumbnailPolicy.ThrowIfNull(nameof(thumbnailPolicy))
: thumbnailPolicy;
return this;
}


public Asset WithImageOptimisationPolicy(ImageOptimisationPolicy imageOptimisationPolicy)
{
FullImageOptimisationPolicy = imageOptimisationPolicy.ThrowIfNull(nameof(imageOptimisationPolicy));
Expand Down
64 changes: 52 additions & 12 deletions src/protagonist/DLCS.Model/Assets/AssetX.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using DLCS.Core.Guard;
using DLCS.Model.Policies;
using IIIF;
using IIIF.ImageApi;

namespace DLCS.Model.Assets;

Expand All @@ -11,23 +13,50 @@ namespace DLCS.Model.Assets;
/// </summary>
public static class AssetX
{
public static List<Size> GetAllThumbSizes(this Asset asset)
{
var thumbnailSizes = new List<Size>();

if (asset.HasDeliveryChannel(AssetDeliveryChannels.Thumbnails))
{
var initialPolicyTransformation = JsonSerializer.Deserialize<List<string>>(asset.ImageDeliveryChannels
.Single(
x => x.Channel == AssetDeliveryChannels.Thumbnails)
.DeliveryChannelPolicy.PolicyData);

foreach (var sizeValue in initialPolicyTransformation!)
{
var sizeParameter = SizeParameter.Parse(sizeValue);

thumbnailSizes.Add(new Size(sizeParameter.Width.Value, sizeParameter.Height.Value));
}
}

return thumbnailSizes;
}

/// <summary>
/// Get a list of all available thumbnail sizes for asset, based on thumbnail policy.
/// </summary>
/// <param name="asset">Asset to extract thumbnails sizes for.</param>
/// <param name="thumbnailPolicy">The thumbnail policy to use to calculate thumb sizes.</param>
/// <param name="maxDimensions">A tuple of maxBoundedSize, maxAvailableWidth and maxAvailableHeight.</param>
/// <param name="includeUnavailable">Whether to include unavailable sizes or not.</param>
/// <returns>List of available thumbnail <see cref="Size"/></returns>
public static List<Size> GetAvailableThumbSizes(this Asset asset, ThumbnailPolicy thumbnailPolicy,
public static List<Size> GetAvailableThumbSizes(this Asset asset,
out (int maxBoundedSize, int maxAvailableWidth, int maxAvailableHeight) maxDimensions,
bool includeUnavailable = false)
{
var initialPolicyTransformation = JsonSerializer.Deserialize<List<string>>(asset.ImageDeliveryChannels.Single(
x => x.Channel == AssetDeliveryChannels.Thumbnails)
.DeliveryChannelPolicy.PolicyData);

var thumbnailPolicy = initialPolicyTransformation!.Select(SizeParameter.Parse).ToList();

asset.ThrowIfNull(nameof(asset));
thumbnailPolicy.ThrowIfNull(nameof(thumbnailPolicy));

var availableSizes = new List<Size>(thumbnailPolicy.SizeList.Count);
var generatedMax = new List<int>(thumbnailPolicy.SizeList.Count);
var availableSizes = new List<Size>(thumbnailPolicy.Count);
var generatedMax = new List<int>(thumbnailPolicy.Count);

var size = new Size(asset.Width.ThrowIfNull(nameof(asset.Width)),
asset.Height.ThrowIfNull(nameof(asset.Height)));
Expand All @@ -36,23 +65,34 @@ public static class AssetX
int maxAvailableWidth = 0;
int maxAvailableHeight = 0;

foreach (int boundingSize in thumbnailPolicy.SizeList)
foreach (var boundingSize in thumbnailPolicy)
{
var assetIsUnavailableForSize = AssetIsUnavailableForSize(asset, boundingSize);
int maxDimension = boundingSize.Width > boundingSize.Height ?
boundingSize.Width.Value : boundingSize.Height.Value;

var assetIsUnavailableForSize = AssetIsUnavailableForSize(asset, maxDimension);
if (!includeUnavailable && assetIsUnavailableForSize) continue;
Size bounded;

Size bounded = Size.Confine(boundingSize, size);

var boundedMaxDimension = bounded.MaxDimension;
if (asset.HasDeliveryChannel(AssetDeliveryChannels.Image) && size.MaxDimension == 0)
{
bounded = Size.Confine(maxDimension, new Size(boundingSize.Width!.Value, boundingSize.Height.Value));
}
else
{
bounded = Size.Confine(maxDimension, size);
}

var boundedMaxDimension = bounded.MaxDimension;

// If image < thumb-size then boundedMax may already have been processed (it'll be the same as imageMax)
if (generatedMax.Contains(boundedMaxDimension)) continue;

generatedMax.Add(boundedMaxDimension);
availableSizes.Add(bounded);
if (boundingSize > maxBoundedSize && !assetIsUnavailableForSize)
if (maxDimension > maxBoundedSize && !assetIsUnavailableForSize)
{
maxBoundedSize = Math.Min(boundingSize, boundedMaxDimension); // handles image being smaller than thumb
maxBoundedSize = Math.Min(maxDimension, boundedMaxDimension); // handles image being smaller than thumb
maxAvailableWidth = bounded.Width;
maxAvailableHeight = bounded.Height;
}
Expand Down
Loading

0 comments on commit c4faa62

Please sign in to comment.