Chcę ustawić orientację kamery zgodnie z orientacją urządzenia w systemie Android, ale wydaje się, że nic nie działa. Próbowałem obrócić Surface oraz parametry aparatu, ale podgląd aparatu w trybie portretowym zawsze wychodzi do góry nogami. Musiałbym obrócić go o 90 stopni w prawo, aby był poprawny. Oto kod, którego teraz używam, który działa tylko w trybie poziomym.
SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() {
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
camera.release();
camera = null;
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
initCamera();
}
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.2;
double targetRatio = (double) w / h;
if (sizes == null)
return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
// Try to find an size match aspect ratio and size
for (Size size : sizes) {
Log.d(TAG, "Checking size " + size.width + "w " + size.height
+ "h");
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
// Cannot find the one match the aspect ratio, ignore the
// requirement
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Camera.Parameters parameters = camera.getParameters();
List<Size> sizes = parameters.getSupportedPreviewSizes();
Size optimalSize = getOptimalPreviewSize(sizes, width, height);
Log.d(TAG, "Surface size is " + width + "w " + height + "h");
Log.d(TAG, "Optimal size is " + optimalSize.width + "w " + optimalSize.height + "h");
parameters.setPreviewSize(optimalSize.width, optimalSize.height);
// parameters.setPreviewSize(width, height);
camera.setParameters(parameters);
camera.startPreview();
}
};
android
camera
orientation
surfaceview
Abhinav
źródło
źródło
Odpowiedzi:
Od innego członka i mój problem:
Problem z obracaniem kamery zależy od różnych urządzeń i określonej wersji.
Wersja 1.6: aby rozwiązać problem z rotacją i jest dobra dla większości urządzeń
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { p.set("orientation", "portrait"); p.set("rotation",90); } if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { p.set("orientation", "landscape"); p.set("rotation", 90); }
Wersja 2.1: zależy od rodzaju urządzeń, na przykład nie można naprawić problemu z XPeria X10, ale jest dobra dla X8 i Mini
Camera.Parameters parameters = camera.getParameters(); parameters.set("orientation", "portrait"); camera.setParameters(parameters);
Wersja 2.2: nie dla wszystkich urządzeń
camera.setDisplayOrientation(90);
http://code.google.com/p/android/issues/detail?id=1193#c42
źródło
Z Javadocs dla
setDisplayOrientation(int)
(wymaga poziomu API 9):public static void setCameraDisplayOrientation(Activity activity, int cameraId, android.hardware.Camera camera) { android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo(); android.hardware.Camera.getCameraInfo(cameraId, info); int rotation = activity.getWindowManager().getDefaultDisplay() .getRotation(); int degrees = 0; 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 (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { result = (info.orientation + degrees) % 360; result = (360 - result) % 360; // compensate the mirror } else { // back-facing result = (info.orientation - degrees + 360) % 360; } camera.setDisplayOrientation(result); }
źródło
CameraInfo
została wprowadzona dopiero na 9 poziomie API, więc metoda, którą opublikowałem, wymaga API na poziomie 9.result = (360 - result) % 360; // compensate the mirror
powinno zostać usunięte , zdjęcia z przedniego aparatu są inaczej obrócone nieprawidłowoTo rozwiązanie będzie działać na wszystkich wersjach Androida. Możesz użyć odbicia w Javie, aby działało na wszystkich urządzeniach z Androidem:
Zasadniczo należy utworzyć otokę odbicia, aby wywołać setDisplayOrientation systemu Android 2.2, zamiast wywoływać określoną metodę.
Metoda:
protected void setDisplayOrientation(Camera camera, int angle){ Method downPolymorphic; try { downPolymorphic = camera.getClass().getMethod("setDisplayOrientation", new Class[] { int.class }); if (downPolymorphic != null) downPolymorphic.invoke(camera, new Object[] { angle }); } catch (Exception e1) { } }
Zamiast używać camera.setDisplayOrientation (x), użyj setDisplayOrientation (camera, x) :
if (Integer.parseInt(Build.VERSION.SDK) >= 8) setDisplayOrientation(mCamera, 90); else { if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { p.set("orientation", "portrait"); p.set("rotation", 90); } if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { p.set("orientation", "landscape"); p.set("rotation", 90); } }
źródło
Camera.Parameters
. Spróbuj dodać następujący wiersz:Camera.Parameters p = camera.getParameters();
Napotkałem problem, gdy używałem ZBar do skanowania w kartach. Problem z orientacją aparatu. Korzystając z poniższego kodu, udało mi się rozwiązać problem. To nie jest cały fragment kodu. Skorzystaj tylko z pomocy.
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { if (isPreviewRunning) { mCamera.stopPreview(); } setCameraDisplayOrientation(mCamera); previewCamera(); } public void previewCamera() { try { // Hard code camera surface rotation 90 degs to match Activity view // in portrait mCamera.setPreviewDisplay(mHolder); mCamera.setPreviewCallback(previewCallback); mCamera.startPreview(); mCamera.autoFocus(autoFocusCallback); isPreviewRunning = true; } catch (Exception e) { Log.d("DBG", "Error starting camera preview: " + e.getMessage()); } } public void setCameraDisplayOrientation(android.hardware.Camera camera) { Camera.Parameters parameters = camera.getParameters(); android.hardware.Camera.CameraInfo camInfo = new android.hardware.Camera.CameraInfo(); android.hardware.Camera.getCameraInfo(getBackFacingCameraId(), camInfo); Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); int rotation = display.getRotation(); int degrees = 0; 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 (camInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { result = (camInfo.orientation + degrees) % 360; result = (360 - result) % 360; // compensate the mirror } else { // back-facing result = (camInfo.orientation - degrees + 360) % 360; } camera.setDisplayOrientation(result); } private int getBackFacingCameraId() { int cameraId = -1; // Search for the front facing camera int numberOfCameras = Camera.getNumberOfCameras(); for (int i = 0; i < numberOfCameras; i++) { Camera.CameraInfo info = new Camera.CameraInfo(); Camera.getCameraInfo(i, info); if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) { cameraId = i; break; } } return cameraId; }
źródło
W końcu naprawiłem to za pomocą aplikacji aparatu Google. Pobiera orientację telefonu za pomocą czujnika, a następnie odpowiednio ustawia tag EXIF. JPEG wychodzący z aparatu nie jest zorientowany automatycznie.
Ponadto podgląd z kamery działa poprawnie tylko w trybie poziomym. Jeśli chcesz, aby układ ćwiczeń był zorientowany pionowo, będziesz musiał to zrobić ręcznie, używając wartości z czujnika orientacji.
źródło
sprawdź to rozwiązanie
public static void setCameraDisplayOrientation(Activity activity, int cameraId, android.hardware.Camera camera) { android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo(); android.hardware.Camera.getCameraInfo(cameraId, info); int rotation = activity.getWindowManager().getDefaultDisplay() .getRotation(); int degrees = 0; 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 (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { result = (info.orientation + degrees) % 360; result = (360 - result) % 360; // compensate the mirror } else { // back-facing result = (info.orientation - degrees + 360) % 360; } camera.setDisplayOrientation(result); }
źródło
Ten problem został rozwiązany dawno temu, ale napotkałem pewne trudności ze złożeniem wszystkich elementów razem, więc oto moje ostateczne rozwiązanie, mam nadzieję, że pomoże to innym:
public void startPreview() { try { Log.i(TAG, "starting preview: " + started); // .... Camera.CameraInfo camInfo = new Camera.CameraInfo(); Camera.getCameraInfo(cameraIndex, camInfo); int cameraRotationOffset = camInfo.orientation; // ... Camera.Parameters parameters = camera.getParameters(); List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes(); Camera.Size previewSize = null; float closestRatio = Float.MAX_VALUE; int targetPreviewWidth = isLandscape() ? getWidth() : getHeight(); int targetPreviewHeight = isLandscape() ? getHeight() : getWidth(); float targetRatio = targetPreviewWidth / (float) targetPreviewHeight; Log.v(TAG, "target size: " + targetPreviewWidth + " / " + targetPreviewHeight + " ratio:" + targetRatio); for (Camera.Size candidateSize : previewSizes) { float whRatio = candidateSize.width / (float) candidateSize.height; if (previewSize == null || Math.abs(targetRatio - whRatio) < Math.abs(targetRatio - closestRatio)) { closestRatio = whRatio; previewSize = candidateSize; } } int rotation = getWindowManager().getDefaultDisplay().getRotation(); int degrees = 0; switch (rotation) { case Surface.ROTATION_0: degrees = 0; break; // Natural orientation case Surface.ROTATION_90: degrees = 90; break; // Landscape left case Surface.ROTATION_180: degrees = 180; break;// Upside down case Surface.ROTATION_270: degrees = 270; break;// Landscape right } int displayRotation; if (isFrontFacingCam) { displayRotation = (cameraRotationOffset + degrees) % 360; displayRotation = (360 - displayRotation) % 360; // compensate // the // mirror } else { // back-facing displayRotation = (cameraRotationOffset - degrees + 360) % 360; } Log.v(TAG, "rotation cam / phone = displayRotation: " + cameraRotationOffset + " / " + degrees + " = " + displayRotation); this.camera.setDisplayOrientation(displayRotation); int rotate; if (isFrontFacingCam) { rotate = (360 + cameraRotationOffset + degrees) % 360; } else { rotate = (360 + cameraRotationOffset - degrees) % 360; } Log.v(TAG, "screenshot rotation: " + cameraRotationOffset + " / " + degrees + " = " + rotate); Log.v(TAG, "preview size: " + previewSize.width + " / " + previewSize.height); parameters.setPreviewSize(previewSize.width, previewSize.height); parameters.setRotation(rotate); camera.setParameters(parameters); camera.setPreviewDisplay(mHolder); camera.startPreview(); Log.d(TAG, "preview started"); started = true; } catch (IOException e) { Log.d(TAG, "Error setting camera preview: " + e.getMessage()); } }
źródło