按像素数量调整图像大小

时间:2012-04-11 13:22:54

标签: algorithm

我试图找出答案,但我做不到。

例如,241x76的图片总共有18,316 pixels (241 * 76)。 调整大小规则是,像素数量无法通过10,000。 然后,如何让新尺寸保持纵横比并且小于10,000像素?

5 个答案:

答案 0 :(得分:5)

伪代码:

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

在实施时,请记住对所有涉及ratioscale的计算使用浮点数学。


的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)

答案 1 :(得分:1)

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 without losing any quality

的答案的图形代码

编辑:计算宽高比实际上与此无关,因为我们已经将宽度和高度缩放了总像素比率(平方根)。您可以使用它来根据newWidth(或反之亦然)计算newHeight,但这不是必需的。

答案 2 :(得分:1)

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

答案 3 :(得分:0)

将图像缩小到最大像素数,同时保持纵横比

这是我今天下午想出来的,当时我想自己解决数学问题,为了好玩。我的代码似乎工作正常,我测试了几种不同形状和大小的图像。确保使用浮点变量,否则数学会出错。

伪代码

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)

答案 4 :(得分:-1)

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,您可以计算其他维度 (给定:new_height)new_width = floor(new_height * r)
(给定:new_width)new_height = floor(new_width / r)

由于剪切值(地板函数),两个维度对可能在它们的比率与原始比率的接近程度上有所不同;你会选择更好的一对。