如何“智能调整大小”显示图像与原始长宽比

发布于 2024-09-04 13:36:39 字数 348 浏览 6 评论 0原文

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

为了帮助用户调整图像大小,我正在考虑实现智能缩放功能,该功能将允许用户轻松固定图片的长宽比,使其不再显得拉伸。

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

没关系,但是我怎样才能使算法更智能,而不是通过询问重新计算应基于哪个尺寸来打扰用户?

I have an application in which end-users can size and position images in a designer. Since the spec calls for the image to be "stretched" to the containing control, the end user can end up with an awkwardly stretched image.

To help the user with image sizing I am thinking of implementing a smart resizer function which would allow the the user to easily fix the aspect ratio of the picture so that it no longer appears stretched.

The quick way to solve this is to actually provide two options: 1) scale from width 2) scale from height. The user chooses the method and the algorithm adjusts the size of the picture by using the original aspect ratio. For example: A picture is displayed as 200x200 on the designer but the original image is 1024x768 pixels. The user chooses "Smart Size from width" and the new size becomes ~200x150 since the original aspect ratio is ~1.333

That's OK, but how could I make the algorithm smarter and not bother the user by asking which dimension the recalculation should be based on?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

一江春梦 2024-09-11 13:36:40

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

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

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

Calculate the new dimensions for both variants ("scale by width" and "scale by height"), then use the one that fits in the display.

Alternatively you could also calculate the the aspect ratio of the "bounding box" and compare it against the aspect ratio of the original image. Depending on which aspect ratio is larger, the height or the width needs to be scaled.

You also could restrict the resize process so that in all cases "scale by width" is done. Then, to change the size of the image, the user always has to change its width. The height will always be adjusted automatically.

一袭水袖舞倾城 2024-09-11 13:36:40

采纳上面的建议并使其在最大高度/宽度内放大/缩小。这里是它的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

Took the suggestion above and made it scale up/down within max height / width. Here the python code for it and also added support for rotating things while keeping within limites:

def _resize(image, dimensions, rotate=None):
"""
Resizes an image to be as close as possible to specified dimensions. Image is a
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
甜味超标? 2024-09-11 13:36:40

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

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

Because you want to maximize showing as much as possible the scaled image (of the original) in your window, i.e. the area in your designer, you would take the larger of either the width or height of the original image, and scale that to 200. Pseudo-code (width, height are dimensions of original):

if (width > height) {
    scaledWidth = 200;
    scaledHeight = (height * 200) / width;
} else {
    scaledHeight = 200;
    scaledWidth = (width * 200) / height;
}
假扮的天使 2024-09-11 13:36:40

这是我的解决方案,

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;
    }
}

here is my solution,

a = aspect
sw = original image width
sh = original image height
dw = requested max width
dh = requested max height

sw and sh will contain the final resized values

code is 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;
    }
}
你列表最软的妹 2024-09-11 13:36:40

我的解决方案是基于 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,
      };
    }

My solution to shrink and grow size in javascript based on https://stackoverflow.com/a/5654847/1055015

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,
      };
    }
鹤仙姿 2024-09-11 13:36:40

您只需计算出两个尺寸所需的比例,然后取 2 中较小的一个即可。

You just need to work out the scale needed for both dimensions and then take the smaller of the 2.

我不会写诗 2024-09-11 13:36:40

我用这种方法将图像大小调整为 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 更改为新大小。

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

I used this way to resize the image to FHD way

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");
}

you can change the 1080 to the new size.

I hope it's useful for someone at least.

只怪假的太真实 2024-09-11 13:36:39

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

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

If I'm interpreting your spec correctly, you want a result that is no larger than the one the end-user laid out originally; you want one of the two dimensions to shrink, and the other to stay the same. In other words, the new size should fill the designer space in one direction while shortening the size in the other direction to retain the original aspect ratio.

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

Often you'll be working with integer coordinates, but the divisions to produce the ratios above need to be floating point. Here's a rearrangement of the formula to be more integer friendly. Make sure your integers have the range to handle the maximum width*height.

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
埋情葬爱 2024-09-11 13:36:39

这是我在处理这个问题时想到的一个解决方案。在我看来,结果非常简短和直接,只是想分享它。

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

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

在 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

Here's a solution I came up with when having to deal with this problem. Turned out pretty short and straightforward imo, just wanted to share it.

Handy "formulas": ratio = W / H W = H * ratio H = W / ratio

  1. Calculate the ratio.
  2. Calculate the height of the image if you would set the width to the new size width (maximum allowed width).
  3. Calculate the width of the image if you would set the height to the new size height (maximum allowed height).
  4. See which of the two sizes does not override the max size in any dimension. If the ratio is not 1 one of them will always be wrong and one will always be correct.

In 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; }
}

originalSize and newSize is an array [0] = width, [1] = height

悲凉≈ 2024-09-11 13:36:39

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

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

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;
}

I also wanted to know this and all I saw were endless examples of scaling width OR height but could leave the other overflowing.

  • Resize width AND height without the need for a loop
  • Doesn't exceed the images original dimensions

.

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文