Android - a visualização da câmera é de lado
-
27-09-2019 - |
Pergunta
Estou usando uma visualização para exibir o que a câmera vê na tela.
Eu posso fazer tudo funcionar bem, criado na superfície, conjunto de superfície e a superfície é exibida.
No entanto, ele sempre exibe a imagem em um ângulo incorreto de 90 graus no modo retrato.
Como na foto:
Estou ciente de que o uso do código a seguir definirá a imagem reta:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
No entanto, tenho a visualização em uma atividade que possui outros elementos e não faz sentido que minha atividade seja exibida no modo paisagem. (Está desativado por padrão)
Então, eu queria saber que existe de alguma maneira apenas para mudar a orientação da pré -visualização? E deixar o restante da minha atividade exibida corretamente no modo retrato?
Ou de qualquer maneira, para girar a visualização para que seja exibida corretamente?
Solução
Este problema parecia começar como um bug com determinado hardware Veja aqui mas pode ser superado usando a chamada para mcamera.setDisplayorientation (graus) disponível na API 8. Portanto, é assim que eu a implemento:
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (isPreviewRunning) {
mCamera.stopPreview();
}
Parameters parameters = mCamera.getParameters();
Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
if(display.getRotation() == Surface.ROTATION_0) {
parameters.setPreviewSize(height, width);
mCamera.setDisplayOrientation(90);
}
if(display.getRotation() == Surface.ROTATION_90) {
parameters.setPreviewSize(width, height);
}
if(display.getRotation() == Surface.ROTATION_180) {
parameters.setPreviewSize(height, width);
}
if(display.getRotation() == Surface.ROTATION_270) {
parameters.setPreviewSize(width, height);
mCamera.setDisplayOrientation(180);
}
mCamera.setParameters(parameters);
previewCamera();
}
And the previewCamera method :
public void previewCamera() {
try {
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.startPreview();
isPreviewRunning = true;
} catch(Exception e) {
Log.d(APP_CLASS, "Cannot start preview", e);
}
}
Isso estava em um desejo HTC e eu tive que colocar inicialmente declarações de registro em cada uma das verificações de rotação para dizer qual era a rotação e, em seguida, depuração no dispositivo e assisti à saída do logcat enquanto eu girava o dispositivo. Para o desejo HTC, 0 era o telefone como você esperava (retrato), 90 graus estavam girando o telefone 90 graus no sentido anti-horário (eu assumi que teria sido no sentido horário). No código, você verá que eu não precisava fazer nenhuma rotação de exibição quando o telefone estava em 90 ou 180 graus - o dispositivo parecia lidar com isso por conta própria. Apenas um ponto não está funcionando corretamente: a rotação de 270 graus é quando você gira o dispositivo 90 graus no sentido horário e os contadores de rotação de exibição que OK, mas se você girar o dispositivo 270 graus no sentido anti-horário, ele não parece compensá-lo corretamente.
PS Observe a troca de largura e altura nas rotações apropriadas.
Outras dicas
Tente definir a orientação da exibição. Ele resolve meu problema.
mCamera.setDisplayOrientation(90);
public void surfaceCreated(SurfaceHolder holder) {
mCamera = Camera.open();
mCamera.setDisplayOrientation(90);
try {
mCamera.setPreviewDisplay(holder);
mCamera.setPreviewCallback(new PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
Experimente este código
Eu estava tendo um problema com a câmera frontal (edição de cabeça para baixo). Então eu usei o seguinte método documentado em Docs Android -
public void setCameraDisplayOrientation(Activity activity , int icameraId , Camera camera1s)
{
CameraInfo cameraInfo = new CameraInfo();
Camera.getCameraInfo(icameraId, cameraInfo);
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0; // k
switch (rotation)
{
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int result;
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)
{
// cameraType=CAMERATYPE.FRONT;
result = (cameraInfo.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
}
else
{ // back-facing
result = (cameraInfo.orientation - degrees + 360) % 360;
}
// displayRotate=result;
camera.setDisplayOrientation(result);
}
Fiz isso aceitando o conselho da mcamera.setDisplayorientation (90); mas também girou o bitmap porque, por algum motivo, as outras abordagens não funcionam para mim na versão 2.3.3.
Para girar o bitmap, eu fiz isso:
Matrix matrix = new Matrix();
matrix.postRotate(90);
imageView1 = new ImageView(this);
Bitmap bitmap = BitmapFactory.decodeFile(files[i].getAbsolutePath());
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap , 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
Bitmap scaledBitmap = Bitmap.createScaledBitmap(rotatedBitmap, 80, 80, true);
imageView1.setImageBitmap(scaledBitmap);
Eu comparei meu código com o tutorial e o que finalmente consertou, estava colocando o seguinte código no meu Androidmanifext.xml: no <activity>
marcação:
android:screenOrientation="landscape"
android:configChanges="keyboardHidden|orientation">
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
try {
mCamera.stopPreview();
} catch (Exception e) {
e.printStackTrace();
}
Camera.Parameters parameters = mCamera.getParameters();
Display display = ((WindowManager) getContext().getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
if (display.getRotation() == Surface.ROTATION_0) {
parameters.setPreviewSize(h, w);
mCamera.setDisplayOrientation(90);
}
if (display.getRotation() == Surface.ROTATION_90) {
parameters.setPreviewSize(w, h);
mCamera.setDisplayOrientation(0);
}
if (display.getRotation() == Surface.ROTATION_180) {
parameters.setPreviewSize(h, w);
mCamera.setDisplayOrientation(270);
}
if (display.getRotation() == Surface.ROTATION_270) {
parameters.setPreviewSize(w, h);
mCamera.setDisplayOrientation(180);
}
previewCamera();
}
public void previewCamera() {
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
//Log.d(APP_CLASS, "Cannot start preview", e);
e.printStackTrace();
}
}