使用ImageSharp缩小图像文件 [英] Shrink image file using ImageSharp

查看:197
本文介绍了使用ImageSharp缩小图像文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要缩小每张超过10MB的图像.文件类型为png,jpg和gif.我看到ImageSharp可以调整图像大小:

I need to shrink every image I get that is more than 10MB. File types are png, jpg and gif. I saw that ImageSharp has an option to resize an image:

Resize(new ResizeOptions
{
    Mode = ResizeMode.Max,
    Size = new Size(maxFileSize)
}

我看到了很多使用带有宽度和高度的resize函数的示例,但是没有一个使用此size选项,也没有文档确切解释"size"是什么.手段.

I saw a lot of examples using the resize function with width and height, but none using this one size option, and no documentation explain exactly what "size" means.

我尝试了以下操作:使用 maxFileSize = 1024 缩小22.2MB的图像会产生527.9MB的图像.收缩" maxFileSize = 1024 * 2 * 10 的同一张图片产生了47.4MB的图片.

I've tried the following: Shrinking an image of 22.2MB using maxFileSize=1024 yielded a picture of 527.9MB. "Shrinking" the same image with maxFileSize=1024*2*10 yielded a 47.4MB picture.

如何将图像缩小到大约10MB(可能少一点)?我的目标是将大小限制为10MB,如果超出限制,则在不影响比率的情况下将图像减小到最大10MB以下.

How can I shrink an image to a size of roughly 10MB (can be a bit less)? My goal here is to limit to 10MB, and, if exceeded, reduce the image to the maximal possible size under 10MB without affecting the ratio.

推荐答案

我认为没有一种简单(可靠)的方法来计算图像的压缩大小,而无需对其进行压缩.

I don't think that there is an easy (and reliable) way to compute the compressed size of an image, without, well, compressing it.

尽管ImageSharp似乎没有为此提供本机API,但我们可以使用现有功能来找到满足我们要求的最佳尺寸.

While ImageSharp doesn't seem to offer a native API for this, we can use existing functionality to find an optimal size which satisfies our constraints.

想法:

  1. 我们可以假设较小的图像在磁盘上占用的空间较小,即文件大小与像素数相关.对于某些非常相似的图像大小,某些复杂的压缩算法可能无法使用 ;但是,即使那样,我们仍然应该能够找到理想的图像尺寸估计值.
  2. 为图像尺寸选择一些粗略的上下限.在最佳情况下,我们的理想图像尺寸介于两者之间.
  3. 通过重复调整大小和压缩图像,直到达到所需的文件大小,在上述范围之间进行二进制搜索.
  1. We can assume that smaller images take less space on disk, i.e., the file size is correlated with the number of pixels. This may not hold for some sophisticated compression algorithms on very similar image sizes; however, even then we should still able to find a good estimation for the perfect image size.
  2. Pick some rough lower and upper bounds for the image size. In the best case, our perfect image size lays somewhere in between.
  3. Perform a binary search between the aforementioned bounds, by repeatedly resizing and compressing our image, until it has our desired file size.


对应的C#代码:


Corresponding C# code:

// Load original image
using Image image = Image.Load("image.jpg");

// Configure encoder
var imageEncoder = new JpegEncoder
{
    Quality = 95,
    Subsample = JpegSubsample.Ratio420
};

// Resize image, until it fits the desired file size and bounds
int min = ESTIMATED_MINIMUM_WIDTH;
int max = ESTIMATED_MAXIMUM_WIDTH;
int bestWidth = min;
using var tmpStream = new MemoryStream();
while(min <= max)
{
    // Resize image
    int width = (min + max) / 2;
    using var resizedImage = image.Clone(op =>
    {
        op.Resize(new ResizeOptions
        {
            Mode = ResizeMode.Max,
            Size = new Size(width, MAXIMUM_HEIGHT)
        });
    });

    // Compress image
    tmpStream.SetLength(0);
    resizedImage.Save(tmpStream, imageEncoder);

    // Check file size of resized image
    if(tmpStream.Position < MAXIMUM_FILE_SIZE)
    {
        // The current width satisfies the size constraint
        bestWidth = width;

        // Try to make image bigger again
        min = width + 1;
    }
    else
    {
        // Image is still too large, continue shrinking
        max = width - 1;
    }
}

// Resize and store final image
image.Mutate(op =>
{
    op.Resize(new ResizeOptions
    {
        Mode = ResizeMode.Max,
        Size = new Size(bestWidth, MAXIMUM_HEIGHT)
    });
});

// Store resized image
image.Save("image-resized.jpg", imageEncoder);

这会将图像"image.jpg"加载到并找到宽度 bestWidth ,该宽度产生的文件大小小于但接近 MAXIMUM_FILE_SIZE .

This loads the image "image.jpg" and finds the width bestWidth which yields a file size smaller than, but near to MAXIMUM_FILE_SIZE.

其他常量定义如下:

  • ESTIMATED_MINIMUM_WIDTH :理想图像宽度的估计下限.图像将永远不会小于此.应该至少为 0 .
  • ESTIMATED_MAXIMUM_WIDTH :完美图像宽度的估计上限.图像将永远不会变得比这个更大.最多应为 image.Width .
  • MAXIMUM_HEIGHT :最大图像高度.如果文件大小以外还有其他限制(例如,图像必须适合特定的屏幕大小),这将很有帮助;否则,可以将其简单地设置为 image.Height .
  • ESTIMATED_MINIMUM_WIDTH: The estimated lower bound for the perfect image width. The image will never become smaller than this. Should be at least 0.
  • ESTIMATED_MAXIMUM_WIDTH: The estimated upper bound for the perfect image width. The image will never become larger than this. Should be at most image.Width.
  • MAXIMUM_HEIGHT: The maximum image height. This is helpful if there are other constraints than the file size (e.g., the image must fit a certain screen size); else, this can be simply set to image.Height.

尽管二进制搜索提供了良好的算法复杂性,但对于非常大的图像而言,这仍然可能相当慢.如果时间很重要(问题未指明这一点),则可以通过对 bestWidth 的上限和下限进行良好的初始估算来提高性能,例如,通过像素与字节之比.

While binary search offers good algorithmic complexity, this can still be quite slow for very large images. If time is important (the question doesn't specify this), the performance can be improved by using good initial estimations of the upper and lower bounds for bestWidth, e.g., by linearly interpolating the file size through the ratio of pixels to bytes.

这篇关于使用ImageSharp缩小图像文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