Android系统Camera图片反转的一个问题

2023-05-16

一、问题提出

  目前遇到项目问题,Camera预览图像是反的,于是考虑设置180度反转以便正常。

  通过如下两种方式:

  params.setRotation(180); //java部分

  p.set(CameraParameters::KEY_ROTATION,180); //C部分

  发现应用部分takepicture出来数据都没有变化。

代码片段如下:

Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
/*              
Matrix matrix = new Matrix();  
matrix.setRotate(180);
int width = bitmap.getWidth();  
int height = bitmap.getHeight(); 
bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
*/               
File out = new File("/data/");
if (!out.exists()) {
  out.mkdirs();
}
out = new File("/data/", "1.jpg");
try {
  FileOutputStream outStream = new FileOutputStream(out);
  bitmap.compress(CompressFormat.JPEG, 100, outStream);
  outStream.close();
} catch (Exception e) {
  e.printStackTrace();
}
  上边屏蔽部分打开后ok,屏蔽后有问题;屏蔽部分完成反转功能,证明图片本身有问题。

二、逐层排查

1.frameworks/av/services/camera/libcameraservice/CameraClient.cpp

void CameraClient::dataCallback(int32_t msgType,
        const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata, void* user) {
  int takepicture_fd;
  takepicture_fd = open("/data/tankai.jpg",O_WRONLY|O_CREAT,00700);
  ALOGD("TK---------->>>>JPEG,dataPtr->size() is %d,takepicture_fd is %d\n",dataPtr->size(),takepicture_fd);
  ALOGD("TK---------->>>>JPEG,dataPtr->size() is 0x%x\n",dataPtr->pointer());
  int write_len = write(takepicture_fd, dataPtr->pointer(), dataPtr->size());
  close(takepicture_fd);
  ALOGD("TK--------_>>>>>>ok\n");
}
2.frameworks/av/camera/Camera.cpp
void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
                          camera_frame_metadata_t *metadata)
{
  int takepicture_fd;
  takepicture_fd = open("/data/tankai_CPP.jpg",O_WRONLY|O_CREAT,00700);
  ALOGD("TK---CPP------->>>>JPEG,dataPtr->size() is %d,takepicture_fd is %d\n",dataPtr->size(),takepicture_fd);
  ALOGD("TK->>>>CPP---->>>>>dataPtr->pointer() is 0x%x",dataPtr->pointer());
  int write_len = write(takepicture_fd, dataPtr->pointer(), dataPtr->size());
  close(takepicture_fd);
  ALOGD("TK---CPP-----_>>>>>>ok\n");
}
3.frameworks/base/core/jni/android_hardware_Camera.cpp
void JNICameraContext::copyAndPost(JNIEnv* env, const sp<IMemory>& dataPtr, int msgType)
{
  jbyteArray obj = NULL;
  obj = env->NewByteArray(size);
  //add by tankai 
  int takepicture_fd;
  takepicture_fd = open("/data/tankai_jni2.jpg",O_WRONLY|O_CREAT,00700);
  ALOGD("TK-------JNI2--->>>>JPEG,size is %d,takepicture_fd is %d\n",size,takepicture_fd);
  ALOGD("TK----->>>>JNI2------>>>>>>data is 0x%x",data);
  int write_len = write(takepicture_fd, data, size);
  close(takepicture_fd);
  ALOGD("TK----JNI2----_>>>>>>ok\n");
  //end tankai
  env->SetByteArrayRegion(obj, 0, size, data);
  //add by tankai
  takepicture_fd = open("/data/tankai_jni3.jpg",O_WRONLY|O_CREAT,00700);
  ALOGD("TK-------JNI3--->>>>JPEG,size is %d,takepicture_fd is %d\n",size,takepicture_fd);
  jbyte * olddata = (jbyte*)env->GetByteArrayElements(obj, 0);
  char* bytearr = (char*)olddata;
  ALOGD("TK----->>>>JNI3------>>>>>>obj is 0x%x,bytearr is 0x%x",obj,bytearr);
  write_len = write(takepicture_fd, bytearr, size);
  close(takepicture_fd);
  ALOGD("TK----JNI3----_>>>>>>ok\n");
  //end tankai
  //调用mCameraJClass的fields.post_event方法,参数为后边的5个
  env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
            mCameraJObjectWeak, msgType, 0, 0, obj); 
}
4.frameworks/base/core/java/android/hardware/Camera.java
public void handleMessage(Message msg) {
  case CAMERA_MSG_COMPRESSED_IMAGE:
    //add by tankai
    Log.d(TAG,"TK-------->>>>>>java callback");
    Bitmap bitmap = BitmapFactory.decodeByteArray(((byte[])msg.obj), 0, ((byte[])msg.obj).length);
    Log.d(TAG,"TK----->>>>((byte[])msg.obj) is 0x%x" + ((byte[])msg.obj));
    String path = "/data/";
    String fileName = "tankai_java.jpg";
    File out = new File(path);
    if (!out.exists()) {
      out.mkdirs();
    }
    out = new File(path, fileName);
    try {
      FileOutputStream outStream = new FileOutputStream( out);
      bitmap.compress(CompressFormat.JPEG, 100,outStream);
      outStream.close();
      Log.d(TAG,"TK-------->>>>>>java callback>>>>ok");
    } catch (Exception e) {
      Log.d(TAG,"TK-------->>>>>>java callback>>>>fail");
      e.printStackTrace();
    }
    //end tankai
}
结果,当设置180度反转后,1-3中所存图片都为正;4为反。

