2016-09-29 45 views
2

我在將圖像加載到某些設備的屏幕上時遇到了問題。甚至當我解碼圖像時OOM錯誤

所有的屏幕都有一個圖像,但它的相當高的圖像。

以下是在圖像尺寸

人像:

  • MDPI:360x1074
  • HDPI:540x1611
  • xhdpi:720x2148
  • xxhdpi:1080x3142

景觀:

  • MDPI:640x705
  • 華電國際:960x1058
  • xhdpi:1280x1410
  • xxhdpi:1920x1035

我跟了:https://developer.android.com/training/displaying-bitmaps/load-bitmap.html也是這個http://successmatics.com/blog/loading-large-bitmaps-in-android-ui/,但他們基本上是相同的。

如果我加載一個小得多的圖像說別的縮略圖,它加載得很好。

在OnCreate

mImageView.setImageBitmap(
    ImageUtils.decodeSampledBitmapFromResource(getResources(), 
    R.drawable.image, 
    ImageUtils.getScreenWidth(getApplicationContext()), 
    ImageUtils.getScreenHeight(getApplicationContext()))); 
} 

方法加載圖像用於解碼圖像(從上面的2個網址)

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { 

    // First decode with inJustDecodeBounds=true to check dimensions 
    final BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    BitmapFactory.decodeResource(res, resId, options); 

    // Calculate inSampleSize 
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 

    // Decode bitmap with inSampleSize set 
    options.inJustDecodeBounds = false; 
    return BitmapFactory.decodeResource(res, resId, options); 
    } 

    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) { 
//--------i tried a sample size of 2. was hoping 3 would work---------// 
     inSampleSize *= 3; 
     } 
    } 

    return inSampleSize; 
    } 

    public static int getScreenWidth(Context context) { 
    DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); 
    return displayMetrics.widthPixels; 
    } 

    public static int getScreenHeight(Context context) { 
    DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); 
    return displayMetrics.heightPixels; 
    } 

任何人都不會有大的圖像解碼更好的辦法,所以我不明白在OOM

有什麼錯我的代碼(WHI CH從Android電子自理)

編輯:對不起忘了堆棧跟蹤:

E/dalvikvm-heap: Out of memory on a 10391232-byte allocation. 
    I/dalvikvm: "main" prio=5 tid=1 RUNNABLE 
    I/dalvikvm: | group="main" sCount=0 dsCount=0 obj=0xb264b450 self=0xb8d604e0 
    I/dalvikvm: | sysTid=26630 nice=0 sched=0/0 cgrp=[fopen-error:2] handle=-1216986048 
    I/dalvikvm: | schedstat=(0 0 0) utm=117 stm=69 core=0 
    I/dalvikvm:  at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) 
    I/dalvikvm:  at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:500) 
    I/dalvikvm:  at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:353) 
    I/dalvikvm:  at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:781) 
    I/dalvikvm:  at android.content.res.Resources.loadDrawable(Resources.java:1935) 
    I/dalvikvm:  at android.content.res.TypedArray.getDrawable(TypedArray.java:601) 
    I/dalvikvm:  at android.widget.ImageView.<init>(ImageView.java:120) 
    I/dalvikvm:  at android.support.v7.widget.AppCompatImageView.<init>(AppCompatImageView.java:57) 
    I/dalvikvm:  at android.support.v7.widget.AppCompatImageView.<init>(AppCompatImageView.java:53) 
    I/dalvikvm:  at android.support.v7.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:106) 
    I/dalvikvm:  at android.support.v7.app.AppCompatDelegateImplV7.createView(AppCompatDelegateImplV7.java:980) 
    I/dalvikvm:  at android.support.v7.app.AppCompatDelegateImplV7.onCreateView(AppCompatDelegateImplV7.java:1039) 
    I/dalvikvm:  at android.support.v4.view.LayoutInflaterCompatHC$FactoryWrapperHC.onCreateView(LayoutInflaterCompatHC.java:44) 
    I/dalvikvm:  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:675) 
    I/dalvikvm:  at android.view.LayoutInflater.rInflate(LayoutInflater.java:746) 
    I/dalvikvm:  at android.view.LayoutInflater.rInflate(LayoutInflater.java:749) 
    I/dalvikvm:  at android.view.LayoutInflater.rInflate(LayoutInflater.java:749) 
    I/dalvikvm:  at android.view.LayoutInflater.inflate(LayoutInflater.java:489) 
    I/dalvikvm:  at android.view.LayoutInflater.inflate(LayoutInflater.java:396) 
    I/dalvikvm:  at android.view.LayoutInflater.inflate(LayoutInflater.java:352) 
    I/dalvikvm:  at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:280) 
    I/dalvikvm:  at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:140) 
    I/dalvikvm:  at com.myapp.app.item.protection.Protection.onCreate(Protection.java:31) 
    I/dalvikvm:  at android.app.Activity.performCreate(Activity.java:5008) 
    I/dalvikvm:  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079) 
    I/dalvikvm:  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023) 
    I/dalvikvm:  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084) 
    I/dalvikvm:  at android.app.ActivityThread.access$600(ActivityThread.java:130) 
    I/dalvikvm:  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195) 
    I/dalvikvm:  at android.os.Handler.dispatchMessage(Handler.java:99) 
    I/dalvikvm:  at android.os.Looper.loop(Looper.java:137) 
    I/dalvikvm:  at android.app.ActivityThread.main(ActivityThread.java:4745) 
    I/dalvikvm:  at java.lang.reflect.Method.invokeNative(Native Method) 
    I/dalvikvm:  at java.lang.reflect.Method.invoke(Method.java:511) 
    I/dalvikvm:  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) 
    I/dalvikvm:  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 
    I/dalvikvm:  at dalvik.system.NativeStart.main(Native Method) 

