我试图找出答案,但我做不到。
例如,一张图像241x76
总共有18,316 pixels (241 * 76)
. 调整大小的规则是,像素数量不能通过10,000
。那么,我怎样才能获得保持纵横比并小于10,000
像素的新尺寸?
我试图找出答案,但我做不到。
例如,一张图像241x76
总共有18,316 pixels (241 * 76)
. 调整大小的规则是,像素数量不能通过10,000
。那么,我怎样才能获得保持纵横比并小于10,000
像素的新尺寸?
伪代码:
pixels = width * height
if (pixels > 10000) then
ratio = width / height
scale = sqrt(pixels / 10000)
height2 = floor(height / scale)
width2 = floor(ratio * height / scale)
ASSERT width2 * height2 <= 10000
end if
ratio
请记住对涉及和实施时的所有计算使用浮点数学scale
。
Python
import math
def capDimensions(width, height, maxPixels=10000):
pixels = width * height
if (pixels <= maxPixels):
return (width, height)
ratio = float(width) / height
scale = math.sqrt(float(pixels) / maxPixels)
height2 = int(float(height) / scale)
width2 = int(ratio * height / scale)
return (width2, height2)
C# 中的一个替代函数,它接受并返回一个Image
对象:
using System.Drawing.Drawing2D;
public Image resizeMaxPixels(int maxPixelCount, Image originalImg)
{
Double pixelCount = originalImg.Width * originalImg.Height;
if (pixelCount < maxPixelCount) //no downsize needed
{
return originalImg;
}
else
{
//EDIT: not actually needed - scaleRatio takes care of this
//Double aspectRatio = originalImg.Width / originalImg.Height;
//scale varies as the square root of the ratio (width x height):
Double scaleRatio = Math.Sqrt(maxPixelCount / pixelCount);
Int32 newWidth = (Int32)(originalImg.Width * scaleRatio);
Int32 newHeight = (Int32)(originalImg.Height * scaleRatio);
Bitmap newImg = new Bitmap(newWidth, newHeight);
//this keeps the quality as good as possible when resizing
using (Graphics gr = Graphics.FromImage(newImg))
{
gr.SmoothingMode = SmoothingMode.AntiAlias;
gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
gr.DrawImage(originalImg, new Rectangle(0, 0, newWidth, newHeight));
}
return newImg;
}
}
使用 Resizing an Image 的答案中的图形代码而不损失任何质量
编辑:计算纵横比实际上在这里无关紧要,因为我们已经通过总像素比的(平方根)来缩放宽度和高度。您可以使用它来计算newWidth
基于newHeight
(或反之亦然),但这不是必需的。
Deestan 的代码适用于方形图像,但在纵横比不同于 1 的情况下,平方根将不起作用。您需要将比例缩放到纵横比除以 2 的幂。
观察(Python):
def capDimensions(width, height, maxPixels):
pixels = width * height
if (pixels <= maxPixels):
return (width, height)
ratio = float(width) / height
scale = (float(pixels) / maxPixels)**(width/(height*2))
height2 = round(float(height) / scale)
width2 = round(ratio * height2)
return (width2, height2)
让我们比较一下结果。
初始尺寸:450x600 初始像素:270000
我正在尝试调整大小以尽可能接近119850像素。
使用 Deestan 的算法:capDimensions:300x400 调整大小的像素:67500
使用修改后的算法:capDimensions。332x442 调整大小的像素:82668
这就是我今天下午想出的,同时试图自己解决数学问题,为了好玩。我的代码似乎运行良好,我测试了几种不同形状和大小的图像。确保使用浮点变量,否则数学会中断。
orig_width=1920
orig_height=1080
orig_pixels=(orig_width * orig_height)
max_pixels=180000
if (orig_pixels <= max_pixels) {
# use original image
}
else {
# scale image down
ratio=sqrt(orig_pixels / max_pixels)
new_width=floor(orig_width / ratio)
new_height=floor(orig_height / ratio)
}
1920x1080 (1.77778 ratio) becomes 565x318 (1.77673 ratio, 179,670 pixels)
1000x1000 (1.00000 ratio) becomes 424x424 (1.00000 ratio, 179,776 pixels)
200x1200 (0.16667 ratio) becomes 173x1039 (0.16651 ratio, 179,747 pixels)
width2 = int(ratio * height / scale)
最好是
width2 = int(ratio * height2)
因为这可能会更好地保持纵横比(因为 height2 已被截断)。
在不引入像“sc”这样的另一个变量的情况下,可以写成
new_height = floor(sqrt(m / r))
和
new_width = floor(sqrt(m * r))
给定 m=max_pixels(这里:10.000),r=ratio=w/h(这里:241/76 = 3.171)
两个结果是相互独立的!从每个 new_value,您可以计算另一个维度, (given: new_height) new_width = floor(new_height * r)
(given: new_width) new_height = floor(new_width / r)
由于裁剪了值(地板函数),两对维度的比率与原始比率的接近程度可能有所不同;你会选择更好的一对。