三、原因

1.java部分使用bitmap存文件,没有直接保存;可能是这个原因。

2.修改应用程序中存JPEG文件的方式:

File ret = null;
BufferedOutputStream stream = null;
try {
  ret = new File("/data/1.jpg");
  FileOutputStream fstream = new FileOutputStream(ret);
  stream = new BufferedOutputStream(fstream);
  stream.write(data);
} catch (Exception e) {
  // log.error("helper:get file from byte process error!");  
  e.printStackTrace();
} finally {
  if (stream != null) {
    try {
      stream.close();
    } catch (IOException e) {
      // log.error("helper:get file from byte process error!");  
      e.printStackTrace();
    }
  }
}
结果,图片变正。

3.结论

问题出在bitmap转换上。

四、读取JPEG文件EXIF信息的ORIENTATION字段

1.源码

private int getBitmapDegree(String path) {
    int degree = 0;
    try {
        // 从指定路径下读取图片,并获取其EXIF信息
        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;
}
result = getBitmapDegree("/data/tankai_CPP.jpg");
Log.d("TKTK","TK------>>>>>>>/data/tankai_CPP is " + result);


result = getBitmapDegree("/data/tankai_jni.jpg");
Log.d("TKTK","TK------>>>>>>>/data/tankai_jni1 is " + result);


result = getBitmapDegree("/data/tankai_jni2.jpg");
Log.d("TKTK","TK------>>>>>>>/data/tankai_jni2 is " + result);


result = getBitmapDegree("/data/tankai_jni3.jpg");
Log.d("TKTK","TK------>>>>>>>/data/tankai_jni3 is " + result);


result = getBitmapDegree("/data/tankai_java.jpg");
Log.d("TKTK","TK------>>>>>>>/data/tankai_java is " + result);


result = getBitmapDegree("/data/1.jpg");
Log.d("TKTK","TK------>>>>>>>/data/1.jpg is " + result);
2.结果

正常显示时该字段为180,没有变正的该字段为0。

五、结论

Android系统中Camera拍照时setRotation在各个平台功能不统一:有些平台会直接操作图片的存储地址,将数据反写;但绝大多数平台只是修改了JPEG编码时EXIF头部的ORIENTATION字段。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android系统Camera图片反转的一个问题 的相关文章

  • 2022小米红米手机最新最全MIUI刷机教程内测版到稳定版 不清除数据(线刷、卡刷)

    文章目录 方法1 xff1a 解锁 线刷手机解锁解锁软件接入电脑刷机工具下载下载刷机包线刷 方法2 xff1a 小米助手卡刷包下载小米助手PC客户端打开手机USB调试模式连接小米助手卡刷miui卡刷包下载 起因是因为意外升级了一版内测版mi
  • TreeSet录入重复的元素及保证录入&输出顺序一致的Java实现

    Java萌新在学习路上遇到的一个扯dan的问题解法 知识点 Set TreeSet TreeSet自然排序 TreeSet比较器排序 Comparator 原题目 请编写main 方法 xff0c 按以下要求顺序 循环接收控制台录入的字符串
  • SpringBoot无法访问static文件夹 404问题

    使用spring boot 配置好后端 导入前端页面到resources 61 gt static 文件夹后 无法访问 但此时进入调试模式 访问controller的路径时 发现后台已经传送出去json数据 64 RequestMappin
  • Ubuntu虚拟机反复在登录界面循环问题

    登录Ubuntu的时候发现登录界面不对劲 xff0c 之前从来没有看到过 而且无法登录 xff0c 反复在登录界面循环 百度 xff0c 说原因有两个 xff1a 1 环境变量修改有问题 xff1b 2 显卡驱动有问题 xff1b 均尝试数
  • pycharm设置笔记

    目录 区分级别显示高亮日志 区分级别显示高亮日志 效果 设置log highlighting里填入 s E RROR s 即可 s E RROR s
  • Ubuntu设置开机自启动

    文章目录 前言一 基本概念二 操作步骤1 终端输入2 设置路径 总结 前言 本文介绍如何在Ubuntu设置开机自启动 一 基本概念 除了系统上配置的默认启动应用程序之外 xff0c gnome session properties 程序使用
  • uniapp 发布网站遇到的问题(跨域,nginx代理失败,index无法打开,手机端无法访问等)

    跨域 如果开发的应用直接是作为手机APP是不存在跨域问题的 xff0c 但是如果是网站形式就要考虑这个问题了 分为两点 xff1a 1 调试时 可通过设置maintest 2 发布后 可通过Nginx配置文件设置代理 nginx代理失败 1
  • 怎么在linux上安装vnc

    1 首先检查是否安装了VNC服务 输入命令 xff1a rpm qa grep vnc 2 安装VNC xff0c 首次执行vncserver需要设置密码 xff0c 可以创建多个桌面 xff0c 执行多次vncserver命令即可 roo
  • VNC修改端口号

    1 vnc的默认端口是自己配置的 xff0c 想要修改vncserver的配置 xff0c 需要先找配置文件路径 root 64 node04 which vncserver usr bin vncserver 2 通过查找以前配置的端口
  • onNewIntent使用遇到的坑

    onCreate是用来创建一个Activity也就是创建一个窗体 xff0c 但一个Activty处于任务栈的顶端 xff0c 若再次调用startActivity去创建它 xff0c 则不会再次创建 若你想利用已有的Acivity去处理别
  • CentOS7使用firewall-cmd打开关闭防火墙与端口

    一 centos7版本对防火墙进行加强 不再使用原来的iptables 启用firewalld 1 firewalld的基本使用 启动 xff1a systemctl start firewalld 查状态 xff1a systemctl
  • 算法数学基础-排列组合(题目取自牛客网)

    基础理论 xff1a 排列 有限集的子集按某种条件的序化法排成列 排成一圈 不许重复或许重复等 从n个不同元素中每次取出m xff08 1 m n xff09 个不同元素 xff0c 排成一列 xff0c 称为从n个元素中取出m个元素的无重
  • 关于对Spring框架的详解

    Spring框架 基本概念Spring的形成主要模块三层架构Spring的优点对于Spring 框架中都用到设计模式 xff1a 基本概念 Spring框架是由于软件开发的复杂性而创建的 Spring使用的是基本的JavaBean来完成以前
  • vs2015 提示严重性代码说明项目文件行禁止显示状态 错误C4996 'scanf': This function or variable may be unsafe.

    在 vs2015 中使用scanf时总是提示 unsafe 报出错误 xff0c 解决办法是在已经建立的项目中 xff0c 以后可能需要经常进行再不同的项目进行这项操作 xff1a 项目 gt 属性 gt c c 43 43 gt 常规 g
  • base7. ThreadPool线程池类——生产者与消费者模型

    ThreadPool类图 数据成员 xff1a MutexLock mutex xff1a 一个MutexLock类型的互斥变量mutex Condition cond xff1a 一个Condition类型的条件变量cond string
  • Ubuntu下anaconda中PyCharm遇到的环境问题

    Table of Contents 运行找不到包文件 可以run xff0c 不能debug 运行找不到包文件 解救办法 xff1a 将包的路径添加到interpreter中 可以run xff0c 不能debug 去掉setting中py
  • origin画图——同一图中多组数据

    origin画图 同一图中多组数据 xff08 2维 xff09 导入数据分别确定X Y轴列数据 xff08 选中列 set as X Y xff0c 全选数据 xff0c 点击下方绘图图标
  • pacman用法

    Pacman 是archlinux 下的包管理软件 它将一个简单的二进制包格式和易用的构建系统结合了起来 不管软件包是来自官方的 Arch 库还是用户自己创建 xff0c Pacman 都能方便得管理 pacman Sy abc 和源同步后
  • Spring注解-1-SpringBoot是如何处理注解的

    本文基于Spring 5 2 7 这是个很大的话题 xff0c 但是是个非常实在的话题 xff0c 注解天天用 xff0c 处处用 xff0c 请问你知道他是怎么起作用的吗 xff1f 如果你使用了注解 xff0c 那么一定有代码在什么地方
  • Qt对当前界面进行截图并保存

    Qt提供了对界面截图的功能 xff0c 非常简单 xff0c 只需要2行即可截图并保存下来 xff0c 如下 xff1a QPixmap pixMap 61 QPixmap grabWidget this pixMap save 34 my

随机推荐

  • Qt中通过Qpixmap设置图片透明度

    最近看到美图秀秀的一些功能 xff0c 可以手动设置图片的透明度并显示在其它图片上 xff0c 所以自己动手做了个小Demo xff0c 实际效果如下 xff1a xff08 图片仅供参考使用 xff09 可以看到拖动下方进度条 xff0c
  • QTableWidget中添加QComboBox/QPushButton控件并响应控件点击

    QTableWidget是QT程序中常用的显示数据表格的空间 xff0c 里面不仅仅可以添加文字 xff0c 也可以添加控件 xff0c 图片等等 xff0c 此处以添加QCombobox和QPushButton举例 xff0c 点击选择控
  • QMap的简单使用(增删改查等)

    前言 QMap是Qt提供的容器类 xff0c 是一种由key到value的映射 与C 43 43 中STL提供的map使用方法相同 xff0c 部分使用细节上 xff0c QMap做了优化 插入 QMap lt int QString gt
  • vector<char>与char*相互转换

    最近在做网络通信 xff0c 看到很多人使用vector lt char gt 来存储二进制网络数据 xff0c 而我有时需要用char 数据 xff0c 所以记录下二者的相互转换方法 xff0c 代码如下 xff1a include lt
  • Qt中自定义qDebug打印信息的宏(文件名,行数,时间等等)

    前言 QDebug类提供用于调试信息的输出流 当开发人员需要将调试或跟踪信息写到设备 xff0c 文件 xff0c 字符串或控制台时 xff0c 将使用QDebug 当我们使用qDebug 打印信息时 xff0c 只有我们所需要打印的信息
  • QT实现鼠标右键快捷菜单(QTableWidget)

    对于右键点击事件 xff0c 这里用到的是Qt CustomContextMenu方法 xff0c 本例通过右点QTableWidget xff0c 显示下拉菜单 xff0c 同时获得点击的行号 ui界面如下图 xff1a customCo
  • git使用遇到问题

    文中自己理解的偏多 xff0c 有错误的地方还请指正 xff08 会有很多错误 xff09 commit in detached head 解决办法 xff1a 进入到工程所在路径运行 git branch f master HEAD am
  • 从零开始学写脚本【第一天】

    废话我就不多说了 xff0c 直接开干 新建一个项目 安装 selenium selenium是浏览器自动化测试工具 控制台输入 pip install selenium 下载Chromedriver 浏览器驱动 xff0c 代码打开浏览器
  • 超简单图文并茂基于Linux使用Docker部署Node.js项目

    一看就懂图文并茂基于CentOS Linux release 7 8 2003 Core 安装并Docker化你的Node js应用 64 TOC 基于CentOS Linux release 7 8 2003 Core 安装并使用Dock
  • ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that c

    1 ERROR 1064 42000 You have an error in your SQL syntax check the manual that corresponds to your MySQL server version f
  • Android 电量监控、关机、重启功能的实现

    本文主要是介绍Android电量监控 关机 重启功能的实现 xff0c 需要具备的条件是手机需要root过 xff0c 才能实现相关操作 1 MainActivity java import java io IOException impo
  • 拓扑排序1图文详解面试常考算法 —— 拓扑排序

    前言 Topological sort 又称 Topological order xff0c 这个名字有点迷惑性 xff0c 因为拓扑排序并不是一个纯粹的排序算法 xff0c 它只是针对某一类图 xff0c 找到一个可以执行的线性顺序 这个
  • Android签名总结

    一 为什么要签名 开发Android 的人这么多 xff0c 完全有可能大家都把类名 xff0c 包名起成了一个同样的名字 xff0c 这时候如何区分 xff1f 签名这时候就是起区分作用的 由于开发商可能通过使用相同的Package Na
  • 消息队列技术介绍

    一 消息队列概述 消息队列中间件是分布式系统中重要的组件 xff0c 主要解决应用耦合 异步消息 流量削锋等问题 实现高性能 高可用 可伸缩和最终一致性架构 是大型分布式系统不可缺少的中间件 目前在生产环境 xff0c 使用较多的消息队列有
  • Ubuntu 循环登录 解决办法

    Ubuntu 经常出现循环登录的情况 但需要根据不同原因 采用不同的解决方案 已知情况有 Xauthority 权限变为root 修改到自己账户权限即可nvidia 显卡驱动问题 卸载重装即可 Xauthority 权限问题 参考Ubunt
  • Kotlin基础(一)android studio中配置Kotlin

    1 何为Kotlin xff1f Kotlin是一门运行在JVM之上的语言 它由Jetbrains创建 xff0c 而Jetbrains则是诸多强大的工具 xff08 如知名的Java IDE IntelliJ IDEA xff09 背后的
  • 关于Ubuntu18.04 root账户登录的问题

    关于Ubuntu18 04 root账户登录的问题 一 Ubuntu 18 04添加root用户登录1 设置root用户2 修改 root profile3 修改 96 etc pam d 96 目录下的 96 gdm autologin
  • Ubuntu下fcitx崩溃,搜狗输入法乱码

    转载 xff1a https www findhao net res 786 预防原文删除 xff0c 侵删 方法 直接重启fcitx即可 xff1a fictx自带的重启 fcitx r 或者执行以下三条 xff1a 获得fcitx的进程
  • KVM虚拟化

    KVM虚拟化 文章目录 KVM虚拟化虚拟化简介 KVMKVM部署CPU虚拟化功能kvm管理界面安装 虚拟化简介 虚拟化 xff1a 在一台计算机上虚拟出多个逻辑的计算机 xff0c 而且每个逻辑计算机它可以是不同的操作系统 虚拟化技术 xf
  • Android系统Camera图片反转的一个问题

    一 问题提出 目前遇到项目问题 xff0c Camera预览图像是反的 xff0c 于是考虑设置180度反转以便正常 通过如下两种方式 xff1a params setRotation 180 java部分 p set CameraPara