2012-08-28 45 views
1

我是android的新手,我對如何處理Bitmaps感到困惑。Android保存大型位圖

我想下載一個Bitmap,它可能很大,並將其保存到一個臨時的內部文件。然後,我將在稍後將此Bitmap繪製爲Canvas

我的當前方法是 1.下載輸入流 2.複製流 3.使用一個流使用bitmapFactory.options 4.使用另一流以完整的位圖與樣品大小進行解碼,以工作出界

但是,我需要landscapeportrait版本,所以現在我將不得不這樣做兩次並保存兩個圖像。

或者 - 我看到有人用bm.compress(Bitmap.CompressFormat.JPEG, 50, bos);來保存文件。這將旁路解碼與樣本大小直接從流中保存。我想我會使用矩陣來縮放,當我畫到我的Canvas

基本上,我很困惑這個任務的最佳方法,哪種方法不太可能遇到內存不足,是更常用的方法?

乾杯

回答

0
byte[] imagesByte = getLogoImage(Your url); 

設置爲imageview的...

imgView.setImageBitmap(BitmapFactory.decodeByteArray(imagesByte, 0, imagesByte.length)); 

方法下載

public static byte[] getLogoImage(String url){ 
      try { 
       URL imageUrl = new URL(url); 
       URLConnection ucon = imageUrl.openConnection(); 

       InputStream is = ucon.getInputStream(); 
       BufferedInputStream bis = new BufferedInputStream(is); 

       ByteArrayBuffer baf = new ByteArrayBuffer(500); 
       int current = 0; 
       while ((current = bis.read()) != -1) { 
        baf.append((byte) current); 
       } 

       return baf.toByteArray(); 
      } catch (Exception e) { 
       Log.d("ImageManager", "Error: " + e.toString()); 
      } 
      return null; 
     } 
+0

我不能使用這種方法,因爲我想保存到內部存儲器中,之後我也繪製到畫布上 - 我沒有圖像視圖。 – serenskye

0

在Android中,你必須知道é有限的內存,如此大的圖像不會適合內存,你會有OutOfMemory異常。

的關鍵是,在內部存儲保存TE圖像後,加載它在顯示分辨率:

首先下載TE形象,這應該是在UI線程之外完成,讓_urlURL intance與圖像ADDRES和_file含有字符串目標文件:

URLConnection conn = _url.openConnection(); 
     conn.connect(); 
     InputStream is = conn.getInputStream(); 
     boolean success = false; //track succesful operation 

     if(_file != null) 
     { 
      try 
      { 
       FileOutputStream fos = new FileOutputStream(_file); 
       byte data[] = new byte[4086]; //use 4086 bytes buffer 

       int count = 0; 
       while ((count = is.read(data)) != -1) 
       { 
        fos.write(data, 0, count);//write de data 
       } 

       is.close(); 
       fos.flush(); 
       fos.close(); 

       int len = conn.getContentLength(); 
       File f = new File(_file);//check fie length is correct 
       if(len== f.length()) 
       { 
        success = true; 
       } 
       else 
       { 
        //error downloading, delete de file 
        File tmp = new File(_file); 
        if(tmp.exists()) 
        { 
         tmp.delete(); 
        } 
       } 
      }catch (Exception e) 
      { 
       try 
       { 
        e.printStackTrace(); 
        //delete file with errors 
        File tmp = new File(_file); 
        if(tmp.exists()) 
        { 
         tmp.delete(); 
        } 

       } 
       catch (Exception ex) 
       { 
        ex.printStackTrace(); 
       } 
      } 
      finally 
      { 
       is.close();//cleanup 

      } 

然後當你有所需的分辨率來加載圖像,這裏的關鍵是使用BitmapFactory讀取位圖信息,並得到縮放位圖:

public static Bitmap bitmapFromFile(int width, int height, String file) 
{ 

    Bitmap bitmap = null; 

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

    if(height >0 && width > 0) { 
     options.inJustDecodeBounds = true;//only read bitmap metadata 
     BitmapFactory.decodeFile(file,options); 

     // Calculate inSampleSize 
     options.inSampleSize = calculateInSampleSize(options, width, height); 

     // Decode bitmap with inSampleSize set 
     options.inJustDecodeBounds = false; 

    } 
    try 
    { 
     bitmap = BitmapFactory.decodeFile(file, options);//decode scaled bitmap 
    }catch (Throwable t) 
    { 
     if(bitmap != null) 
     { 
      bitmap.recycle();//cleanup memory, very important! 
     } 
     return null; 

    } 
    return bitmap 
} 

的最後一步是計算比例因子:

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; 
     final int halfWidth = width; 

     // 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 ((couldShrink(halfWidth, reqWidth, inSampleSize)&& 
       couldShrink(halfHeight,reqHeight, inSampleSize)) 
       //&&(halfHeight*halfWidth)/inSampleSize > maxsize) 
       ) 
     { 
      inSampleSize *= 2; 
     } 

    } 

    return inSampleSize; 
} 
private static boolean couldShrink (int dimension, int req_dimension, int divider) 
{ 
    int actual = dimension/divider; 
    int next = dimension/(divider*2); 

    int next_error = Math.abs(next - req_dimension); 
    int actual_error = Math.abs(actual-req_dimension); 

    return next > req_dimension || 
      (actual > req_dimension && (next_error < actual_error)) 
      ; 
} 

,如果你想通過做手工也就是說,我建議你使用Picasso將處理donwloading,磁盤緩存和內存緩存你的形象:

要加載到ImageView的名爲image呈現出化背景(R.drawable.img_bg),而下載:

Picasso.with(image.getContext()) 
      .load(url).placeholder(R.drawable.img_bg).fit() 
        .into(image, new Callback.EmptyCallback() 
        { 
         @Override 
         public void onSuccess() 
         { 
          holder.progress.setVisibility(View.GONE); //hide progress bar 
         } 

         @Override 
         public void onError() 
         { 
          holder.progress.setVisibility(View.GONE); //hide progress bar 
          //do whatever you design to show error 
         } 
        }); 

自己處理位圖:

//first declare a target 
_target = new Target() 
    { 
     @Override 
     public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) 
     { 
      //handle your bitmap (store it and use it on you canvas 
     } 

     @Override 
     public void onBitmapFailed(Drawable errorDrawable) 
     { 
      //handle your fail state 

     } 

     @Override 
     public void onPrepareLoad(Drawable placeHolderDrawable) 
     {//for example for drawing a placeholder while downloading 
     } 
    }; 

現在你只需要加載和調整圖片大小:

Picasso.with(context).load(url).resize(192, 192).centerCrop().into(_target); 

希望有所幫助。