15

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

为了帮助用户调整图像大小,我正在考虑实现一个智能调整大小功能,该功能将允许用户轻松修复图片的纵横比,使其不再显得拉伸。

解决这个问题的快速方法是实际提供两个选项:1)从宽度缩放 2)从高度缩放。用户选择方法,算法使用原始纵横比调整图片大小。例如:图片在设计器上显示为 200x200,但原始图像为 1024x768 像素。用户选择“Smart Size from width”,新尺寸变为~200x150,因为原始纵横比为~1.333

没关系,但是我怎样才能使算法更智能,并且不通过询问重新计算应该基于哪个维度来打扰用户呢?

4

10 回答 10

33

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

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
于 2010-06-09T19:01:20.337 回答
13
于 2012-09-11T01:49:28.297 回答
3

我也想知道这一点,我看到的只是缩放宽度或高度的无穷无尽的例子,但可能会让另一个溢出。

  • 无需循环即可调整宽度和高度
  • 不超过图片原始尺寸

.

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;
}
于 2011-04-13T19:55:41.343 回答
2

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

def _resize(image, dimensions, rotate=None): """ 调整图像的大小以尽可能接近指定的尺寸。图像是 django 图像模型字段。

    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
于 2013-02-16T11:33:33.820 回答
2

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

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

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

于 2010-06-09T18:40:10.890 回答
1

因为您希望在窗口中(即设计器中的区域)尽可能多地显示缩放后的图像(原始图像),所以您将取原始图像的宽度或高度中的较大者,并将其缩放到 200 . 伪代码(宽、高为原尺寸):

if (width > height) {
    scaledWidth = 200;
    scaledHeight = (height * 200) / width;
} else {
    scaledHeight = 200;
    scaledWidth = (width * 200) / height;
}
于 2010-06-09T18:47:26.917 回答
1

这是我的解决方案,

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;
    }
}
于 2013-03-18T14:51:02.953 回答
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,
      };
    }
于 2017-05-15T11:29:25.503 回答
0

您只需要计算出两个维度所需的比例,然后取 2 中较小的一个。

于 2010-06-09T19:02:06.203 回答
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 更改为新尺寸。

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

于 2017-01-22T11:56:23.627 回答