2016-08-19 54 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个字节开始。但是在中间的某个地方,光标上次停止。因此,如果需要两次读取流,则需要首先将输入流复制到某处,以便能够读取流两次。希望它可以帮助你。