--基于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 -->