如何将显示的图像“智能调整”为原始宽高比

时间:2010-06-09 18:35:17

标签: algorithm image image-processing aspect-ratio

我有一个应用程序,最终用户可以在设计器中调整图像的大小和位置。由于规范要求图像“拉伸”到包含控件,最终用户最终可能会得到一个笨拙的拉伸图像。

为了帮助用户进行图像大小调整,我正在考虑实现智能缩放器功能,该功能允许用户轻松修复图片的宽高比,使其不再显示拉伸。

解决这个问题的快捷方法是实际提供两个选项:1)从宽度开始缩放2)从高度开始缩放。用户选择该方法,并且算法通过使用原始宽高比来调整图片的大小。例如:图片在设计器上显示为200x200,但原始图像为1024x768像素。用户选择“宽度智能尺寸”,新尺寸变为〜200x150,因为原始宽高比为~1.333

没关系,但是如何通过询问重新计算应基于哪个维度来使算法更智能而不打扰用户?

10 个答案:

答案 0 :(得分:26)

如果我正确地解释您的规范,您希望结果不大于最终用户最初布置的结果;你希望两个维度中的一个缩小,另一个保持不变。换句话说,新尺寸应该在一个方向上填充设计师空间,同时缩短另一个方向上的尺寸以保持原始宽高比。

original_ratio = original_width / original_height
designer_ratio = designer_width / designer_height
if original_ratio > designer_ratio
    designer_height = designer_width / original_ratio
else
    designer_width = designer_height * original_ratio

通常你会使用整数坐标,但产生上述比率的分区需要是浮点数。这是公式的重新排列,更加整数友好。确保整数具有处理最大宽度*高度的范围。

if original_width * designer_height > designer_width * original_height
    designer_height = (designer_width * original_height) / original_width
else
    designer_width = (designer_height * original_width) / original_height

答案 1 :(得分:9)

这是我在处理这个问题时提出的解决方案。结果非常简短直接的imo,只是想分享它。

方便的“公式”:ratio = W / H W = H * ratio H = W / ratio

  1. 计算比率。
  2. 如果要将宽度设置为新的尺寸宽度(允许的最大宽度),请计算图像的高度。
  3. 如果要将高度设置为新的尺寸高度(允许的最大高度),请计算图像的宽度。
  4. 查看两种尺寸中的哪一种不会覆盖任何尺寸的最大尺寸。如果比率不是1,则其中一个总是错误的,而且总是正确的。
  5. 在Javascript中

    // Returns array with new width and height
    function proportionalScale(originalSize, newSize)
    {
        var ratio = originalSize[0] / originalSize[1];
    
        var maximizedToWidth = [newSize[0], newSize[0] / ratio];
        var maximizedToHeight = [newSize[1] * ratio, newSize[1]];
    
        if (maximizedToWidth[1] > newSize[1]) { return maximizedToHeight; }
        else { return maximizedToWidth; }
    }
    

    originalSizenewSize是一个数组[0] = width[1] = height

答案 2 :(得分:2)

没有考虑复制和粘贴的数量呃!我也想知道这一点,我所看到的只是缩放宽度或高度的无数例子。谁会想要另一个溢出?!

  • 调整宽度和高度,无需循环
  • 不超过图像原始尺寸
  • 使用正常工作的数学,即高度的宽度/宽高度,以及宽度的高度*宽高比,因此图像实际上可以上下缩放:/

//////////////

private void ResizeImage(Image img, double maxWidth, double maxHeight)
{
    double srcWidth = img.Source.Width;
    double srcHeight = img.Source.Height;

    double resizeWidth = srcWidth;
    double resizeHeight = srcHeight;

    double aspect = resizeWidth / resizeHeight;

    if (resizeWidth > maxWidth)
    {
        resizeWidth = maxWidth;
        resizeHeight = resizeWidth / aspect;
    }
    if (resizeHeight > maxHeight)
    {
        aspect = resizeWidth / resizeHeight;
        resizeHeight = maxHeight;
        resizeWidth = resizeHeight * aspect;
    }

    img.Width = resizeWidth;
    img.Height = resizeHeight;
}

答案 3 :(得分:2)

接受上面的建议并使其在最大高度/宽度范围内向上/向下扩展。这里是它的python代码,还增加了对旋转事物的支持,同时保持在限制范围内:

def _resize(图片,尺寸,旋转=无):     “””         将图像的大小调整为尽可能接近指定的尺寸。图像是一个         django image-model-field。

    Will both scale up and down the image to meet this while keeping the proportions
    in width and height

