Android – предварительный просмотр камеры в боковом направлении

Я использую Предварительный просмотр, чтобы показать, что камера видит на экране.

Я могу заставить все работать нормально, созданная поверхность, набор поверхности и поверхность.

Однако он всегда отображает изображение с неправильным углом 90 градусов в портретном режиме.

Например, на картинке:

Alt text

Я знаю, что используя следующий код, вы можете установить изображение прямо:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 

Однако у меня есть Предварительный просмотр внутри Activity, в котором есть другие элементы, и для моего Activity не имеет смысла отображаться в ландшафтном режиме. (По умолчанию он отключен)

Поэтому мне было интересно, так или иначе, просто изменить ориентацию Preview? И оставите остальную часть моей деятельности правильно отображаемой в режиме портрета?

Или в любом случае, чтобы повернуть предварительный просмотр так, чтобы он отображался правильно?

Эта проблема, как представляется, начиналась как ошибка с определенным оборудованием, см. Здесь, но ее можно преодолеть, используя вызов mCamera.setDisplayOrientation (в градусах), доступный в API 8. Так вот как я его реализую:

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

И метод previewCamera:

 public void previewCamera() { try { mCamera.setPreviewDisplay(mSurfaceHolder); mCamera.startPreview(); isPreviewRunning = true; } catch(Exception e) { Log.d(APP_CLASS, "Cannot start preview", e); } } 

Это было на HTC Desire, и я должен был сначала включить в протоколы регистрации в каждом из проверок вращения, чтобы сказать, что такое поворот, а затем отлаживается на устройстве и наблюдал вывод logCat, когда я вращал устройство. Для HTC Desire 0 был телефоном, как вы ожидали (портрет), 90 градусов поворачивали телефон на 90 градусов COUNTER-CLOCKWISE (я предположил, что это было бы по часовой стрелке). В коде вы увидите, что мне не нужно было поворачивать изображение, когда телефон находился на уровне 90 или 180 градусов – устройство, похоже, справлялось с этим. Только одна точка не работает должным образом: вращение на 270 градусов – это когда вы поворачиваете устройство на 90 градусов по часовой стрелке, а вращение дисплея работает нормально, но если вы поворачиваете устройство на 270 градусов против часовой стрелки, оно, похоже, не компенсирует его должным образом.

PS Обратите внимание на swapover ширины и высоты при соответствующих поворотах.

Попробуйте установить ориентацию дисплея. Это решает мою проблему.

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

Попробуйте этот код

Я сделал это, получив совет mCamera.setDisplayOrientation (90); Но также повернул растровое изображение, потому что по какой-то причине другие подходы не работают для меня в версии 2.3.3.

Для поворота растрового изображения я сделал следующее:

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

Я сравнил свой код с учебником, и наконец, исправил, что он помещает следующий код в мой AndroidManifext.xml: в <activity> :

 android:screenOrientation="landscape" android:configChanges="keyboardHidden|orientation"> 

У меня возникла проблема с передней камерой (проблема с верхней стороной). Тогда я использую этот метод

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

Эта часть линии отлично работала для меня

  static { ORIENTATIONS.append(Surface.ROTATION_0, 90); ORIENTATIONS.append(Surface.ROTATION_90, 180); ORIENTATIONS.append(Surface.ROTATION_180, 270); ORIENTATIONS.append(Surface.ROTATION_270, 360); }