Android Camera 预览角度和拍照保存图片角度相关

news2024/9/23 20:18:22

–基于Android R(11)

关于Camera

Camera Framework 的架构

Android Camera Framework 是一个分层架构,由以下组件组成:

  • HAL(硬件抽象层): HAL 抽象底层相机硬件,提供与不同设备相机进行交互的标准接口.
  • CameraService : CameraService 是框架的核心,管理相机设备并为应用程序提供访问 HAL 的接口.
  • Camera 应用程序 : Camera 应用程序是面向用户的界面,允许用户控制相机设置、预览取景器并拍摄照片或视频.

以 Android 原生 Camera2 应用程序为例,PhotoModule 和 VideoModule 展示了如何使用 Camera Framework 构建高级相机应用程序.
PhotoModule 负责管理照片拍摄.
VideoModule 负责管理视频录制.

Android 最新Camera框架
Camera 架构
AndroidO Camera(API 2)openCamera 流程

关于Camera预览

Camera的图像数据来源于摄像头硬件的图像传感器,图像传感器被固定到手机上后会有一个默认的方向.
如果默认的图像传感器为横向,而所用设备拍照是竖向的,比如手机,但得到的图片数据依然会是横向的,因为这个数据取决于图像传感器的方向.

由于Camera默认是横向的,竖向拍照时得到的照片和预览的照片会有所不同.
Camera1 API 上可以利用setDisplayOrientation(int rotateDegree)设置预览角度调节预览图片.
setDisplayOrientation只是改变了预览的角度,而拍摄生成图片的角度还是和默认图片传感器方向一致.

Camera2 API --通过TextureView.setTransform(matrix) 接口来调整textureView的显示来达到目的,设置预览方向.

./packages/apps/Camera2/src/com/android/camera/one/v2/OneCameraImpl.java:400:                builder.set(CaptureRequest.JPEG_ORIENTATION,
./packages/apps/Camera2/src/com/android/camera/one/v2/SimpleOneCameraFactory.java:199:                rootBuilder.setParam(CaptureRequest.JPEG_ORIENTATION,
./packages/apps/Camera2/src/com/android/camera/one/v2/OneCameraZslImpl.java:824:                builder.set(CaptureRequest.JPEG_ORIENTATION,
public void openCamera(){
      CameraManager manager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
        try {
           ......
    //调整预览画面显示方向
        configureTextureViewTransform(mTextureView.getWidth(),mTextureView.getHeight());
            manager.openCamera(cameraId, mStateCallback, null);
           ......
        }
}

private void configureTextureViewTransform(int viewWidth, int viewHeight) {
        if (null == mTextureView) {
            return;
        }
        int rotation = 0 ;/*activity.getWindowManager().getDefaultDisplay().getRotation();*/
        Matrix matrix = new Matrix();
        RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
        RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth());
        float centerX = viewRect.centerX();
        float centerY = viewRect.centerY();
        if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
            bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
            matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
            float scale = Math.max(
                    (float) viewHeight / mPreviewSize.getHeight(),
                    (float) viewWidth / mPreviewSize.getWidth());
            matrix.postScale(scale, scale, centerX, centerY);
            matrix.postRotate(90 * (rotation - 2), centerX, centerY);
        }else if (Surface.ROTATION_180 == rotation) {
            matrix.postRotate(180, centerX, centerY);
        }
        mTextureView.setTransform(matrix);
    }
关于Camera拍照生成图片角度处理

利用Camera拍照时,读取图片数据存储为图片,取到的数据直接来源于图像传感器采集到的图像数据.
所以拍摄生成图片的角度还是和默认图片传感器方向一致.
可以利用代码修改—拍摄生成图片的角度.

Camera2 API – 通过CaptureRequest.JPEG_ORIENTATION来设置拍照的图像方向

修改生成图片镜像
Android 7.1 RK3288 A40i Camera2 拍照镜像分析

./packages/apps/Camera2/src/com/android/camera/PhotoModule.java

    void saveFinalPhoto(final byte[] jpegData, final ExifInterface exif, CameraProxy camera) {
            if (mNamedImages == null)
                mNamedImages = new NamedImages();
            if (mNamedImages.mQueue.size() == 0)
                mNamedImages.nameNewImage(System.currentTimeMillis());

            int orientation = Exif.getOrientation(exif);

            float zoomValue = 1.0f;
            if (mCameraCapabilities.supports(CameraCapabilities.Feature.ZOOM)) {
                zoomValue = mCameraSettings.getCurrentZoomRatio();
            }
            
            ...
            
                exif.setTag(directionRefTag);
                exif.setTag(directionTag);
            }
            
+           //add text
+           Bitmap bitmap = CameraUtil.makeBitmap(jpegData, exifWidth * exifHeight);//jpeg byte 数组转换为bitmap
+           Matrix matrix = new Matrix();
+           matrix.postScale(-1, 1);//利用matrix 对矩阵进行转换 x轴镜像
+           bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
+           ByteArrayOutputStream baos = new ByteArrayOutputStream();
+           bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);//重新转换为 .jpeg 数据
+           byte [] tm_jpegData = baos.toByteArray();
+           //add text
+
            onMediaSavedListenerAfterBurstCapture mediaSavedListener = new onMediaSavedListenerAfterBurstCapture(
                    (mBurstPictureLength - mIndex));
            getServices().getMediaSaver().addImage(
-                            jpegData, title, date, mLocation, width, height,
+                            tm_jpegData, title, date, mLocation, width, height,
                             orientation, exif, mediaSavedListener);
                }
            // Animate capture with real jpeg data instead of a preview
            

