2016-08-19 58 views
0

我一直在努力改變從服務器上下載的位圖的大小,因爲我知道這是我收到的OOM錯誤的問題。我已經嘗試了下面的其他例子,以及https://developer.android.com/training/displaying-bitmaps/load-bitmap.html,但我無法做出正面或反面的關於如何使用它以及在哪裏使用它。我想將我的位圖縮放到屏幕分辨率,但無法縫製出來。感謝您的幫助。在android中更改位圖的大小以避免OOM

也不是說這是在AsyncTask,如果這是有所作爲的話。

這裏是我的設置位圖代碼:

public class ImageDownloaderTask extends AsyncTask<String, Void, Bitmap> { 

BitmapFactory.Options options = new BitmapFactory.Options(); 

private final WeakReference<ImageView> imageViewReference; 
Resources resources; 

public ImageDownloaderTask(ImageView imageView) { 
    imageViewReference = new WeakReference<ImageView>(imageView); 
} 


@Override 
protected Bitmap doInBackground(String... params) 
{ 
    return downloadBitmap(params[0]); 
} 
@Override 
protected void onPostExecute(Bitmap bitmap) { 
    if (isCancelled()) { 
     bitmap = null; 
     Log.d("HTTPS No go", bitmap.toString()); 
    } 

    if (imageViewReference != null) { 
     ImageView imageView = imageViewReference.get(); 
     if (imageView != null) { 
      if (bitmap != null) { 
       //Scale the bitmap to a smaller size 
       imageView.setImageBitmap(bitmap); 
      } else { 
       Log.d("Downloading the image: ", "No Image found"); 
      } 
     } 

    } 
} 

//URL connection to download the image 
private Bitmap downloadBitmap(String url) { 

    HttpURLConnection urlConnection = null; 
      try{ 
      URL uri = new URL(url); 
      urlConnection = (HttpURLConnection) uri.openConnection(); 
      urlConnection.setRequestMethod("GET"); 
      int statusCode = urlConnection.getResponseCode(); 
      //check if the HTTP status code is equal to 200, which means that it is ok 
      if (statusCode != 200) { 
       return null; 
      } 

      InputStream inputStream = urlConnection.getInputStream(); 
      if (inputStream != null) { 

       /* 
       options.inJustDecodeBounds = true; 
       Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, options); 
       int imageHeight = options.outHeight; 
       int imageWidth = options.outWidth; 
       String imageType = options.outMimeType; 
       int sampleSize = calculateInSampleSize(options, imageWidth, imageHeight); 
       */ 
       Bitmap bitmap = BitmapFactory.decodeStream(inputStream); 
       return bitmap; 
      } 
      }catch (ProtocolException e) { 
       e.printStackTrace(); 
      } catch (MalformedURLException e) { 
       e.printStackTrace(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } {} 

    return null; 
} 

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; 
} 

} 

UPDATE:

這個固定了一下。它允許我僅註銷一次,但是當我第二次註銷時,它會與舊的OOM錯誤一起崩潰。