我使用目前唯一的圖像加載庫排球聯網的圖像。這是@Drawable文件中的資源。有2個版本,縱向和橫向(不想拉伸)

感謝

+0

張貼您的logcat?你使用任何圖書館進行圖片加載? – PN10

+0

請參閱編輯 – x10sion

回答

0

替換該行

options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 

它會解決你的問題

options.inSampleSize = 8; 
+0

那種作品,除了圖像現在在活動的頂部附近被壓扁了嗎? – x10sion

+0

是的,因爲inSampleSize返回一個較小的圖像來節省內存,因此,質量會下滑 –

+0

有沒有辦法讓它仍然顯示在相同的大小,但質量稍低? – x10sion

0

這裏是我通常用來計算的方法inSampleSize

private int calculateInSampleSize(BitmapFactory.Options opts, int reqWidth, int reqHeight) { 
    int outHeight = opts.outHeight; 
    int outWidth = opts.outWidth; 
    int inSampleSize = 1; 
    while (outHeight > reqHeight || outWidth > reqWidth) { 
     outHeight /= 2; 
     outWidth /= 2; 
     inSampleSize *= 2; 
    } 
    return inSampleSize; 
} 

如果你希望你的位圖適合您的ImageView,您可以使用scaleType在XML這樣的:

<ImageView 
    android:scaleType="centerCrop" 
    android:id="@+id/test_iv" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"/> 

如果你不想自己對圖像進行解碼,您可能需要使用像Glide

+0

有沒有辦法讓它仍然以相同的尺寸顯示,但質量略低,因爲我的圖像以相當長的圖像離開屏幕 – x10sion

0

一些第三方庫有一個與我的代碼出了問題(這是從Android的 自理)

它沒有錯(從某種意義上說它沒有故障)。它正在做什麼陳述。

任何人都不會有大的圖像解碼更好的辦法,所以我不明白 的OOM

Ammm ..我不這樣做,但是我可以告訴你,你可以進行更改,使這項工作。

用於計算下采樣索引的條件存在問題。我會用你的問題給出的例子來解釋它。

Configuration landscape 

XXHDPI qhd device with dimention 960x540 hence, 

    deviceWidth 960 deviceHeight 540 
    halfWidth 960 halfHeight 517 
    imgWidth 1920 imgHeight 1035 

設備寬度是必要的寬度在這裏的話,

reqWidth 960 reqHeight 540  

您使用的條件是

while ((halfHeight/inSampleSize) >= reqHeight 
       && (halfWidth/inSampleSize) >= reqWidth) { 
//--------i tried a sample size of 2. was hoping 3 would work---------// 
     inSampleSize *= 3; 
     } 

如果我們簡單地設置參數變得

while ((517/1) >= 540 
       && (960/1) >= 960) { 
//--------i tried a sample size of 2. was hoping 3 would work---------// 
     inSampleSize *= 3; 
     } 

正如你可以看到第一個條件不滿足,因此雖然循環被打破並且inSampleSize保持爲1,意味着圖像不會被重新採樣。這可能會導致OOM。

的想法是,當你走向更高的高寬比它會更容易獲得給定條件OOM,

例如圖像去, 尺寸爲2160 x 1035的圖像更有可能導致您的應用程序崩潰(注意:由於相同的原因,此圖像不會重新採樣)。

而且隨着尺寸4320 X 1035的圖像肯定會崩潰您的應用程序(注意:這不會重樣要麼)

也是如此的1035 X 4320(肖像的情況下)。

那麼要改變什麼? 條件應修改,使之做這樣的事情,

Get the large side of image, down sample it until it fits adjacent device side 

我會讓你來改變狀況,你認爲適合。

UPLDATE:

我想指出,在this答案的評論OP提到鏈接到一個要點這實際上表明你在找什麼。它還通過將位圖配置設置爲每像素16位(RGB_888使用24)的RGB_565來減小給定位圖的大小,從而進一步實現。

scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.RGB_565); 

請注意,這會降低圖像的質量。

+0

你有沒有ImageCompression的例子在我看到的要點? – x10sion

相關問題