问题描述
请原谅我可能“想得太多了”,但我通常用 C 和 C++ 等编程。
我的任务是在 .NET 5 中编写一个 jpg resizer。
它需要“从本地磁盘读取”有问题的 .jpg (s) 并将宽度更改为 600 像素(以及相对于宽度的高度)。
宽度最初可以更高或更低,但无论如何都会转换为 600px。
我决定使用看起来不错的库“ImageSharp”,但由于这些项目中的大多数文档都相当缺乏,并且只展示了简单的示例(大多数与现实世界无关。)
简而言之,我正在迭代大量的 .jpg 文件,这些文件很大(大小)。
我的问题是“这是正确的做法吗?”,在此过程中不会占用大量内存。如果不仔细检查源代码,就不清楚“Image.Load”在做什么。 (是用整个图像填充内存还是分部分流式传输?)。
这是基于 Web 的应用程序的后端(在实际应用程序中,排队的不需要即时响应服务)。
这是我的测试代码:
using System.IO;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
namespace ImagePlay
{
class Program
{
static void Main(string[] args)
{
ResizeImages();
}
static void ResizeImages()
{
int resizedImageWidth = 600;
// START LOOP OVER ALL A LOT OF LARGE IMAGES TO CONVERT.
// IS THIS STREAMING THE FILES OR IS IT TAKING UP LOTS OF MEMORY????
// WHAT HAPPENS IF THIS FILE (and every other error) DOESNT EXIST.
// ALSO notinG THE NEW VERSIONS OF (.NET 5 in this case march 2021) DO NOT NEED THE
// BRACKETS AROUND THE USING (maybe they do in a loop?).
using Image image = Image.Load(Path.Combine(@"C:\some_folder","one.jpg"));
// Resize the image.
image.Mutate(x => x.Resize(resizedImageWidth,0));
image.Save(Path.Combine(@"C:\some_other_folder","one_new.jpg"));
// END LOOP OVER ALL THE IMAGES TO CONVERT.
}
}
}
解决方法
来自您的代码示例。
// The image is fully decoded into a pooled buffer (defaulting to Rgba32).
// You can choose your own pixel format by using the generic Image<TPixel> type.
// The underlying filestream will throw a FileNotFoundException if the file is missing
// (see FileStream docs for other possible exceptions).
// The decoder will throw an UnknownImageFormatException if the file is misnamed and not actually a valid,supported image file.
// The decoder will throw an InvalidImageContentException if the image contains invalid
// data not conforming to the specification.
using Image image = Image.Load(Path.Combine(@"C:\some_folder","one.jpg"));
// Resize the image.
// This is performed using a sliding window to reduce memory pressure to a max of 1MB.
// The original buffer is returned to the memory pool and a new one is rented.
// Any errors (incredibly unlikely) are thrown as the type ImageProcessingException.
image.Mutate(x => x.Resize(resizedImageWidth,0));
// The image is encoded and the allocated memory returned to the memory pool at the end of
// the using declaration (not statement,they're different things) container scope.
// In a loop this is scoped to the loop action.
image.Save(Path.Combine(@"C:\some_other_folder","one_new.jpg"));
异常类型记录在 API docs
内存池在 Conceptual Docs
中讨论整个操作得到 SIMD 硬件内在函数的大力支持,因此与本机等效项相比运行得非常好。
如果您生成图像用于显示目的,最好使用 ImageSharp.Web 中间件按需调整和缓存每个图像。