Android相机预览总是横向的
我正在编写一个Android插件,它将从相机预览中获取数据并发送给Unity。(由于各种原因,我无法使用Unity WebCamTexture)我能够获取相机预览数据并将其发送给Unity,但是,图像始终旋转90度。我的Unity应用程序设置为始终处于纵向模式 在我的像素XL上,前后图像以相反方向旋转。这是我的应用程序在使用前后摄像头时的照片 我在NativeCamera.java中创建了函数AdjustOrientation,试图修复方向,但调用它似乎没有任何效果 我找到了一些地方的链接,这些地方说要添加类似于AdjustOrientation函数中的代码来解决问题,但没有一个地方解决了问题 这是我调查过的一个没有解决我问题的链接 我试过不同的方法Android相机预览总是横向的,android,camera,orientation,preview,portrait,Android,Camera,Orientation,Preview,Portrait,我正在编写一个Android插件,它将从相机预览中获取数据并发送给Unity。(由于各种原因,我无法使用Unity WebCamTexture)我能够获取相机预览数据并将其发送给Unity,但是,图像始终旋转90度。我的Unity应用程序设置为始终处于纵向模式 在我的像素XL上,前后图像以相反方向旋转。这是我的应用程序在使用前后摄像头时的照片 我在NativeCamera.java中创建了函数AdjustOrientation,试图修复方向,但调用它似乎没有任何效果 我找到了一些地方的链接,
mCamera.setDisplayOrientation()
params.setRotation()
但是没有任何运气
我只需要图像在正确的方向
public void onPreviewFrame(byte[] data, Camera camera)
保存的图像是否颠倒或旋转并不重要。我只是将数据传递给我的Unity项目,Android插件的唯一目的就是将相机数据传递给Unity。只要OnPreviewFrame内的图像数据正确,我将全部设置
我知道有一个更新的Camera2 API,它不赞成原来的摄像头,但我真的希望能够用我现有的插件修复这个问题,而不必编写一个使用Camera2的新插件
这是我的项目的链接
提前谢谢
约翰·劳里
更新。以下是我的.java文件的源代码,以便于参考。如果您查看AdjustOrientation,您可以看到我有一些代码尝试调整displayorientation。这似乎没有效果
package com.test.camerapreview;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.opengl.GLES11Ext;
import android.opengl.GLES20;
import android.support.annotation.Dimension;
import android.util.Log;
import android.util.Size;
import android.view.Display;
import android.view.Surface;
import com.unity3d.player.UnityPlayer;
import com.google.gson.Gson;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class NativeCamera implements Camera.PreviewCallback {
public static NativeCamera instance;
public static String gameObjectTargetName;
private static Activity myActivity;
Camera mCamera;
SurfaceTexture texture;
int nativeTexturePointer = -1;
int prevHeight;
int prevWidth;
//
// Call this function first.
//
public static void Setup(String gameObjectName, Activity theActivity){
gameObjectTargetName = gameObjectName;
myActivity = theActivity;
instance = new NativeCamera();
}
public int startCamera(int idx, int width, int height) {
nativeTexturePointer = createExternalTexture();
texture = new SurfaceTexture(nativeTexturePointer);
mCamera = Camera.open(idx);
setupCamera(idx, width, height);
try {
mCamera.setPreviewTexture(texture);
mCamera.setPreviewCallback(this);
AdjustOrientation(width, height);
mCamera.startPreview();
Log.i("Unity", "JAVA: camera started");
} catch (IOException ioe) {
Log.w("Unity", "JAVA: CAM LAUNCH FAILED");
}
return nativeTexturePointer;
}
public void stopCamera() {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0);
Log.i("Unity", "JAVA: Camera stopped");
}
private int createExternalTexture() {
int[] textureIdContainer = new int[1];
GLES20.glGenTextures(1, textureIdContainer, 0);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureIdContainer[0]);
return textureIdContainer[0];
}
@SuppressLint("NewApi")
private void setupCamera(int cameraID, int width, int height) {
Camera.Parameters params = mCamera.getParameters();
params.setRecordingHint(true);
// params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
params.setPreviewFormat(17);
params.setZoom(0);
// 16 ~ NV16 ~ YCbCr
// 17 ~ NV21 ~ YCbCr ~ DEFAULT *
// 4 ~ RGB_565
// 256~ JPEG
// 20 ~ YUY2 ~ YcbCr ...
// 842094169 ~ YV12 ~ 4:2:0 YCrCb comprised of WXH Y plane, W/2xH/2 Cr & Cb. see documentation *
// params.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
Camera.Size previewSize = getOptimalSize(width, height, mCamera.getParameters().getSupportedPreviewSizes());
int previewWidth = previewSize.width;
int previewHeight = previewSize.height;
params.setPictureSize(previewWidth, previewHeight);
params.setPreviewSize(previewWidth, previewHeight);
params.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);
params.setExposureCompensation(0);
//
// Fix the orientation.
//
// int orientation = detectCameraDisplayOrientation(cameraID);
// mCamera.setDisplayOrientation(orientation);
// params.setRotation(orientation);
// Camera.CameraInfo info = new Camera.CameraInfo();
// Camera.getCameraInfo(cameraID, info);
// Log.d("Unity", "info.orientation = " + info.orientation);
// params.setRotation(-90);
// mCamera.setDisplayOrientation(-90);
// mCamera.setDisplayOrientation(90);
// params.setRotation(90);
try{
mCamera.setParameters(params);
} catch (Exception e){
Log.i("Unity", "ERROR: " + e.getMessage());
}
Camera.Size mCameraPreviewSize = params.getPreviewSize();
prevWidth = mCameraPreviewSize.width;
prevHeight = mCameraPreviewSize.height;
int[] fpsRange = new int[2];
params.getPreviewFpsRange(fpsRange);
String previewFacts = mCameraPreviewSize.width + "x" + mCameraPreviewSize.height;
if (fpsRange[0] == fpsRange[1]) {
previewFacts += " @" + (fpsRange[0] / 1000.0) + "fps";
} else {
previewFacts += " @[" + (fpsRange[0] / 1000.0) + " - " + (fpsRange[1] / 1000.0) + "] fps";
}
Log.i("Unity", "JAVA: previewFacts=" + previewFacts);
}
private void AdjustOrientation(int width, int height) {
Camera.Parameters parameters = mCamera.getParameters();
Display display = myActivity.getWindowManager().getDefaultDisplay();
if(display.getRotation() == Surface.ROTATION_0) {
Camera.Size previewSize = getOptimalSize(height, width, mCamera.getParameters().getSupportedPreviewSizes());
prevWidth = previewSize.width;
prevHeight = previewSize.height;
mCamera.setDisplayOrientation(90);
}
else if(display.getRotation() == Surface.ROTATION_90) {
Camera.Size previewSize = getOptimalSize(width, height, mCamera.getParameters().getSupportedPreviewSizes());
prevWidth = previewSize.width;
prevHeight = previewSize.height;
}
else if(display.getRotation() == Surface.ROTATION_180) {
Camera.Size previewSize = getOptimalSize(height, width, mCamera.getParameters().getSupportedPreviewSizes());
prevWidth = previewSize.width;
prevHeight = previewSize.height;
}
else { //if(display.getRotation() == Surface.ROTATION_270) {
Camera.Size previewSize = getOptimalSize(width, height, mCamera.getParameters().getSupportedPreviewSizes());
prevWidth = previewSize.width;
prevHeight = previewSize.height;
mCamera.setDisplayOrientation(180);
}
parameters.setPreviewSize(prevWidth, prevHeight);
mCamera.setParameters(parameters);
}
private Camera.Size getOptimalSize(int width, int height, List<Camera.Size> sizes) {
if(mCamera == null)
return null;
final double ASPECT_TOLERANCE = 0.1;
double targetRatio=(double)width / height;
if (sizes == null)
return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetWidth = width;
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
Log.i("Unity", "RES: size=" + size.width + "/" + size.height + " Aspect Ratio: " + ratio + " target width: " + width + " target height: " + height);
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) {
continue;
}
if (Math.abs(size.width - targetWidth) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.width - targetWidth);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.width - targetWidth) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.width - targetWidth);
}
}
}
Log.i("Unity", "optimal size=" + optimalSize.width + "/" + optimalSize.height + "/ Aspect Ratio: " + (double) optimalSize.width / optimalSize.height);
return optimalSize;
}
public int getPreviewSizeWidth() {
return prevWidth;
}
public int getPreviewSizeHeight() {
return prevHeight;
}
public String GetPreviewSizes(int id) {
Camera cam = Camera.open(id);
Camera.Parameters params = cam.getParameters();
Gson gson = new Gson();
String JSON = gson.toJson(params.getSupportedPreviewSizes());
cam.release();
Log.d("Unity", "Supported sizes are " + JSON);
return JSON;
}
public byte[] bytes;
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
bytes = data;
UnityPlayer.UnitySendMessage(gameObjectTargetName, "GetBuffer", "");
}
}
package com.test.camerapreview;
导入android.annotation.SuppressLint;
导入android.app.Activity;
导入android.graphics.SurfaceTexture;
导入android.hardware.Camera;
导入android.opengl.GLES11Ext;
导入android.opengl.GLES20;
导入android.support.annotation.Dimension;
导入android.util.Log;
导入android.util.Size;
导入android.view.Display;
导入android.view.Surface;
导入com.unity3d.player.UnityPlayer;
导入com.google.gson.gson;
导入java.io.IOException;
导入java.util.ArrayList;
导入java.util.List;
公共类NativeCamera实现Camera.PreviewCallback{
公共静态NativeCamera实例;
公共静态字符串gameObjectTargetName;
私人静态活动;
麦克默拉照相机;
表面结构;
int nativeTexturePointer=-1;
高度;
int-prevWidth;
//
//首先调用这个函数。
//
公共静态无效设置(字符串gameObjectName、Activity和Activity){
gameObjectTargetName=gameObjectName;
我的活动=活动;
实例=新的NativeCamera();
}
公共int startCamera(int idx、int宽度、int高度){
nativeTexturePointer=createExternalTexture();
纹理=新的表面纹理(nativeTexturePointer);
mCamera=Camera.open(idx);
设置摄像机(idx、宽度、高度);
试一试{
mCamera.setPreviewTexture(纹理);
mCamera.setPreviewCallback(此);
调整方向(宽度、高度);
mCamera.startPreview();
Log.i(“Unity”、“JAVA:camera启动”);
}捕获(ioe异常ioe){
Log.w(“Unity”,“JAVA:CAM启动失败”);
}
返回nativeTexturePointer;
}
公共摄像机(){
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
GLES20.glBindTexture(Gles11Text.GL_TEXTURE_EXTERNAL_OES,0);
Log.i(“Unity”,“JAVA:摄像机停止”);
}
私有int createExternalTexture(){
int[]textureIdContainer=新int[1];
GLES20.glGenTextures(1,0);
GLES20.glBindTexture(Gles11Text.GL_TEXTURE_EXTERNAL_OES,textureIdContainer[0]);
返回容器[0];
}
@SuppressLint(“新API”)
专用摄像机(int-cameraID、int-width、int-height){
Camera.Parameters params=mCamera.getParameters();
参数setRecordingHint(真);
//参数设置聚焦模式(摄像机参数聚焦模式连续视频);
参数setPreviewFormat(17);
参数设置缩放(0);
//16~NV16~YCbCr
//17~NV21~YCbCr~默认*
//4~RGB_565
//256~JPEG
//20~YUY2~YcbCr。。。
//842094169~YV12~4:2:0 YCrCb由WXH Y平面、W/2xH/2 Cr和Cb组成。参见文件*
//参数设置闪光模式(摄像机参数闪光模式);
Camera.Size previewSize=getOptimalSize(宽度、高度、mCamera.getParameters().getSupportedPreviewSizes());
int previewWidth=previewSize.width;
int previewwheight=previewSize.height;
参数设置图片大小(预览宽度、预览宽度);
参数设置PreviewSize(previewWidth、PreviewWight);
参数设置白平衡(摄像机参数白平衡自动);
参数setExposureCompensation(0);
//
//确定方向。
//
//int-orientation=detectCameraDisplayOrientation(cameraID);
//mCamera.setDisplayOrientation(方向);
//参数设置旋转(方向);
//Camera.CameraInfo info=新建Camera.CameraInfo();
//Camera.getCameraInfo(cameraID,info);
//Log.d(“Unity”、“info.orientation=“+info.orientation”);
//参数设置旋转(-90);
//mCamera.setDisplayOrientation(-90);
//mCamera.setDisplayOrientation(90);
//参数设置旋转(90);
试一试{
mCamera.setParameters(参数);
}捕获(例外e){
Log.i(“Unity”,“ERROR:+e.getMessage());
mCamera = Camera.open(0);
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
mCamera.setDisplayOrientation(90);`