2011-03-20 78 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)