2012-12-04 69 views
9

我在'developer.android.com'上看到縮小我的位圖文件,我發現一件事我不明白。所以我感謝你給我一點幫助。android - calculateInSampleSize,爲什麼Math.round在width> height時處理height(height/reqHeight)?

這裏有一個snippet從developer.android.com

public static int calculateInSampleSize(
     BitmapFactory.Options options, int reqWidth, int reqHeight) { 
    // Raw height and width of image 
    final int height = options.outHeight; 
    final int width = options.outWidth; 
    int inSampleSize = 1; 

    if (height > reqHeight || width > reqWidth) { 
    if (width > height) { 
     inSampleSize = Math.round((float)height/(float)reqHeight); 
    } else { 
     inSampleSize = Math.round((float)width/(float)reqWidth); 
    } 
    } 
    return inSampleSize; 
} 
在if語句

,當 「如果(寬度>高度)」 爲什麼他們計算 「(浮動)的高度/(浮動)reqHeight」?

例如,width = 600,height = 800,reqWidth = 100,reqHeight = 100。

在這種情況下,inSampleSize爲6,計算的維數爲width = 100,height = 133。身高仍然高於reqHeight ..

所以,任何人都可以解釋我這件事嗎?對不起,複雜的解釋,但 我希望有人給我一個想法。 :)

回答

3

