6
基本上我試圖在Android應用程序中旋轉位圖(從圖像)。我想這樣做的原因是,即使垂直拍攝,從相機拍攝的照片(通過意圖)也會水平顯示,並且方向將作爲元數據保留在圖像上。糾正我,如果在錯誤的。然而,問題是,如果在裝有相當好的相機的電話上拍攝時,圖像會佔用大量內存,並且我還沒有找到方法來旋轉並保存它,而沒有出現OutOfMemoryError的風險。下面的代碼是其中i:在沒有OutOfMemoryError或縮小的情況下在Android中旋轉圖像
- 負載在圖像中
- 判斷是否需要被旋轉
- 負載按比例縮小的版本顯示在ImageView的
- 如果需要旋轉小圖像
- 在一個單獨的線程;加載,旋轉和保存圖像,所以它不需要在將來
應用程序保留圖像的分辨率是非常重要的,但任何技術與編碼是受歡迎的。我在網上搜索了幾天,找不到比我已經實施的更多的東西。這裏有另一個主題,但似乎沒有任何解決方案。希望你能幫助。
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;
}
如果有什麼事情你需要知道的或者有任何的優化,我也許可以用來減少內存使用,請寫:)謝謝
我已經創建了一個很好的JNI解決方案,通過消除最大堆大小限制障礙來避免內存不足。 [**這裏有一個鏈接**](http://stackoverflow.com/questions/14398670/android-rotating-a-bitmap-using-jni-ndk#comment20033361_14398670)到我的片段。一些注意事項: - 在代碼中將「uint16_t」的每個實例替換爲「uint32_t」(這是我詢問的代碼上的錯誤)。 - 輸入和輸出位圖必須使用8888 config(即ARGB) - 輸入位圖將在此過程中回收。 - 代碼以時鐘方式旋轉圖像90度計數器。當然你可以改變它 –