[英]Shrink image file using ImageSharp
我需要縮小我得到的每張超過 10MB 的圖像。 文件類型為 png、jpg 和 gif。 我看到 ImageSharp 有一個調整圖像大小的選項:
Resize(new ResizeOptions
{
Mode = ResizeMode.Max,
Size = new Size(maxFileSize)
}
我看到了很多使用帶有寬度和高度的 resize 函數的例子,但沒有一個使用這個單一尺寸選項,也沒有文檔解釋“尺寸”的確切含義。
我嘗試了以下方法:使用maxFileSize=1024
縮小 22.2MB 的圖像產生了 527.9MB 的圖片。 使用maxFileSize=1024*2*10
“縮小”相同的圖像產生了 47.4MB 的圖片。
如何將圖像縮小到大約 10MB(可以小一點)? 我的目標是限制為 10MB,如果超過,則將圖像減小到 10MB 以下的最大可能大小而不影響比率。
我不認為有一種簡單(可靠)的方法來計算圖像的壓縮大小,而不是壓縮它。
雖然 ImageSharp 似乎沒有為此提供本機 API,但我們可以使用現有功能來找到滿足我們約束的最佳大小。
主意:
對應的C#代碼:
// 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
。
其他常量定義如下:
ESTIMATED_MINIMUM_WIDTH
:完美圖像寬度的估計下限。 圖像永遠不會比這更小。 應該至少為0
。ESTIMATED_MAXIMUM_WIDTH
:完美圖像寬度的估計上限。 圖像永遠不會變得比這更大。 最多應該是image.Width
。MAXIMUM_HEIGHT
:最大圖像高度。 如果除了文件大小之外還有其他限制(例如,圖像必須適合特定的屏幕大小),這會很有幫助; 否則,這可以簡單地設置為image.Height
。 雖然二分搜索提供了良好的算法復雜度,但對於非常大的圖像,這仍然很慢。 如果時間很重要(問題沒有具體說明這一點),可以通過對bestWidth
的上限和下限使用良好的初始估計來提高性能,例如,通過像素與字節的比率線性插值文件大小。
在查看更多文檔后,我現在看到單個 int 構造函數只是將相同的數字插入寬度和高度。
現在,我使用以下方法過度縮小圖像:
using (var image = Image.Load(imageFile))
{
var proportion = (double)imageFile.Length / maxFileSize;
var maxWidth = (int)(image.Width / proportion);
var maxHeight = (int)(image.Height / proportion);
image.Mutate(x => x
.Resize(new ResizeOptions
{
Mode = ResizeMode.Max,
Size = new Size(maxWidth, maxHeight)
}));
// Save the Image
}
如果有人有更好的想法,我很樂意聽到。
目標是將圖像縮小到略低於 10MB(盡可能接近)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.