InputStream inputStream = urlConnection.getInputStream(); 
      if (inputStream != null) { 

       BitmapFactory.Options options = new BitmapFactory.Options(); 
       options.inSampleSize=1; //try to decrease decoded image 

       Bitmap bitmap = BitmapFactory.decodeStream(inputStream , null, options); 
       return bitmap; 
      } 
      }catch (ProtocolException e) { 
       e.printStackTrace(); 
      } catch (MalformedURLException e) { 
       e.printStackTrace(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } {} 
+1

你可以發佈你所有的'AsyncTask'代碼嗎? –

+0

添加@ L.Swifter – MNM

+0

@MNM您想調整大小與固定大小成比例,如128 * 128的圖像。 –

回答

0

感謝大家幫忙。我發現我的問題不是下載位圖的大小,因爲我每次將它們添加到我的回收視圖中時會自動調整它們的大小。這是由於我在登錄頁面上玩過的gif造成的,這個gif佔用了大量的內存,一旦其他任何東西佔用了內存,它就會終止該設備。

我真的很感謝大家,謝謝。我認爲我自己的問題是下載圖像,因爲這是通常的習慣。

1

我用這個代碼:

Bitmap outBitmap; 

    // Decode image size 
    BitmapFactory.Options o = new BitmapFactory.Options(); 
    o.inJustDecodeBounds = true; 
    BitmapFactory.decodeFile(photoPath, o); 

    // The new size we want to scale to ensure memory usage is optimal 
    int targetWidth; 
    int targetHeight; 
    if (o.outHeight > o.outWidth) { 
     targetWidth = getResources().getInteger(R.integer.pic_width_px); 
     targetHeight = getResources().getInteger(R.integer.pic_height_px); 
    } else if (o.outHeight == o.outWidth) { 
     targetWidth = targetHeight = getResources().getInteger(R.integer.pic_width_px); 
    } else { 
     targetWidth = getResources().getInteger(R.integer.pic_width_px); 
     targetHeight = getResources().getInteger(R.integer.pic_height_px); 
    } 

    if (o.outWidth <= targetWidth && o.outHeight <= targetHeight) { 
     // Return image as is without any additional scaling 
     Bitmap origBitmap = BitmapFactory.decodeFile(photoPath, null); 
     outBitmap = Bitmap.createBitmap(origBitmap, 0, 0, o.outWidth, o.outHeight, m, true); 
     origBitmap.recycle(); 

     return outBitmap; 
    } 

    // Find the correct scale value. It should be the power of 2. 
    int scale = 1; 
    while(o.outWidth/scale/2 >= targetWidth && 
      o.outHeight/scale/2 >= targetHeight) { 
     scale *= 2; 
    } 

    // Decode with inSampleSize 
    BitmapFactory.Options scaleOptions = new BitmapFactory.Options(); 
    scaleOptions.inSampleSize = scale; 

    Bitmap scaledBitmap = BitmapFactory.decodeFile(photoPath, scaleOptions); 
    return Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), m, true); 
1

我認爲你需要改變你的圖像的大小才能觀看它進入記憶。

private Bitmap downloadBitmap(String url) { 

    HttpURLConnection urlConnection = null; 
      try{ 
      URL uri = new URL(url); 
      urlConnection = (HttpURLConnection) uri.openConnection(); 
      urlConnection.setRequestMethod("GET"); 
      int statusCode = urlConnection.getResponseCode(); 
      //check if the HTTP status code is equal to 200, which means that it is ok 
      if (statusCode != 200) { 
       return null; 
      } 

      InputStream inputStream = urlConnection.getInputStream(); 
      if (inputStream != null) { 

       //scale down the image and load 
       options.inJustDecodeBounds = true; 
       Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, options); 
       options.inSampleSize = calculateInSampleSize(options, 100, 100); 
       options.inJustDecodeBounds = false; 
       return BitmapFactory.decodeStream(inputStream, null, options); //I'm not sure here, because the inputStream used twice. 
      } 
      }catch (ProtocolException e) { 
       e.printStackTrace(); 
      } catch (MalformedURLException e) { 
       e.printStackTrace(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } {} 

    return null; 
} 
1

幾天前我面臨同樣的問題。理論上有兩種方法可以做到這一點。要麼你完全下載圖像,然後調整圖像大小,或者你必須要求你的服務器這樣做,而不是應用程序。我更喜歡第二種解決方案,我發送所需的寬度,高度和所需的圖像。服務器計算可能的比例,然後縮小尺寸並返回,打印圖像。之後,我只需使用HttpURLConnection下載位圖,並從連接的輸入流創建位圖,而不會出現任何問題。

你的錯誤怎麼樣,也許你試圖先從流計算然後創建它。當然,它會導致崩潰,因爲您正在嘗試第二次讀取輸入流。您的光標已經移動到流中,同時閱讀圖像的元數據來學習大小。現在,當它嘗試創建位圖時,它會失敗,導致它不從流的第0個字節開始。但是在中間的某個地方,光標上次停止。因此,如果需要兩次讀取流,則需要首先將輸入流複製到某處,以便能夠讀取流兩次。希望它可以幫助你。