.NET 5 ImageSharp 调整大小的 jpg (s) 大列表

问题描述

请原谅我可能“想得太多了”,但我通常用 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 中间件按需调整和缓存每个图像。