【问题标题】:How to make new given coordinates proportional to old ones?如何使新的给定坐标与旧坐标成比例?
【发布时间】:2011-11-18 03:01:16
【问题描述】:

我有一个对象。它有一些原始宽度和高度。我得到了 new 宽度和高度。如何采用 new 给定的宽度和高度来对象原始对象? (假设我们有一个正方形1000x1000,并给出了一些所需的最大可能坐标,比如1900x1200,什么算法会从中产生1200x1200?或者在其他情况下,我们有1000x1000原始并给出400x600它应该返回400x400...)

所以我开始尝试创建一些可能会失败但失败的代码:

void resize_coefs(const int & original_w, const int & original_h, int & new_w, int & new_h)
{
    double VW = new_w; 
    double VH =  new_h;

    double rw = original_w/VW;
    double rh = original_h/VH;
    if (rw>=rh){
        new_h = VH;
        new_w = rh*new_w + 2;

    }
    else
    {
        new_w = VW;
        new_h= rw*new_h;
    }
}

【问题讨论】:

标签: c++ algorithm resize


【解决方案1】:

这样做:

  1. 计算宽度的比例因子。
  2. 计算高度的比例因子。
  3. 使用最小的缩放因子来缩放宽度和高度。

示例代码:

void resize_coefs(const int original_w, const int original_h, int & new_w, int & new_h)
{
    double scale = std::min(
        ((double) new_w) / original_w ,
        ((double) new_h) / original_h );
    new_w = std::min( scale * original_w, new_w );
    new_h = std::min( scale * original_h, new_h );
}

由于可能存在舍入误差,建议在缩放后检查new_wnew_h 是否仍在界限内。

编辑:这是一个仅使用整数算术执行相同操作的版本,使用了 Kerrek 在他的回答中提供的提示。有点难以看出它遵循完全相同的逻辑。

void resize_coefs(const int original_w, const int original_h, int & new_w, int & new_h)
{
    int num, den;
    if (new_w * original_h < new_h * original_w) {
        num = new_w;
        den = original_w;
    } else {
        num = new_h;
        den = original_h;
    }
    new_w = original_w * num / den;
    new_h = original_h * num / den;
}

【讨论】:

  • 整数运算的危险在于它们很容易溢出。但是,如果您确定它不会发生,那么您可以轻松修改原始清晰代码以保持清晰:int scale = std::min(new_w * original_h, new_h * original_w );new_w = scale / original_h; 等。
【解决方案2】:

计算出原始边界和新边界的纵横比。然后进行比较,并根据需要进行水平或垂直缩放:

const double orig_width, orig_height;
const double max_new_width, max_new_height;

const double orig_ar = orig_width / orig_height;
const double new_ar = max_new_width / max_new_height;

const double scale = new_ar < orig_ar ? max_new_width / orig_width : max_new_height / orig_height;

const double new_height = orig_height * scale;
const double new_width  = orig_width  * scale;

如果您愿意,您可以完全使用整数来完成此操作。请记住,a/b == c/d 等价于 a*d == b*c(您甚至不必担心分母中的零)。

更新:这是我要使用的具体整数函数:

void scale(unsigned int orig_width, unsigned int orig_height,
           unsigned int max_new_width, unsigned int max_new_height)
{
  const bool scale_width = max_new_width * orig_height < orig_width * max_new_height;

  const unsigned int new_height = scale_width ?
                                  orig_height * max_new_width / orig_width :
                                  orig_height * max_new_height / orig_height;
  const unsigned int new_width  = scale_width ?
                                  orig_width  * max_new_width / orig_width :
                                  orig_width  * max_new_height / orig_height;

  std::cout << "New dims: " << new_width << " x " << new_height << std::endl;
}

【讨论】:

  • 不必要的浮点运算过多。计算宽度和高度的比例更有效。
  • @GeneBushuyev:正如我所说,这只是为了展示数学。我会用纯整数运算来编写实际的实现。
猜你喜欢
  • 1970-01-01
  • 2015-09-26
  • 2015-01-20
  • 1970-01-01
  • 2014-11-22
  • 2021-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多