2011-03-20 53 views
1

我有一个N图片阵列,每个图片的尺寸都是WxH。我想将它们显示在尽可能接近正方形的矩形矩阵中。最后一行可能不完整。我如何计算行数和列数?布局算法

回答

2

所以,假设你有p和q向下;那么你的整个图像是qH,你想包括所有的图像,所以pq> = N;只允许最后一行不完整,所以p(q-1)< N.并且,根据这些条件,您希望pW和qH尽可能接近相等。 (也许你还希望pq-N尽可能小?)

条件N < p(q-1)< = N相当于q = ceiling(N/p)。所以你要选择p,以使比率p:ceiling(N/p)尽可能接近H:W(从某种意义上说,也许你想最小化对数的绝对差值或某物)。因此,非常粗略地,p /(N/p)= = H/W,所以p = = sqrt(NH/W)。

随着p增加,N/p减少,因此上限(N/p)至少不会增加。所以p/ceiling(N/p)是p的递增函数。所以,无论你喜欢什么样的比例贴近率标准,只有一个P值才能完成这项工作,而且当你以一种方式离开它时,比例会逐渐变差,而在另一个方向变得更糟在另一方移走。

所以,超级幼稚但很可能足够的伪代码如下所示(请注意,它忽略了的东西像整数和浮点值之间的转换):

target_ratio = H/W; 
p = round(sqrt(N*H/W)); // initial guess 
current_ratio = p/ceiling(N/p); 
merit = merit_function(current_ratio, target_ratio); 
best_p = p; best_merit = merit; prev_merit = merit; 
// [define merit_function however you like; e.g., -abs(log(x/y)-1) 
// or -max(x/y-1,y/x-1) or whatever.] 
if (current_ratio > target_ratio) { 
    // p might be too big 
    while (true) { 
    --p; if (p<=0) break; 
    current_ratio = p/ceiling(N/p); 
    merit = merit_function(current_ratio, target_ratio); 
    if (merit > best_merit) { best_p=p; best_merit=merit; } 
    else if (merit < prev_merit) break; 
    prev_merit = merit; 
    } 
} 
else if (current_ratio < target_ratio) { 
    // p might be too small 
    // similar loop, but in the other direction 
} 

我怀疑为merit_function合理的选择,你只永远不得不做一次迭代,但我不想现在就试图证明这一点。

如果一个适当的解决方案,而不是一个最佳的解决方案,是足够好的,那么你可以只使用p=round(sqrt(N*H/W))并完成它。或者,对于略微更好的近似值,可以说ceiling(N/p)平均可能约为N/p+0.5,我认为这最终意味着您需要类似p = round(sqrt(N*H/W+0.25*H*H/(W*W)) - 0.25*H/W之类的东西。 (你应该在依赖它之前检查我的代数,我只是简化p /(N/p-1/2)= H/W并求解二次方程)

0

(第一尝试是完全错误..

(所以是第2次试)

3ND尝试:

columns = floor(sqroot(N * H/W) + 0.5) 
rows = ceiling(N/columns) 
+0

这给出了不是多个的W和H.这听起来像是Carn想要沿着每一边的整张照片。 – 2011-03-21 00:04:56

+0

哦,我的算法是完全错误的,纠正它。 – 2011-03-21 00:26:17

1

你可以尝试所有可能的布局,如果N足够小

Score(N, W, H, columnCount): 
    rowCount = ceiling(N/columnCount) 
    xPixels = W * columnCount 
    yPixels = H * rowCount 
    return min(xPixels, yPixels)/max(xPixels, yPixels) 

bestColumnCount = columnCount with max Score(N, W, H, columnCount) in [1,N] 
bestRowCount = ceiling(N/bestColumnCount)