"""

if image and os.path.isfile(image.path):

    im = pil.open(image.path)
    logging.debug('resizing image from %s x %s --> %s x %s ' % (im.size[0], im.size[1], dimensions[0], dimensions[1]))

    if rotate:
        logging.debug('first rotating image %s' % rotate)
        im = im.rotate(90)

    srcWidth = Decimal(im.size[0])
    srcHeight = Decimal(im.size[1])

    resizeWidth = srcWidth
    resizeHeight = srcHeight

    aspect = resizeWidth / resizeHeight # Decimal

    logging.debug('resize aspect is %s' % aspect)

    if resizeWidth > dimensions[0] or resizeHeight > dimensions[1]:
        # if width or height is bigger we need to shrink things
        if resizeWidth > dimensions[0]:
            resizeWidth = Decimal(dimensions[0])
            resizeHeight = resizeWidth / aspect

        if resizeHeight > dimensions[1] :
            aspect = resizeWidth / resizeHeight
            resizeHeight = Decimal(dimensions[1])
            resizeWidth = resizeHeight * aspect

    else:
        # if both width and height are smaller we need to increase size
        if resizeWidth < dimensions[0]:
            resizeWidth = Decimal(dimensions[0])
            resizeHeight = resizeWidth / aspect

        if resizeHeight > dimensions[1] :
            aspect = resizeWidth / resizeHeight
            resizeHeight = Decimal(dimensions[1])
            resizeWidth = resizeHeight * aspect

    im = im.resize((resizeWidth, resizeHeight), pil.ANTIALIAS)

    logging.debug('resized image to %s %s' % im.size)
    im.save(image.path)

else:
    # no action, due to no image or no image in path
    pass

return image

答案 4 :(得分:1)

计算两种变体的新尺寸(“按宽度比例”和“按高度比例”),然后使用适合显示的那种尺寸。

或者,您也可以计算“边界框”的纵横比,并将其与原始图像的纵横比进行比较。根据哪个纵横比较大,需要缩放高度或宽度。

您还可以限制调整大小过程,以便在所有情况下都可以“按宽度缩放”。然后,要更改图像的大小,用户始终必须更改其宽度。高度始终会自动调整。

答案 5 :(得分:1)

因为您希望尽可能多地显示窗口中缩放的图像(原始图像),即设计器中的区域,您将采用原始图像的宽度或高度中较大的一个,并进行缩放到200.伪代码(宽度,高度是原始尺寸):

if (width > height) {
    scaledWidth = 200;
    scaledHeight = (height * 200) / width;
} else {
    scaledHeight = 200;
    scaledWidth = (width * 200) / height;
}

答案 6 :(得分:1)

我的解决方案是根据https://stackoverflow.com/a/5654847/1055015

缩小和增加javascript中的尺寸
var scale =  function (srcWidth, srcHeight, maxWidth, maxHeight) {

      let resizeWidth  = srcWidth;
      let resizeHeight = srcHeight;

      let aspect = resizeWidth / resizeHeight;
      let scaleX = maxWidth / srcWidth;
      let scaleY = maxHeight / srcHeight;
      let scale  = Math.min(scaleX, scaleY);

      resizeWidth *= scale;
      resizeHeight *= scale;

      if (resizeWidth > maxWidth) {
        resizeWidth  = maxWidth;
        resizeHeight = resizeWidth / aspect;
      }

      if (resizeHeight > maxHeight) {
        aspect       = resizeWidth / resizeHeight;
        resizeHeight = maxHeight;
        resizeWidth  = resizeHeight * aspect;
      }

      return {
        width : resizeWidth,
        height: resizeHeight,
      };
    }

答案 7 :(得分:0)

您只需要计算出两个尺寸所需的比例,然后选择较小的尺寸。

答案 8 :(得分:0)

这是我的解决方案,

a =方面 sw =原始图像宽度 sh =原始图像高度 dw =请求的最大宽度 dh =要求的最大高度

sw和sh将包含最终调整大小的值

代码是PHP:

$a = $sw / $sh;

if($a > 1){
    //  wider image
    if($sw != $dw){
        $rt = $dw / $sw;
        $sw = $sw * $rt;
        $sh = $sh * $rt;
    }

    if($sh > $dh){
        $rt = $dh / $sh;
        $sw = $sw * $rt;
        $sh = $sh * $rt;
    }
}else{
    //  taller image
    if($sh != $dh){
        $rt = $dh / $sh;
        $sh = $sh * $rt;
        $sw = $sw * $rt;
    }

    if($sw > $dw){
        $rt = $dw / $sw;
        $sh = $sh * $rt;
        $sw = $sw * $rt;
    }
}

答案 9 :(得分:0)

我用这种方式将图像调整为FHD方式

if ( width >= height) {
  var original_ratio = width / height
  new_width = 1080 * original_ratio
  console.log("new new_width = " + Math.round(new_width) );
  console.log("new new_height = 1080");
} else {
  var original_ratio =  height / width
  new_height = 1080 * original_ratio
  console.log("new new_height = " + Math.round(new_height) );
  console.log("new new_width = 1080");
}

您可以将1080更改为新尺寸。

我希望它至少对某些人有用。