Android部分手机拍照后获取的图片被旋转问题的解决方法

调用Android系统拍照功能后,三星手机拍摄后的照片被旋转了90度,横着拍给你变成竖的,竖的拍给你变成横的。其它品牌的手机都是正常的,就三星出现这个怪事。

在Android适配上,我原来一直以为国内的小米手机够奇葩了,结果还有更奇葩的!你说你没事旋转照片干啥,实在是猜不透其居心何在,纯粹是在给开发者制造麻烦啊!

解决办法是获取到拍照后照片被旋转的角度,再旋转回去就好了。

具体思路:
1、首先在调用拍照方法时,保存拍照后的相片原图,得到原图路径,(PhotoBitmapUtils是我自己写的一个工具类)

String fileName = "";
/**
 * 启动相机拍照
 */
private void addBitmapShoots() {
  Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  // 设置图片要保存的 根路径+文件名
  fileName = PhotoBitmapUtils.getPhotoFileName(getContext());
  File file = new File(fileName);
  if (!file.exists()) {
    try {
      file.createNewFile();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
  intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
  startActivityForResult(intent, OPEN_CAMERA);
}

2、在获取相机返回的回调方法onActivityResult()中,修复被旋转的图片并取得修复后的图片路径,有了这个路径后就可以展示出来了

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  // 获取相机拍照返回
  if (resultCode == Activity.RESULT_OK && requestCode == OPEN_CAMERA) {
    // 得到修复后的照片路径
    String filepath = PhotoBitmapUtils.amendRotatePhoto(fileName, getContext());
  }
}

PhotoBitmapUtils类:

/**
 * 集合一些图片工具
 *
 * Created by zhuwentao on 2016-07-22.
 */
public class PhotoBitmapUtils { 

  /**
   * 存放拍摄图片的文件夹
   */
  private static final String FILES_NAME = "/MyPhoto";
  /**
   * 获取的时间格式
   */
  public static final String TIME_STYLE = "yyyyMMddHHmmss";
  /**
   * 图片种类
   */
  public static final String IMAGE_TYPE = ".png"; 

  // 防止实例化
  private PhotoBitmapUtils() {
  } 

  /**
   * 获取手机可存储路径
   *
   * @param context 上下文
   * @return 手机可存储路径
   */
  private static String getPhoneRootPath(Context context) {
    // 是否有SD卡
    if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)
        || !Environment.isExternalStorageRemovable()) {
      // 获取SD卡根目录
      return context.getExternalCacheDir().getPath();
    } else {
      // 获取apk包下的缓存路径
      return context.getCacheDir().getPath();
    }
  } 

  /**
   * 使用当前系统时间作为上传图片的名称
   *
   * @return 存储的根路径+图片名称
   */
  public static String getPhotoFileName(Context context) {
    File file = new File(getPhoneRootPath(context) + FILES_NAME);
    // 判断文件是否已经存在,不存在则创建
    if (!file.exists()) {
      file.mkdirs();
    }
    // 设置图片文件名称
    SimpleDateFormat format = new SimpleDateFormat(TIME_STYLE, Locale.getDefault());
    Date date = new Date(System.currentTimeMillis());
    String time = format.format(date);
    String photoName = "/" + time + IMAGE_TYPE;
    return file + photoName;
  } 

  /**
   * 保存Bitmap图片在SD卡中
   * 如果没有SD卡则存在手机中
   *
   * @param mbitmap 需要保存的Bitmap图片
   * @return 保存成功时返回图片的路径,失败时返回null
   */
  public static String savePhotoToSD(Bitmap mbitmap, Context context) {
    FileOutputStream outStream = null;
    String fileName = getPhotoFileName(context);
    try {
      outStream = new FileOutputStream(fileName);
      // 把数据写入文件,100表示不压缩
      mbitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);
      return fileName;
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    } finally {
      try {
        if (outStream != null) {
          // 记得要关闭流!
          outStream.close();
        }
        if (mbitmap != null) {
          mbitmap.recycle();
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  } 

  /**
   * 把原图按1/10的比例压缩
   *
   * @param path 原图的路径
   * @return 压缩后的图片
   */
  public static Bitmap getCompressPhoto(String path) {
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = false;
    options.inSampleSize = 10; // 图片的大小设置为原来的十分之一
    Bitmap bmp = BitmapFactory.decodeFile(path, options);
    options = null;
    return bmp;
  } 

  /**
   * 处理旋转后的图片
   * @param originpath 原图路径
   * @param context 上下文
   * @return 返回修复完毕后的图片路径
   */
  public static String amendRotatePhoto(String originpath, Context context) { 

    // 取得图片旋转角度
    int angle = readPictureDegree(originpath); 

    // 把原图压缩后得到Bitmap对象
    Bitmap bmp = getCompressPhoto(originpath);; 

    // 修复图片被旋转的角度
    Bitmap bitmap = rotaingImageView(angle, bmp); 

    // 保存修复后的图片并返回保存后的图片路径
    return savePhotoToSD(bitmap, context);
  } 

  /**
   * 读取照片旋转角度
   *
   * @param path 照片路径
   * @return 角度
   */
  public static int readPictureDegree(String path) {
    int degree = 0;
    try {
      ExifInterface exifInterface = new ExifInterface(path);
      int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
      switch (orientation) {
        case ExifInterface.ORIENTATION_ROTATE_90:
          degree = 90;
          break;
        case ExifInterface.ORIENTATION_ROTATE_180:
          degree = 180;
          break;
        case ExifInterface.ORIENTATION_ROTATE_270:
          degree = 270;
          break;
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
    return degree;
  } 

  /**
   * 旋转图片
   * @param angle 被旋转角度
   * @param bitmap 图片对象
   * @return 旋转后的图片
   */
  public static Bitmap rotaingImageView(int angle, Bitmap bitmap) {
    Bitmap returnBm = null;
    // 根据旋转角度,生成旋转矩阵
    Matrix matrix = new Matrix();
    matrix.postRotate(angle);
    try {
      // 将原始图片按照旋转矩阵进行旋转,并得到新的图片
      returnBm = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
    } catch (OutOfMemoryError e) {
    }
    if (returnBm == null) {
      returnBm = bitmap;
    }
    if (bitmap != returnBm) {
      bitmap.recycle();
    }
    return returnBm;
  }
} 

在调用修复图片角度方法的时候需要注意,现在的手机像素越来越大,拍完后一张照片有近10M,所以我们需要对图片进行压缩处理。不然在保存图片时会等待挺久的,屏幕会黑一会。
参考文档1
参考文档2

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android 7.0中拍照和图片裁剪适配的问题详解

    前言 Android 7.0系统发布后,拿到能升级的nexus 6P,就开始了7.0的适配.发现在Android 7.0以上,在相机拍照和图片裁剪上,可能会碰到以下一些错误: Process: com.yuyh.imgsel, PID: 22995 // 错误1 android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/com.yuyh.imgsel/cache/1486438962645.jpg ex

  • Android获取本地相册图片和拍照获取图片的实现方法

    需求:从本地相册找图片,或通过调用系统相机拍照得到图片. 容易出错的地方: 1.当我们指定了照片的uri路径,我们就不能通过data.getData();来获取uri,而应该直接拿到uri(用全局变量或者其他方式)然后设置给imageView imageView.setImageURI(uri); 2.我发现手机前置摄像头拍出来的照片只有几百KB,直接用imageView.setImageURI(uri);没有很大问题,但是后置摄像头拍出来的照片比较大,这个时候使用imageView.setIm

  • Android判断是否有拍照权限的实例代码

    下面一段代码给大家介绍android判断是否有拍照权限,具体代码如下所示: /** * 返回true 表示可以使用 返回false表示不可以使用 */ public boolean cameraIsCanUse() { boolean isCanUse = true; Camera mCamera = null; try { mCamera = Camera.open(); Camera.Parameters mParameters = mCamera.getParameters(); //针对

  • Android仿微信单击拍照长按录像功能实例代码

    此文章是看郭神公众号发的一篇,仅作学习. 在modlue gradle中添加 compile 'cjt.library.wheel:camera:0.0.7' 在project gradle中添加 compile 'cjt.library.wheel:camera:0.0.7' 添加的地方是 allprojects { repositories { jcenter() /*在此处添加*/ } } 使用起来很方便,只需在xml布局中 <com.cjt2325.cameralibrary.JCame

  • Android通过手机拍照或从本地相册选取图片设置头像

    像微信.QQ.微博等社交类的APP,通常都有设置头像的功能,设置头像通常有两种方式: 1.让用户通过选择本地相册之类的图片库中已有的图像,裁剪后作为头像. 2.让用户启动手机的相机拍照,拍完照片后裁剪,然后作为头像. 我现在写一个简单的完整代码例子,说明如何在android中实现上述两个头像设置功能. MainActivity.Java文件: package zhangpgil.photo; import java.io.File; import android.support.v7.app.A

  • Android 通过Intent调用系统拍照程序出现图片太小的问题解决办法

    Android 通过Intent调用系统拍照程序出现图片太小的问题解决办法 Intent it = newIntent("android.media.action.IMAGE_CAPTURE"); startActivityForResult(it, Activity.DEFAULT_KEYS_DIALER); 按下拍照键后,会返回到你的activity,所以你的activity要在onActivityResult方法里加一个处理, protectedvoidonActivityRes

  • Android自定义相机实现定时拍照功能

    这篇博客为大家介绍Android自定义相机,并且实现倒计时拍照功能. 首先自定义拍照会用到SurfaceView控件显示照片的预览区域,以下是布局文件: activity_main.xml <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="m

  • Android Camera实现毫秒级拍照实例

    我们知道自定义Camera需要以下几步 打开相机,即实例化Camera对象,Camera camera = Camera.open(); 设置Camera的相关参数,Camera.Parameters parameters = camera.getParameters(); 打开预览,camera.setPreviewDisplay(surfaceholder); camera.startPreview(); 获取图片,这里只是从预览中获取因此使用,camera.setPreviewCallb

  • Android自定义组件获取本地图片和相机拍照图片

    iOS中有封装好的选择图片后长按出现动画删除效果,效果如下 而Android找了很久都没有找到有这样效果的第三方组件,最后懒得找了还是自己实现这效果吧 选择图片后还可对图片进行剪裁 当然,代码中还有很多不完善的地方,我接下来会继续完善这个组件的 已经上传到开源社区,欢迎大家来Star啊~ Demo源码:传送门 设计中的碰到的一些问题和解决思路 1.如何让加号图片显示在GridView最后面 首先在调用GridAdapter构造方法时就加载加号图片 /** * 图片适配器 * @param con

  • Android部分手机拍照后获取的图片被旋转问题的解决方法

    调用Android系统拍照功能后,三星手机拍摄后的照片被旋转了90度,横着拍给你变成竖的,竖的拍给你变成横的.其它品牌的手机都是正常的,就三星出现这个怪事. 在Android适配上,我原来一直以为国内的小米手机够奇葩了,结果还有更奇葩的!你说你没事旋转照片干啥,实在是猜不透其居心何在,纯粹是在给开发者制造麻烦啊! 解决办法是获取到拍照后照片被旋转的角度,再旋转回去就好了. 具体思路: 1.首先在调用拍照方法时,保存拍照后的相片原图,得到原图路径,(PhotoBitmapUtils是我自己写的一个

  • 解决android有的手机拍照后上传图片被旋转的问题

    需求:做仿新浪发微博的项目,能够上传图片还有两外一个项目用到手机拍摄图片,这两个都需要把图片上传到服务器 遇到问题:有的手机拍摄的图片旋转90度,有的图片旋转了180度,有的手机是正常的,服务器要求的是正的,这样问题就来了,不能用户发个照片在微博上看到的是被旋转了的啊,另外一个项目里旋转了的图片直接匹配出现问题,这个更严重. 解决:开始的时候在网上没有找到很好的解决办法,谷歌百度的搜了一通,想到第一种解决方式,当手机拍照结束,在返回结果处理里面立即跳转到一个新的页面,在新的页面里让用户自己手动去

  • Android应用中拍照后获取照片路径并上传的实例分享

    Activity 中的代码,我只贴出重要的事件部分代码 public void doPhoto(View view) { destoryBimap(); String state = Environment.getExternalStorageState(); if (state.equals(Environment.MEDIA_MOUNTED)) { Intent intent = new Intent("android.media.action.IMAGE_CAPTURE"); s

  • php更新mysql后获取影响的行数发生异常解决方法

    从manual上知道了mysql_affected_rows函数当UPDATE前后的数据一样时会返回异常值, 下面有个方便的解决办法,从官方munual上看到 bdobrica at gmail dot com 留言的: As a solution to the problem pointed in the post reffering to mysql_affected_rows() returning 0 when you are making an update query and the

  • Android手机拍照或选取图库图片作为头像

    package zhangpgil.photo; import java.io.File; import android.support.v7.app.ActionBarActivity; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.Toast; import android.content.Intent; import

  • Android圆形头像拍照后“无法加载此图片”的问题解决方法(适配Android7.0)

    Feature: 点击选择拍照或者打开相册,选取图片进行裁剪最后设置为圆形头像. Problem: 拍好照片,点击裁剪,弹Toast"无法加载此图片". Solution: 在裁剪的class里加两行代码 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 主要代码如下: public static final S

  • Android调用手机拍照功能的方法

    本文实例讲述了Android调用手机拍照功能的方法.分享给大家供大家参考.具体如下: 一.main.xml布局文件: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" andr

  • Android 录制手机屏幕视频生成GIF图片实例详解

    Android 录制手机屏幕视频生成GIF图片实例详解 无图无真相,在我们日常的网络交流中往往需要给交流对象提供直观的显示,而视频是一个很好的方式,但是视频需要播放器,还需要当做文件进行对点传输,并不是很方便.想CSDN这样的博客网站也并不支持在博客里放视频这种方式,除非你贴外链,太烦了不是么.最好是如下图这种gif方式,直观 今天来教大家一个易操作的录制方式.当然,一般只适合Android开发者.因为你需要有AndroidStudio 工具 AndroidStudio(完成手机屏幕的视频录制,

  • Android百度地图定位后获取周边位置的实现代码

    本文实例讲解Android百度地图定位后获取周边位置的实现代码,分享给大家供大家参考,具体内容如下 效果图: 具体代码: 1.布局文件 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical&q

随机推荐