2012-06-21 2 views
6

기본적으로 안드로이드 애플 리케이션에서 비트 맵 (이미지에서) 회전하려고합니다. 이 작업을 수행하려는 이유는 카메라에서 찍은 사진 (의도를 통해)이 세로로 캡처 되어도 가로로 표시되고 이미지의 방향이 메타 데이터로 유지된다는 것입니다. 잘못하면 나를 바로 잡으십시오. 그러나 문제는 이미지가로드 될 때 많은 양의 메모리가 필요하다는 것입니다. OutOfMemoryError가 발생하지 않고 이미지를 회전하고 저장하는 방법을 찾지 못했습니다. . 필요한 경우OutOfMemoryError 또는 다운 스케일없이 안드로이드에서 이미지 회전

  1. 이미지의로드가 이미지 뷰
  2. 부하 표시 용의 축소 된 버전을 회전 할 필요가있는 경우
  3. 체크가 작은 화상을 를 회전
  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 구성 (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,... 
} 
관련 문제