2012-06-21 69 views
6

基本上我試圖在Android應用程序中旋轉位圖(從圖像)。我想這樣做的原因是,即使垂直拍攝,從相機拍攝的照片(通過意圖)也會水平顯示,並且方向將作爲元數據保留在圖像上。糾正我,如果在錯誤的。然而,問題是,如果在裝有相當好的相機的電話上拍攝時,圖像會佔用大量內存,並且我還沒有找到方法來旋轉並保存它,而沒有出現OutOfMemoryError的風險。下面的代碼是其中i:在沒有OutOfMemoryError或縮小的情況下在Android中旋轉圖像

  1. 負載在圖像中
  2. 判斷是否需要被旋轉
  3. 負載按比例縮小的版本顯示在ImageView的
  4. 如果需要旋轉小圖像
  5. 在一個單獨的線程;加載,旋轉和保存圖像,所以它不需要在將來

應用程序保留圖像的分辨率是非常重要的,但任何技術與編碼是受歡迎的。我在網上搜索了幾天,找不到比我已經實施的更多的東西。這裏有另一個主題,但似乎沒有任何解決方案。希望你能幫助。

public Bitmap getBitmap(final Context c) { 
    if (bitmap != null) 
     return bitmap; 

    final int rotate = necessaryRotation(c, file); 
    // if(rotate != 0) rotateImageFile(c, rotate); 

    try { 
     // Get scaled version 
     BitmapFactory.Options options = new BitmapFactory.Options(); 
     options.inJustDecodeBounds = true; 
     BitmapFactory.decodeFile(file, options); 
     options.inSampleSize = calcInSampleSize(options, 1024, 1024); 
     options.inJustDecodeBounds = false; 
     bitmap = BitmapFactory.decodeFile(file, options); 

     // rotate? 
     bitmap = rotateImage(c,bitmap,rotate); 

     System.out.println("Bitmap loaded from file: size=" 
       + bitmap.getWidth() + "," + bitmap.getHeight()); 

     System.gc(); 
    } catch (Exception e) { 
     System.err.println("Unable to load image file: " 
       + this.getFilename()); 
    } 

    // if rotation is needed, do it in worker thread for next time 
    if(rotate != 0){ 
     Thread t = new Thread(new Runnable(){ 

      public void run() { 
       // load entire image 
       try{ 
        File imageFile = new File(getFilename()); 
        Bitmap huge = Media.getBitmap(c.getContentResolver(), 
        Uri.fromFile(imageFile)); 

        huge = rotateImage(c,huge,rotate); 

        // save bitmap properly 
        FileOutputStream out = new FileOutputStream(imageFile); 
        huge.compress(Bitmap.CompressFormat.PNG, 100, out); 

        out.flush(); 
        out.close(); 
        huge.recycle(); 
        huge = null; 
        out = null; 
        System.gc(); 

       }catch(IOException e){ 
        e.printStackTrace(); 
       } 
      } 

     }); 
     t.start(); 
    } 

    return bitmap; 
} 

private Bitmap rotateImage(Context c, Bitmap bitmap, int rotate) { 
    if (rotate != 0) { 
     // rotate 
     Matrix m = new Matrix(); 
     m.postRotate(rotate); 
     Bitmap rotImage = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), 
       bitmap.getHeight(), m, true); 
     bitmap.recycle(); 

     System.out.println("Image (id=" + getId() 
       + ") rotated successfully"); 

     System.gc(); 

     return rotImage; 
    } 
    return bitmap; 
} 

private int necessaryRotation(Context c, String imageFile) { 
    int rotate = 0; 
    ExifInterface exif; 
    try { 
     exif = new ExifInterface(imageFile); 
     int orientation = exif.getAttributeInt(
       ExifInterface.TAG_ORIENTATION, 
       ExifInterface.ORIENTATION_NORMAL); 

     switch (orientation) { 
     case ExifInterface.ORIENTATION_ROTATE_270: 
      rotate = 270; 
      break; 
     case ExifInterface.ORIENTATION_ROTATE_180: 
      rotate = 180; 
      break; 
     case ExifInterface.ORIENTATION_ROTATE_90: 
      rotate = 90; 
      break; 
     } 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

    return rotate; 
} 

private int calcInSampleSize(BitmapFactory.Options options, int reqWidth, 
     int reqHeight) { 
    int height = options.outHeight; 
    int width = options.outWidth; 
    int inSampleSize = 1; 
    while (height > reqHeight || width > reqWidth) { 
     height /= 2; 
     width /= 2; 
     inSampleSize *= 2; 
    } 

    return inSampleSize; 
} 

如果有什麼事情你需要知道的或者有任何的優化,我也許可以用來減少內存使用,請寫:)謝謝

+0

我已經創建了一個很好的JNI解決方案,通過消除最大堆大小限制障礙來避免內存不足。 [**這裏有一個鏈接**](http://stackoverflow.com/questions/14398670/android-rotating-a-bitmap-using-jni-ndk#comment20033361_14398670)到我的片段。一些注意事項: - 在代碼中將「uint16_t」的每個實例替換爲「uint32_t」(這是我詢問的代碼上的錯誤)。 - 輸入和輸出位圖必須使用8888 config(即ARGB) - 輸入位圖將在此過程中回收。 - 代碼以時鐘方式旋轉圖像90度計數器。當然你可以改變它 –

回答

0

試試這個片斷:

private Bitmap rotateImage(Context c, Bitmap bitmap, int rotate) { 
    .... 

    // reduce byte per pixel 
    bitmap = bitmap.copy(Bitmap.Config.RGB_565, false); 

    Bitmap.createBitmap(bitmap,... 
} 
相關問題