【问题标题】:math/algorithm Fit image to screen retain aspect ratio数学/算法使图像适合屏幕保留纵横比
【发布时间】:2011-09-27 18:51:33
【问题描述】:

我需要数学/算法方面的帮助来拍摄已知尺寸并适合两个屏幕尺寸之一的图像:

720 x 480 或 1280 x 1024。

图像尺寸来自 XML 文件,但是这些尺寸是 Web 尺寸,我还从 XML 中选择了一些图像,这些图像的分辨率可能比 Web 尺寸更高和更低。

我想要的是使用网络尺寸的纵横比在高清 (1280x720) 屏幕上显示更高分辨率的图像(如果可用),或者如果用户在标清屏幕 (720x480) 上显示图像在那个屏幕上。

对此有用但优先级较低的其他事情是,如果我知道图像的分辨率在两个维度上都小于 SD 屏幕(在这种情况下,我只知道网络维度,并且图像文件的水平尺寸),以在该屏幕上显示为实际大小。

希望这足够清楚。

谢谢!

【问题讨论】:

  • 您能发布示例数据吗?您希望结果是什么?
  • 好的,这里有一些真实的示例数据: web dimension= width="340" height="517" 其中有一个可用的图像,x 尺寸实际上是 1280。我想调整大小这样它的高度不高于720,并按比例调整宽度以使图像不会失真,所以我可以在高清屏幕上显示它,或者如果用户在SD屏幕上,那将是我的尺寸将扩展到。输出将是 targetrect={x,y,xx,yy)

标签: algorithm image math graphics resize


【解决方案1】:

尽可能通用:

图像数据:(wi, hi) 并定义 ri = wi / h
屏幕分辨率:(ws, hs) 并定义 rs = ws / h s

缩放的图像尺寸:

rs > ri ? (wi * hs/hi, hs) : (ws, hi * ws/wi)

例如:

         20
|------------------|
    10
|---------|

--------------------     ---   ---
|         |        |      | 7   |
|         |        |      |     | 10
|----------        |     ---    |
|                  |            |
--------------------           ---

ws = 20
hs = 10
wi = 10
hi = 7

20/10 > 10/7 ==> (wi * hs/hi, hs) = (10 * 10/7, 10) = (100/7, 10) ~ (14.3, 10)

您可以清楚地看到它与屏幕尺寸的比例,因为高度是屏幕的高度,但自14.3/10 ~ 10/7以来显然保持纵横比

更新

如下图居中:

调用 (wnew, hnew) 新维度。

top = (hs - hnew)/2
left = (ws - wnew)/2

【讨论】:

  • 我对您使用的符号并不完全熟悉,下标 i 是否指代数组的成员,例如 x[i] 其中 x 是大小数组,所以 i 指一个图像和 w[i] 表示我们正在对一组图像进行操作?对不起,如果这让我看起来像个白痴。
  • @alphablender,不,没有数组,i 应该是图像,s 是屏幕。
  • 这看起来有点像你所描述的吗?: imagewidth=x imageheight=y imageratio= imagewidth / imageheight screenwidth=1280 screenheight=720 screenratio=screenwidth / screenheight if screenratio > imageratio then resultwidth=imagewidth * screenheight / imageheight resultheight=screenheight else resultwidth=screenwidth resultheight=imageheight * screenwidth / imagewidth end if
  • 计算尺寸后,如何计算在给定屏幕尺寸上居中的图像?
  • 这很好,也很清楚。我认为使用 9 而不是 10 之一可能更清楚,但我喜欢 ascii 图纸。
【解决方案2】:

我理解接受的答案并且它有效,但我总是发现以下方法更简单,更简洁,适合“最适合”:

// prep
let maxWidth = 190,
    maxHeight = 150;
let imgWidth = img.width,
    imgHeight = img.height;

// calc
let widthRatio = maxWidth / imgWidth,
    heightRatio = maxHeight / imgHeight;
let bestRatio = Math.min(widthRatio, heightRatio);

// output
let newWidth = imgWidth * bestRatio,
    newHeight = imgHeight * bestRatio;

...当然可以归结为:

const maxWidth = 190, maxHeight = 150;
const bestRatio = Math.min(maxWidth / img.width, maxHeight / img.height);
img.width *= bestRatio;
img.height *= bestRatio;

【讨论】:

  • 很好的答案。便于理解算法实际在做什么。
【解决方案3】:

这里是简单的 C 语言。

您希望通过返回的比例因子来缩放两个坐标。

/* 对于屏幕内的矩形,获取允许该矩形的比例因子 在不拉伸或挤压的情况下缩放。 */ 漂浮 aspect_correct_scale_for_rect(const float screen[2], const float rect[2]) { 浮动屏幕方面=屏幕[0]/屏幕[1]; 浮动 rectAspect = rect[0] / rect[1]; 浮动比例因子; if (screenAspect > rectAspect) 比例因子=屏幕[1]/矩形[1]; 别的 比例因子=屏幕[0]/矩形[0]; 返回比例因子; }

【讨论】:

  • 纵横比与选择高宽比的关系。
【解决方案4】:

使用信箱或适合屏幕进行纵横比校正

我最近写了一个方法来处理 iOS 中的这个确切问题。我是用Eigen矩阵库做缩放的,但是原理(缩放因子)是一样的,不用矩阵。

Eigen::Matrix4x4f aspectRatioCorrection(bool fillScreen, const Eigen::Vector2f &screenSize, const Eigen::Vector2f &imageSize)
{
    Eigen::Matrix4x4f scalingMatrix(Eigen::Matrix4x4f::Identity());

    float screenWidth = screenSize.x();
    float screenHeight = screenSize.y();
    float screenAspectRatio = screenWidth / screenHeight;
    float imageWidth = imageSize.x();
    float imageHeight = imageSize.y();
    float imageAspectRatio = imageWidth / imageHeight;

    float scalingFactor;
    if (fillScreen) {
        if (screenAspectRatio > imageAspectRatio) {
            scalingFactor = screenWidth / imageWidth;
        } else {
            scalingFactor = screenHeight / imageHeight;
        }
    } else {
        if (screenAspectRatio > imageAspectRatio) {
            scalingFactor =  screenHeight / imageHeight;
        } else {
            scalingFactor = screenWidth / imageWidth;
        }
    }

    scalingMatrix(0, 0) = scalingFactor;
    scalingMatrix(1, 1) = scalingFactor;

    return scalingMatrix;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-09
    • 1970-01-01
    • 2013-07-26
    • 2021-07-22
    • 1970-01-01
    • 1970-01-01
    • 2015-07-16
    • 1970-01-01
    相关资源
    最近更新 更多