使用Bitmap压缩图片后上传至Firebase Storage出现90度旋转问题
图片上传Firebase Storage后90度旋转问题解决
问题原因
手机拍摄的照片会在EXIF元数据中记录拍摄方向(比如竖拍时标记为90度旋转),但MediaStore.Images.Media.getBitmap()获取的Bitmap不会自动应用该方向信息。直接压缩上传后,图片的方向元数据丢失,导致显示时出现90度顺时针旋转。
解决方案
通过读取图片的EXIF方向信息,手动旋转Bitmap后再进行压缩上传。
步骤1:添加获取EXIF方向的方法
private int getExifOrientation(Context context, Uri uri) { ExifInterface exif = null; try { InputStream inputStream = context.getContentResolver().openInputStream(uri); exif = new ExifInterface(inputStream); } catch (IOException e) { e.printStackTrace(); } return exif != null ? exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL) : ExifInterface.ORIENTATION_NORMAL; }
步骤2:添加Bitmap旋转方法
private Bitmap rotateBitmap(Bitmap bitmap, int orientation) { Matrix matrix = new Matrix(); switch (orientation) { case ExifInterface.ORIENTATION_ROTATE_90: matrix.postRotate(90); break; case ExifInterface.ORIENTATION_ROTATE_180: matrix.postRotate(180); break; case ExifInterface.ORIENTATION_ROTATE_270: matrix.postRotate(270); break; default: return bitmap; } try { Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); bitmap.recycle(); // 释放原Bitmap资源,避免内存泄漏 return rotatedBitmap; } catch (OutOfMemoryError e) { e.printStackTrace(); return bitmap; } }
步骤3:修改上传代码
在获取Bitmap后,先读取EXIF方向并旋转图片,再执行压缩上传:
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == 123 && resultCode == RESULT_OK && data != null) { Uri imageUri = data.getData(); Bitmap bmp = null; try { bmp = MediaStore.Images.Media.getBitmap(getContentResolver(), imageUri); // 获取图片EXIF方向并旋转Bitmap int orientation = getExifOrientation(this, imageUri); bmp = rotateBitmap(bmp, orientation); } catch (IOException e) { e.printStackTrace(); } ByteArrayOutputStream baos = new ByteArrayOutputStream(); bmp.compress(Bitmap.CompressFormat.JPEG, 35, baos); byte[] datasa = baos.toByteArray(); StorageReference filePath = UserProfilePics.child(UserID + ".jpg"); filePath.putBytes(datasa).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() { @Override public void onComplete(@NonNull Task<UploadTask.TaskSnapshot> task) { if (task.isSuccessful()) { Toast toast = new Toast(getApplicationContext()); toast.setDuration(Toast.LENGTH_LONG); View custom_view = getLayoutInflater().inflate(R.layout.toast_icon_text, null); ((TextView) custom_view.findViewById(R.id.message)).setText("Profile image updated successfully"); ((ImageView) custom_view.findViewById(R.id.icon)).setImageResource(R.drawable.ic_baseline_done_24); ((CardView) custom_view.findViewById(R.id.parent_view)).setCardBackgroundColor(getResources().getColor(R.color.green_500)); toast.setView(custom_view); toast.show(); } } }); } }
注意事项
- Android 10及以上版本,需申请
READ_EXTERNAL_STORAGE权限(或使用MediaStore API进行适配),否则可能无法读取EXIF信息。 - 旋转后回收原Bitmap,避免内存占用过高导致OOM。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

