Android - a visualização da câmera é lateral

123

Estou usando uma visualização para exibir o que a câmera vê na tela.

Posso fazer tudo funcionar bem, criar superfície, definir 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 imagem:

texto alternativo

Estou ciente de que o uso do código a seguir definirá a imagem corretamente:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

No entanto, eu tenho a Visualização dentro de 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 se existe alguma maneira de apenas mudar a orientação da visualização? E deixar o restante da minha atividade exibido corretamente no modo retrato?

Ou mesmo assim, para girar a visualização para que ela seja exibida corretamente?

Donal Rafferty
fonte
Dê uma olhada - stackoverflow.com/questions/10259299/…
Suvam Roy

Respostas:

145

Esse problema parece ter começado como um bug em determinado hardware, veja aqui, mas pode ser superado usando a chamada para mCamera.setDisplayOrientation (graus) disponível na API 8. Portanto, é assim que eu o 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 acontecia no HTC Desire e eu tive que inserir instruções de registro em cada uma das verificações de rotação para dizer qual era a rotação e depois depurar no dispositivo e observar a saída do logCat enquanto eu rodava o dispositivo. Para o HTC Desire, 0 era o telefone como você esperava (retrato), 90 graus estava girando o telefone 90 graus no sentido anti-horário (eu supus que seria no sentido horário). No código, você verá que eu não precisava fazer rotação do visor quando o telefone estava a 90 ou 180 graus - o dispositivo parecia lidar com isso sozinho. Apenas um ponto não está funcionando corretamente: a rotação de 270 graus ocorre quando você gira o dispositivo 90 graus no sentido horário e a rotação do visor é 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.

John J Smith
fonte
7
mas setDisplayOrientation (degree); O método suporta o formulário 2.2, e a versão inferior? parameters.setRotation (90); parameters.set ("orientação", "retrato"); não estão funcionando. Se você tem alguma solução para versões inferiores, por favor me ajude.
Vikram
1
Eu implementei uma visualização no meu aplicativo, que sempre será exibida no modo retrato. Eu estava sempre girando a tela em 90 graus e isso parecia funcionar em todos os dispositivos até testá-la no HTC Desire C. Como não conto com o dispositivo agora para testar isso, gostaria que você esclarecesse se isso corrige sugerir finalmente funcionou bem no desejo HTC. Obrigado!
Argenkiwi
13
A mCamera.setParameters(parameters);declaração trava meu aplicativo, porque as dimensões da superfície não são um tamanho de visualização válido para o meu telefone (talvez porque eu mantenho a barra de status visível?). No entanto, eu achei que usando mCamera.setDisplayOrientation(90)então mCamera.setPreviewDisplay(mSurfaceHolder);sem definir os parâmetros funcionou também!
22613 nicopico
3
seria mais limpo com uma instrução switch
Siavash
2
Isso não pressupõe que a visualização seja lateral em TODOS os dispositivos? pois é lateral em alguns dispositivos e vertical em outros .... existe uma maneira de verificar se um dispositivo possui a orientação padrão da câmera alinhada com o lado retrato do telefone ou não?
Siavash
16

tente definir a orientação da tela. Isso resolve meu problema.

 mCamera.setDisplayOrientation(90);
ksu
fonte
5
no momento da gravação, ele salva a imagem do retrato na paisagem.
Akanksha Rathore
@Akanksha: essa bandeira se aplica apenas à exibição de visualização. Ele não altera a orientação do buffer retornado onPreviewFrame()ouonPictureTaken()
Alex Cohn
13
 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();
     }
}

tente este código

jitendra G2
fonte
3
no momento da gravação, ele salva a imagem do retrato na paisagem.
Akanksha Rathore
@Akanksha que provavelmente está relacionado aos parâmetros EXIF.
EpicPandaForce
4

Eu estava tendo um problema com a câmera frontal (problema de cabeça para baixo). Então usei o seguinte método documentado no Android Docs -

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);


    }
Zar E Ahmer
fonte
3
Este método vem da documentação da câmera: developer.android.com/reference/android/hardware/…
VinceFior
@VinceFior Algo errado se ele postar em documento oficial?
Ranjith Kumar
1
@RanjithKumar Não particularmente, eu só queria dar crédito à fonte e apontar as pessoas para um contexto maior. :)
VinceFior
3

Fiz isso seguindo o conselho de 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);
yngrdyn
fonte
0

Comparei meu código com o tutorial e o que finalmente foi corrigido foi colocar o seguinte código no meu AndroidManifext.xml: Na <activity>tag:

android:screenOrientation="landscape"
android:configChanges="keyboardHidden|orientation">
sbaechler
fonte
0
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();
    }
}
sofi37
fonte
0

Eu acho que o valor SENSOR_ORIENTATION explicará qual valor deve ser usado para a rotação em vez de codificar para 90 graus

CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
        if (manager == null) {
            Log.i(TAG, "camera manager is null");
            return;
        }
        for (String id: manager.getCameraIdList()) {
            CameraCharacteristics characteristics = manager.getCameraCharacteristics(id);
            Integer orientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
            Log.i(TAG, "camera sensor orientation is " + orientation);
        }
psykid
fonte