2012-06-21 96 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,... 
} 
相关问题