Android9.0 Camera2 横屏问题修改记录
Android Camera预览角度和拍照保存图片角度学习

修改摄像头旋转方向

可以驱动层,hal层,framework层,app层修改.

--- a/frameworks/base/core/java/android/hardware/Camera.java
+++ b/frameworks/base/core/java/android/hardware/Camera.java
@@ -399,7 +399,7 @@ public class Camera {
      * @see android.app.admin.DevicePolicyManager#getCameraDisabled(android.content.ComponentName)
      */
     public static Camera open(int cameraId) {
-        return new Camera(cameraId);
+        return rotateCamera(i);
     }

     /**
    public static Camera open() {
        int numberOfCameras = getNumberOfCameras();
        CameraInfo cameraInfo = new CameraInfo();   
         for (int i = 0; i < numberOfCameras; i++) {
             getCameraInfo(i, cameraInfo);
             if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
-                return new Camera(i);
+                return rotateCamera(i);
             }
         }
         return null;
     }

+    //add text
+    private static Camera rotateCamera(int cameraId) {
+        Camera camera = new Camera(cameraId);
+        Parameters parameters = camera.getParameters();
+        CameraInfo cameraInfo = new CameraInfo();
+        getCameraInfo(cameraId, cameraInfo);
+        if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {//0 后置
+            camera.setDisplayOrientation(270);
+            parameters.setRotation(270);
+        } else if (cameraInfo.facing == CameraInfo.CAMERA_FACING_FRONT) {// 1 前置
+            camera.setDisplayOrientation(90);
+            parameters.setRotation(90);
+        }
+        camera.setParameters(parameters);
+        return camera;
+    }
+    //add text
+

修改某个apk应用拿到的SENSOR_ORIENTATION方向,影响Camera拍照生成图片角度.

frameworks/base/core/java/android/hardware/camera2/CameraCharacteristics.java

    @PublicKey
    @NonNull
    public static final Key<Integer> SENSOR_ORIENTATION =
            new Key<Integer>("android.sensor.orientation", int.class);

    @Nullable
    public <T> T get(Key<T> key) {
        //add text  
        Log.d("tag",  "Activity name: " + ActivityThread.currentActivityThread().currentActivityName() + " ,key = " + key);
            if(key != null && SENSOR_ORIENTATION.equals(key)){
                if(ActivityThread.currentOpPackageName().contains("com.xxx")){
                    //String cameraId = CameraManager.getCameraId();
                    if(cameraId != null){
                        T value = (T)(Object)90;
                        Log.d("tag",  "value = " + value + " ,ori = " + mProperties.get(key));
                        return value;
                }
            }
        //add text    
        return mProperties.get(key);
    }   

三方Camera App Framework方向控制(API2)

改变摄像头成像方向
camera3_profiles_rk356x.xml,这个配置说明了这个板子所有支持的摄像头配置.
RK 硬件的camera配置文件中找到ov8858摄像头设备,并修改其sensor.orientation value 的值.

hardware/rockchip/camera/etc/camera/camera3_profiles_rk356x.xml
<Profiles cameraId="0" name="ov8858" moduleId="m00">
        <Supported_hardware>
            <hwType value="SUPPORTED_HW_RKISP1"/>
        </Supported_hardware>
        ...
    <!-- Sensor -->
    <sensor.orientation value="270"/><!-- Sensor -->

rk356x OpenCamera流程浅析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2158370.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

共享打印机,局域网搜不到

如果共享打印机后&#xff0c;局域网内其余机器检索不到 1. 排查 是否启用来宾账户&#xff08;Guest&#xff09; 2. 网络和共享中心->更改高级共享设置->启用网络发现、启用文件和打印机共享、关闭密码保护共享 排查基本可以解决搜索不到打印机问题

Transformer动画讲解

**Transformer工作原理**** **一、**** ******GPT的核心是Transformer******** *GPT* &#xff1a; **GPT&#xff08;Generative Pre-trained Transformer&#xff09;**** ****是一种基于单向Transformer解码器的预训练语言模型&#xff0c;它通过在大规模语料库上的无监督…

MatrixOne 助力某电信运营商构建低成本高性能车联网管理系统

客户基本情况 该电信运营商在物联网领域深耕多年&#xff0c;致力于为企业和个人提供全面的物联网解决方案&#xff0c;包括智能连接、设备管理、数据采集与分析等核心服务。凭借其强大的网络覆盖和技术优势&#xff0c;该运营商为各行业提供高效、安全、可靠的物联网服务&…

风速传感器一文浅谈 了解自然的力量

产品概述 本产品主要采用优质聚合物碳纤维为原材料&#xff0c;具有良好的防腐、防侵蚀等特点&#xff0c;能够保证仪器长期使用不起锈&#xff0c;同时配合内部顺滑的轴承系统&#xff0c;确保了信息采集的准确性。外型小巧轻便&#xff0c;便于携带和组装&#xff0c;三杯设…

MCU和YT9218交换机通过RMII连接

1、可以通过带RMII的MCU和EXT1端口连接&#xff0c;将MCU配置为RMII 100M/全双工就可以通 2、原先在这里改SW配置&#xff0c; 一直不通 3、后来通过api调用可以通 这样改&#xff1a; 在初始化后&#xff0c;添加下面代码 //使能RMII&#xff0c;phy模式 #define Port5 …

【LeetCode】动态规划—使用最小花费爬楼梯(附完整Python/C++代码)

动态规划—#746. 使用最小花费爬楼梯 前言题目描述基本思路1. 问题定义:2. 理解问题和递推关系:3. 解决方法:4. 进一步优化:5. 小总结: 代码实现Python3代码实现Python 代码解释C代码实现C 代码解释 总结: 前言 在这个问题中&#xff0c;我们有一个数组 c o s t [ ] cost[] c…

单细胞SCENIC简单可视化分析学习和整理

SCENIC教程中给出三个方法进行下游的可视化分析&#xff0c;分别可以选择网页(SCope)平台&#xff0c;R或者python进行分析。 1、网页版&#xff1a;https://scope.aertslab.org/ 把数据从左侧工具栏处上传之后就可以个性化分析了~ 2、R和Python就殊途同归啦~ 笔者基于githu…

linux/CentOS 开机启动程序

前言 TencentOS Server 3.1 (TK4)适用于自己编写启动脚本的情况 编写启动脚本 比如启动tomcat&#xff0c;kaijiqidong_tomcat.sh #!/bin/bashecho "kaijiqidong_tomcat on date ." >> kaijiqidong_tomcat.log 2>&1cd /x/xx/xxx sh /x/tomcat/bin/s…

老照片修复软件有哪些?6个工具轻松搞定

在回忆的长廊中&#xff0c;老照片承载着岁月的痕迹和珍贵的记忆。 然而&#xff0c;时间的流逝往往让这些宝贵的瞬间变得模糊不清。幸运的是&#xff0c;现代科技赋予了我们修复这些老照片的能力。 面对市场上众多的老照片自动修复软件&#xff0c;选择一个合适的工具变得尤…

Apache APISIX学习(1):介绍、docker启动

一、介绍 Apache APISIX 是一个动态、实时、高性能的 API 网关&#xff0c; 提供负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能。你可以把 Apache APISIX 当做流量入口&#xff0c;来处理所有的业务数据&#xff0c;包括动态路由、动态上游…

得物自建 Redis 无人值守资源均衡调度设计与实现

目录&#xff1a; 一、为什么要做资源均衡调度 二、为什么要做自动化资源均衡调度 三、如何合理选择迁移节点 四、如何保障迁移过程中可靠性1. 添加从节点2. 检查同步数据正常3. 执行主从切换4. 检查主从切换正常5. 删除待迁移节点6. 消息通知 五、迁移任务管理展示 六、总结 …

户用光伏项目难管理,到底该怎么办?

一、鹧鸪云光伏业务管理软件&#xff1a;一站式管理利器 鹧鸪云光伏业务管理软件&#xff0c;作为一款专为光伏行业量身定制的智能化管理工具&#xff0c;集成了项目管理、运维管理、数据分析、用户服务等多功能模块于一体&#xff0c;旨在通过数字化手段&#xff0c;实现户用…

Nature Genetics|三代测序微量建库技术:媲美WGBS的直接甲基化检测

DNA修饰和甲基化是理解基因调控机制的关键。以往&#xff0c;我们的经验表明&#xff0c;使用三代测序从未经扩增的长DNA模板中同时读取序列信息和碱基修饰&#xff0c;需要投入大量的DNA样本来构建文库。 今天&#xff0c;小编带大家看一篇2024年发表于《Nature Genetics》的…

【MAUI】FlexLayout

文章目录 概述属性方向和对齐方式DirectionWrapJustifyContentAlignItemsAlignContent 圣杯布局来源 概述 FlexLayout弹性布局&#xff0c;和前端的Flex弹性布局&#xff0c;几乎一样。FlexLayout是容器&#xff0c;可以定义Direction/主轴方向、Wrap/子元素在主轴方向上是否换…

Vue使用Vue Router路由:开发单页应用

1、路由基础 在单页 Web 应用中&#xff0c;整个项目只有一个 HTML 文件&#xff0c;不同视图&#xff08;组件的模块&#xff09;的内容都是在同一个页面中渲染的。当用户切换页面时&#xff0c;页面之前的跳转都是在浏览器端完成的&#xff0c;这时就需要使用前端路由。 路…

蒙古语有方言差异吗?

蒙古语存在方言差异&#xff0c;主要分为西部方言和东部方言两大类。西部方言&#xff0c;即蒙古方言或喀尔喀方言&#xff0c;主要在蒙古国使用&#xff0c;是该国的官方语言。东部方言&#xff0c;又称布里亚特方言或巴尔虎-布里亚特方言&#xff0c;主要在中国内蒙古自治区和…

deepin桌面版连接windows远程桌面

在Linux系统中&#xff0c;要登录到Windows系统&#xff0c;通常可以使用远程桌面协议(RDP)。你需要在Linux系统上安装RDP客户端。 使用如下命令安装rdp协议&#xff1a; sudo apt-get install xrdp 安装成功后&#xff0c;启动rdp服务。 sudo systemctl start xrdp 有了r…

vscode缩进 和自动格式化

如下图&#xff0c;缩进太大了。 检查2个地方 prettierrc.cjs文件。此处决定缩进几个tab vscode 的设置。 保存的时候 格式化。

Apache Druid命令执行(CVE-2021-25646)

漏洞详情&#xff1a; Apache Druid 是用Java编写的面向列的开源分布式数据存储系统&#xff0c;旨在快速获取大量事件数据&#xff0c;并在数据之上提供低延迟查询。 Apache Druid含有能够执行嵌入在各种类型请求中由用户提供的JavaScript代码功能。此功能适用于高度信任环境…

Java_Day04学习

类继承实例 package com.dx.test03; public class extendsTest {public static void main(String args[]) {// 实例化一个Cat对象&#xff0c;设置属性name和age&#xff0c;调用voice()和eat()方法&#xff0c;再打印出名字和年龄信息/********* begin *********/Cat cat ne…