我只能說他們的邏輯看起來不正確:(無論如何,這種方法是相當簡單的,所以它不應該是一個很大的問題,你要重新實現它的正確條件!看看decodeSampledBitmapFromResource,它只是想減少位圖,使其適合所需的邊界,所以這必須是一個錯誤。

編輯::這看起來更糟糕,至於我不會爲一些工作假設你有width = 200和height = 600.你設置你的最大邊界爲width = 100,height = 500.你有height> width,但是如果你希望它們都適合返回結果,那麼inSampleSize必須是200/100而不是600/500 所以基本上如果你重新實現了這個方法,我會這樣做:

public static int calculateInSampleSize(
      BitmapFactory.Options options, int reqWidth, int reqHeight) { 
    // Raw height and width of image 
    final int height = options.outHeight; 
    final int width = options.outWidth; 

    int stretch_width = Math.round((float)width/(float)reqWidth); 
    int stretch_height = Math.round((float)height/(float)reqHeight); 

    if (stretch_width <= stretch_height) 
     return stretch_height; 
    else 
     return stretch_width; 
} 

但是這看起來像他們的代碼太多問題,我相信我正確地理解了它的重點!

+0

Thx!所以他們的邏輯似乎是錯誤的。 – user1874389

3

好,具有縮放,東西很多問題後,我覺得我有我自己的答案:

使用「裝入大的位圖高效」從http://developer.android.com/training/displaying-bitmaps/load-bitmap.html我想發表我的一些結果(原始代碼如下 ):

// Calculate ratios of height and width to requested height and width 
final int heightRatio = Math.round((float) height/(float) reqHeight); 
final int widthRatio = Math.round((float) width/(float) reqWidth); 

我目前正在使用橫​​向模式下的1280 x 752分辨率的Galaxy-Tab 7.7。想象一下具有以下規格的圖像:

1920 x 1200 ..會發生什麼?

heighRatio =一千二百八十零分之一千九百二十零= 1.5和widthRatio =七百五十二分之一千二= 1.59

兩個數字獲得roundet到所以圖像將被因子2按比例縮小,如果我明白了一切對。這將導致圖像爲1920/2 = 960 * 600,這小於我的要求分辨率1280 * 752

我解決了這個由地板更換輪:

// Calculate ratios of height and width to requested height and width 
final int heightRatio = (int)Math.floor((float) height/(float) reqHeight); 
final int widthRatio = (int)Math.floor((float) width/(float) reqWidth); 

這實際上阻止我的一些圖片得到縮小太多。我目前仍在調查參數inSampleSize以查看是否使用「分數」是一個選項。目前所有尺寸最大爲1280x752(* 2)= 2560 * 1504的圖片都會縮放,並且而不是。我寫的imageView是圖像的詳細視圖,所以它現在不應該是太多問題。

我結合使用的修改後的版本代碼:

returnview.setAdjustViewBounds(true); 

這將防止圖像更大然後我的屏幕上獲得搞砸邊框。如果將顏色背景設置爲實際圖像,則可以看到它。此外,通過現在固定的代碼,我可以實現一些onClick處理程序來檢測用戶是否在我的圖像之外單擊以關閉圖像。

0

我覺得他們的邏輯

if (height > reqHeight || width > reqWidth) { 
    if (width > height) { 
     inSampleSize = Math.round((float)height/(float)reqHeight); 
    } else { 
     inSampleSize = Math.round((float)width/(float)reqWidth); 
    } 
} 

混淆了。我會採取更簡單的方法。我的邏輯是如果圖像是水平圖像而忽略所需的高度,則按照寬度縮放圖像,如果圖像是垂直圖像並忽略所需的寬度,則將圖像放大到高度。

if (height > reqHeight || width > reqWidth) { 
     if (width > height) { 
      inSampleSize = Math.round((float) width/(float) reqWidth); 
     } else { 
      inSampleSize = Math.round((float) height/(float) reqHeight); 
     } 
    } 
2

上述問題中的代碼嚴重過時。如圖BitmapFactory.Options reference記錄(自2013年3月8日)。如果設置爲值> 1 inSampleSize將被向下舍入爲2.

最近的電源,要求解碼器以子採樣原始圖像 ,返回一個較小的圖像來節省內存。樣本大小爲在任一維度中對應於解碼位圖中的單個像素的像素數量的 。例如,inSampleSize == 4將返回一個 圖像,該圖像是原始寬度/高度的1/4,以及1/16像素數。任何值< = 1同等對待1注: 解碼器使用基於2的冪的最終值,任何其它值將 可以向下舍入到從2.

BitmapFactory.Options reference最近的電源2013年3月8日

所以正確的代碼,以計算inSampleSizeLoading Large Bitmaps

public static int calculateInSampleSize(BitmapFactory.Options options, 
    int reqWidth, int reqHeight) { 

    // Raw height and width of image 
    final int height = options.outHeight; 
    final int width = options.outWidth; 
    int inSampleSize = 1; 

    if (height > reqHeight || width > reqWidth) { 

     final int halfHeight = height/2; 
     final int halfWidth = width/2; 

     // Calculate the largest inSampleSize value that is a power of 2 and keeps both 
     // height and width larger than the requested height and width. 
     while ((halfHeight/inSampleSize) > reqHeight 
       && (halfWidth/inSampleSize) > reqWidth) { 
      inSampleSize *= 2; 
     } 
    }  
    return inSampleSize; 
} 

然而上面的代碼可以附加地優化。因爲halfWidthhalfHeight已被除以2,而循環可以被重寫以將圖像大於或等於返回到所請求的大小範圍。

 while ((halfHeight/inSampleSize) >= reqHeight 
       && (halfWidth/inSampleSize) >= reqWidth) { 
      inSampleSize *= 2; 
     } 

用於圖像原始代碼大小800x800 PIX具有裝配到100x100 PIX將返回4 inSampleSize - >返回的圖像將是200x200 PIX,並且修改後的代碼將返回8的inSampleSize - >返回的圖像將是100x100 PIX。

注:下采樣圖像與inSampleSizeBitmapFactory.decodeXXX方法主要功能是在加載了比所需的用於顯示目的顯著較大的圖像保存存儲器。這些方法結合上面的代碼總是會給你最小的圖像(按2的冪進行縮放),它大於(或等於)所要求的邊界,而不是適合該邊界的圖像。

0

他們的邏輯不僅僅是它的邏輯錯誤。在圖像中需要的東西不會縮小,直到一個參數小於所需的值,如果它被分成了一半,但確保沒有維度大於2048.在此之上,很多時候您可以' t渲染紋理或顯示圖像。如果你有一個像是4000x1300的圖像,並且你說你至少需要768.如果沒有低於這個值,它實際上不能切割1300。所以它什麼也不做,退出。試圖加載失敗的4000幅圖像。

public static int calculateInSampleSize(BitmapFactory.Options options, int maxWidth, int maxHeight) { 
    int height = options.outHeight; 
    int width = options.outWidth; 
    int inSampleSize = 1; 
    while (height > maxHeight || width > maxWidth) { 
     height /= 2; 
     width /= 2; 
     inSampleSize *= 2; 
    } 
    return inSampleSize; 
} 
相關問題