diff --git a/contentapi.data/File/GetFileModify.cs b/contentapi.data/File/GetFileModify.cs index 32b11550..ad3f5e78 100644 --- a/contentapi.data/File/GetFileModify.cs +++ b/contentapi.data/File/GetFileModify.cs @@ -3,6 +3,7 @@ namespace contentapi.data; public class GetFileModify { public int size { get; set; } + public int maxSize { get; set; } public bool crop { get; set; } public bool freeze { get; set; } = false; } diff --git a/contentapi.sln b/contentapi.sln index 4ba88f69..1519af56 100644 --- a/contentapi.sln +++ b/contentapi.sln @@ -1,20 +1,19 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30114.105 +# Visual Studio Version 17 +VisualStudioVersion = 17.11.35222.181 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "contentapi", "contentapi\contentapi.csproj", "{762071EA-F0B2-4B21-81D3-B89CC7750F96}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "contentapi", "contentapi\contentapi.csproj", "{762071EA-F0B2-4B21-81D3-B89CC7750F96}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "contentapi.test", "contentapi.test\contentapi.test.csproj", "{09193632-DC79-44F4-BED2-063CFF0961CD}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "contentapi.test", "contentapi.test\contentapi.test.csproj", "{09193632-DC79-44F4-BED2-063CFF0961CD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "contentapi.data", "contentapi.data\contentapi.data.csproj", "{2A8B442A-3C59-4431-8F82-DAB1612D6092}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {762071EA-F0B2-4B21-81D3-B89CC7750F96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {762071EA-F0B2-4B21-81D3-B89CC7750F96}.Debug|Any CPU.Build.0 = Debug|Any CPU @@ -24,5 +23,12 @@ Global {09193632-DC79-44F4-BED2-063CFF0961CD}.Debug|Any CPU.Build.0 = Debug|Any CPU {09193632-DC79-44F4-BED2-063CFF0961CD}.Release|Any CPU.ActiveCfg = Release|Any CPU {09193632-DC79-44F4-BED2-063CFF0961CD}.Release|Any CPU.Build.0 = Release|Any CPU + {2A8B442A-3C59-4431-8F82-DAB1612D6092}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2A8B442A-3C59-4431-8F82-DAB1612D6092}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A8B442A-3C59-4431-8F82-DAB1612D6092}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A8B442A-3C59-4431-8F82-DAB1612D6092}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE EndGlobalSection EndGlobal diff --git a/contentapi/Main/File/FileService.cs b/contentapi/Main/File/FileService.cs index 566cf691..15c7edfa 100644 --- a/contentapi/Main/File/FileService.cs +++ b/contentapi/Main/File/FileService.cs @@ -163,6 +163,8 @@ public string GetThumbnailPath(string hash, GetFileModify? modify = null) if (modify.size > 0) extraFolder += $"{modify.size}"; + if (modify.maxSize > 0) + extraFolder += $"m{modify.maxSize}"; if (modify.crop) extraFolder += "a"; if (modify.freeze) @@ -362,17 +364,11 @@ protected async Task> TryQuantize(int quantize, ContentView new public async Task> GetFileAsync(string hash, GetFileModify modify) { - if (modify.size > 0) - { - if (modify.size < 10) - throw new RequestException("Requested file size too small!"); - else if (modify.size <= 100) - modify.size = 10 * (modify.size / 10); - else if (modify.size <= 1000) - modify.size = 100 * (modify.size / 100); - else - throw new RequestException("Requested file size too large!"); - } + modify.size = SizeConstraint(modify.size); + modify.maxSize = SizeConstraint(modify.maxSize); + + if (modify.size > 0 && modify.maxSize > 0) + throw new RequestException("Cannot specify both size and maxSize!"); //Go get that ONE file. This should return null if we can't read it... let's hope! //SPECIAL: the 0 file is @@ -450,4 +446,21 @@ public async Task GetThumbnailAsync(string hash, string thumbnailPath, G return await System.IO.File.ReadAllBytesAsync(thumbnailPath); } + + private static int SizeConstraint(int size) + { + if (size > 0) + { + if (size < 10) + throw new RequestException("Requested file size too small!"); + else if (size <= 100) + return 10 * (size / 10); + else if (size <= 1000) + return 100 * (size / 100); + else + throw new RequestException("Requested file size too large!"); + } + + return size; + } } \ No newline at end of file diff --git a/contentapi/Utilities/Image/ImageManipulator_Direct.cs b/contentapi/Utilities/Image/ImageManipulator_Direct.cs index ee636f42..fa23d1d5 100644 --- a/contentapi/Utilities/Image/ImageManipulator_Direct.cs +++ b/contentapi/Utilities/Image/ImageManipulator_Direct.cs @@ -145,9 +145,6 @@ await Task.Run(async () => result.RenderCount++; } - //This must come after the crop! - var isNowLarger = (modify.size > Math.Max(image.Width, image.Height)); - //Saving as png also works, but this preserves the format (even if it's a little heavier compute, it's only a one time thing) if (modify.freeze && isGif) { @@ -156,8 +153,19 @@ await Task.Run(async () => result.RenderCount++; } - if (modify.size > 0 && !(isGif && isNowLarger)) //&& (modify.size > image.Width || modify.size > image.Height))) + // this is to catch the fact that we don't want to resize gifs + if (isGif) + { } + // check to make sure you don't set both + else if (modify.size > 0 && modify.maxSize > 0) + { + throw new RequestException("Cannot have both size and maxSize!"); + } + // size + else if (modify.size > 0) //&& (modify.size > image.Width || modify.size > image.Height))) { + var sizeIsLarger = (modify.size > Math.Max(image.Width, image.Height)); + var width = 0; var height = 0; @@ -168,12 +176,32 @@ await Task.Run(async () => height = modify.size; if (HighQualityResize) - image.Mutate(x => x.Resize(width, height, isNowLarger ? KnownResamplers.Spline : KnownResamplers.Lanczos3)); + image.Mutate(x => x.Resize(width, height, sizeIsLarger ? KnownResamplers.Spline : KnownResamplers.Lanczos3)); else image.Mutate(x => x.Resize(width, height)); result.RenderCount++; } + // maxSize: only resize if the image is larger than the max size + else if (modify.maxSize > 0 && modify.maxSize < Math.Max(image.Width, image.Height)) + { + var width = 0; + var height = 0; + + //Preserve aspect ratio when not square + if (image.Width > image.Height) + width = modify.maxSize; + else + height = modify.maxSize; + + if (HighQualityResize) + image.Mutate(x => x.Resize(width, height, KnownResamplers.Lanczos3)); + else + image.Mutate(x => x.Resize(width, height)); + + result.RenderCount++; + + } result.Width = image.Width; result.Height = image.Height; diff --git a/contentapi/Utilities/Image/ImageManipulator_IMagick.cs b/contentapi/Utilities/Image/ImageManipulator_IMagick.cs index 7bf14702..64d1124c 100644 --- a/contentapi/Utilities/Image/ImageManipulator_IMagick.cs +++ b/contentapi/Utilities/Image/ImageManipulator_IMagick.cs @@ -137,8 +137,16 @@ public async Task GeneralIMagickResize(string filename, ImageManipulationInfo ba var arglist = new List() { filename + (baseInfo.MimeType == Constants.GifMime && !modify.freeze ? "" : "[0]") }; + if (modify.size > 0 && modify.maxSize > 0) + throw new RequestException("Can't specify both size and maxSize in the same request!"); + + var size = modify.size > 0 ? modify.size : modify.maxSize; + //Cropping can be done with the resize arg, add ^ to the end - var resize = $"{modify.size}x{modify.size}"; + var resize = $"{size}x{size}"; + + if (modify.maxSize > 0) + resize += ">"; if(modify.crop) resize += "^"; @@ -154,7 +162,7 @@ public async Task GeneralIMagickResize(string filename, ImageManipulationInfo ba } if(modify.crop) - arglist.AddRange(new [] { "-background", "none", "-gravity", "center", "-extent", $"{modify.size}x{modify.size}"}); + arglist.AddRange(new [] { "-background", "none", "-gravity", "center", "-extent", $"{size}x{size}"}); if(baseInfo.MimeType == Constants.GifMime && !modify.freeze) {