我正在尝试一个简单的应用程序,它可以在以纵向模式锁定的camera2 repeatingrequest提供的预览帧上执行一些RenderScript处理。我试过从提供的例子开始工作,但似乎没有解决处理原始图像然后以肖像显示的问题。
图像显示旋转90度并在显示时拉伸。我曾试图应用矩阵变换来纠正这个问题,但却无法找到正确的变换来防止图像拉伸。这导致我使用TextureView,但我以前尝试过SurfaceView无济于事。
这是一个精简的应用程序,用我当前的解决方案显示我所处的位置(用硬编码值替换大量设置等)。
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsicYuvToRGB;
import android.renderscript.Type;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Size;
import android.view.Surface;
import android.view.TextureView;
import java.util.Arrays;
public class MainActivity extends AppCompatActivity {
private CameraDevice mCameraDevice;
private RenderScript mRenderScript;
private ScriptIntrinsicYuvToRGB mScript;
//private Size mDimensions = new Size(1024,576);
private Size mDimensions = new Size(1280,720);
private Allocation mScriptInputAllocation;
private Allocation mScriptOutputAllocation;
private CameraCaptureSession mCaptureSession;
private TextureView mTextureView;
private SurfaceTexture mDisplaySurface;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextureView = findViewById(R.id.textureView);
mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
mRenderScript = RenderScript.create(this);
Type.Builder yuvTypeBuilder = new Type.Builder(mRenderScript, Element.YUV(mRenderScript));
yuvTypeBuilder.setX(mDimensions.getWidth());
yuvTypeBuilder.setY(mDimensions.getHeight());
yuvTypeBuilder.setYuvFormat(ImageFormat.YUV_420_888);
mScriptInputAllocation = Allocation.createTyped(mRenderScript, yuvTypeBuilder.create(),
Allocation.USAGE_IO_INPUT | Allocation.USAGE_SCRIPT);
Type.Builder rgbTypeBuilder = new Type.Builder(mRenderScript, Element.RGBA_8888(mRenderScript));
rgbTypeBuilder.setX(mDimensions.getWidth());
rgbTypeBuilder.setY(mDimensions.getHeight());
mScriptOutputAllocation = Allocation.createTyped(mRenderScript, rgbTypeBuilder.create(),
Allocation.USAGE_IO_OUTPUT | Allocation.USAGE_SCRIPT);
mScript = ScriptIntrinsicYuvToRGB.create(mRenderScript, Element.U8_4(mRenderScript));
mScript.setInput(mScriptInputAllocation);
mScriptInputAllocation.setOnBufferAvailableListener(mOnBufferAvailableListener);
if((ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED)){
setUpCamera();
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 1);
}
}
@SuppressLint("MissingPermission")
private void setUpCamera() {
try {
CameraManager mCameraManager = (CameraManager) getSystemService(CAMERA_SERVICE);
String cameraId = null;
String[] cameraIds = new String[0];
cameraIds = mCameraManager.getCameraIdList();
for (String id : cameraIds) {
cameraId = id;
CameraCharacteristics info = mCameraManager.getCameraCharacteristics(id);
Integer facing = info.get(CameraCharacteristics.LENS_FACING);
if(facing == CameraCharacteristics.LENS_FACING_BACK)
{
break;
}
}
mCameraManager.openCamera(cameraId, mCameraDeviceStateCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
setUpCamera();
}
private void startCameraSessionIfReady(){
if(mTextureView != null && mCameraDevice != null){
startCameraSession();
}
}
private void startCameraSession() {
try {
mCameraDevice.createCaptureSession(Arrays.asList(mScriptInputAllocation.getSurface()), mCameraSessionStateCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void sendCaptureRequest() {
try {
CaptureRequest.Builder previewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
previewBuilder.addTarget(mScriptInputAllocation.getSurface());
CaptureRequest previewRequest = previewBuilder.build();
mCaptureSession.setRepeatingRequest(previewRequest, null, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private Allocation.OnBufferAvailableListener mOnBufferAvailableListener = new Allocation.OnBufferAvailableListener(){
@Override
public void onBufferAvailable(Allocation a) {
mScriptInputAllocation.ioReceive();
mScript.forEach(mScriptOutputAllocation);
mScriptOutputAllocation.ioSend();
}
};
private CameraCaptureSession.StateCallback mCameraSessionStateCallback = new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraCaptureSession session) {
Surface surface = new Surface(mDisplaySurface);
mScriptOutputAllocation.setSurface(surface);
mCaptureSession = session;
sendCaptureRequest();
}
@Override
public void onConfigureFailed(@NonNull CameraCaptureSession session) {}
};
private CameraDevice.StateCallback mCameraDeviceStateCallback = new CameraDevice.StateCallback(){
@Override
public void onOpened(@NonNull CameraDevice camera) {
mCameraDevice = camera;
startCameraSessionIfReady();
}
@Override
public void onDisconnected(@NonNull CameraDevice camera) {}
@Override
public void onError(@NonNull CameraDevice camera, int error) {}
};
private TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
mDisplaySurface = surface;
//Matrix matrix = new Matrix();
//matrix.postRotate(90, width/2f, height/2f);
//matrix.postScale((float)width/mDimensions.getHeight(), (float)height/mDimensions.getWidth(), width/2, height/2);
//mTextureView.setTransform(matrix);
startCameraSessionIfReady();
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {return false;}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {}
};
}
如果有人能指出我正确的方向,我们将非常感激。