Về cơ bản, tôi đang cố xoay một ảnh bitmap (từ hình ảnh) trong Ứng dụng Android. Lý do tại sao tôi muốn làm điều này là một bức ảnh chụp từ máy ảnh (thông qua một ý định) được hiển thị theo chiều ngang ngay cả khi nó được chụp theo chiều dọc, và hướng được giữ như siêu dữ liệu trên hình ảnh. Sửa tôi nếu sai. Tuy nhiên, vấn đề là hình ảnh sẽ mất rất nhiều bộ nhớ khi được nạp vào, nếu được chụp trên điện thoại có camera tốt hợp lý và tôi không tìm thấy cách xoay và lưu nó mà không có nguy cơ bị OutOfMemoryError . Đoạn code dưới đây là nơi tôi:Xoay hình ảnh trong Android mà không có lỗi OutOfMemoryError hoặc downscaling
- tải trong hình ảnh
- Kiểm tra nếu nó cần phải được luân chuyển
- tải một phiên bản thu nhỏ để trưng bày trong một ImageView
- Xoay hình ảnh nhỏ nếu cần thiết
- Trong một chủ đề riêng biệt; tải, xoay và lưu hình ảnh, do đó, không cần phải trong tương lai
Điều quan trọng là phải giữ hình ảnh ở độ phân giải, nhưng mọi thủ thuật với mã hóa đều được chào đón. Tôi đã tìm kiếm trên Internet trong một vài ngày, không thể tìm thấy bất cứ điều gì nhiều hơn những gì tôi đã thực hiện. Có một chủ đề khác về chủ đề ở đây, nhưng dường như không có giải pháp nào. Hy vọng bạn có thể giúp đỡ.
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;
}
Nếu có bất cứ điều gì bạn cần phải biết hoặc có bất kỳ tối ưu hóa tôi có thể có thể sử dụng để giảm thiểu sử dụng bộ nhớ, xin vui lòng viết :) Cảm ơn
i đã tạo ra một giải pháp JNI tốt để tránh bộ nhớ ngoài bằng cách loại bỏ rào cản giới hạn kích thước heap tối đa. [** đây là liên kết **] (http://stackoverflow.com/questions/14398670/android-rotating-a-bitmap-using-jni-ndk#comment20033361_14398670) vào đoạn trích của tôi. một số lưu ý: - thay thế trong mã mỗi trường hợp của "uint16_t" với "uint32_t" (đó là lỗi trên mã của tôi mà tôi đã hỏi). - bitmap đầu vào và đầu ra phải có cấu hình 8888 (là ARGB) - bitmap đầu vào sẽ được tái chế trong quá trình xử lý. - mã xoay hình ảnh 90 đồng hồ đếm ngược suy thoái. tất nhiên bạn có thể thay đổi tùy theo –