Uwaga: ta strona dotyczy pakietu Aparat2. Jeśli Twoja aplikacja nie wymaga konkretnych, niskopoziomowych funkcji z Aparatu 2, zalecamy używanie AparatuX. Aparaty CameraX i Aparat 2 obsługują Androida 5.0 (poziom interfejsu API 21) i nowsze wersje.
Podglądy aparatów i aparatów nie zawsze mają tę samą orientację na Androidzie urządzenia.
Kamera na urządzeniu jest w stałym położeniu niezależnie od tego, czy to telefon, tablet lub komputer. Gdy orientacja urządzenia ulegnie zmianie, zmiany orientacji aparatu.
W związku z tym aplikacje aparatu zwykle przyjmują stałą relację między od orientacji urządzenia i formatu obrazu podglądu z aparatu. Gdy telefonu jest w orientacji pionowej, podgląd aparatu zakłada, że jest wyższy. niż ma szerokość. Gdy telefon (i aparat) ustawisz poziomo, obraz z aparatu powinien być szerszy niż wyższy.
Te założenia podważają jednak nowe formaty, takie jak urządzenia składane urządzeń i trybów wyświetlania na przykład wiele okien oraz Wiele ekranów. Urządzenia składane zmieniają rozmiar wyświetlacza i format obrazu bez zmian orientacji ekranu. Tryb wielu okien ogranicza aplikacje aparatu do części na ekranie, skalując podgląd z aparatu niezależnie od orientacji urządzenia. Tryb wielu wyświetlaczy umożliwia korzystanie z ekranów dodatkowych, które mogą nie musi mieć tę samą orientację co główny wyświetlacz.
Orientacja aparatu
Definicja zgodności z Androidem określa, że czujnik obrazu „MUSI być zorientowany tak, aby długi i długości ekranu. Oznacza to, że gdy urządzenie jest ustawione poziomo, aparat MUSI robić zdjęcia do orientacji poziomej. Działa to niezależnie od naturalnych ustawień, orientacja; Dotyczy to zarówno urządzeń w orientacji poziomej, w orientacji pionowej.
Układ kamery i ekranu maksymalizuje obszar wyświetlania kamery wizjer w aplikacji aparatu. Ponadto czujniki obrazu zwykle zapisują dane w format obrazu w orientacji poziomej, gdzie najczęściej jest używany format 4:3.
Czujnik aparatu ma naturalną orientację poziomą. Na ilustracji 1 czujnik przedniego aparatu (skieruj aparat w tym samym kierunku co wyświetlacza) jest obracany o 270 stopni względem telefonu, aby zapewnić Definicja zgodności z Androidem.
Aby udostępnić aplikacjom obrót czujnika,
Interfejs API camera2 obejmuje
SENSOR_ORIENTATION
.
jest stała. W przypadku większości telefonów i tabletów urządzenie zgłasza orientację czujnika.
270 stopni dla przedniego aparatu i 90 stopni
dla tylnej części urządzenia, aby zapewnić jej dłuższą krawędź.
przylegaj do czujnika dłuższą krawędzią urządzenia. Laptopy zazwyczaj zgłaszają
od 0 do 180 stopni.
Czujniki obrazu z aparatu zapisują dane (bufor obrazu) w
w naturalnej orientacji czujnika (poziomo), bufor obrazu należy obracać
liczba stopni określonej przez SENSOR_ORIENTATION
na podgląd z aparatu
wyświetlają się pionowo w naturalnej orientacji. W przypadku aparatów przednich
obraca się w lewo. dla aparatów z tyłu, w prawo.
Na przykład w przypadku przedniego aparatu na ilustracji 1 buforowanie obrazu generowany przez czujnik aparatu wygląda tak:
Obraz musi być obrócony o 270 stopni w lewo, aby podgląd orientacja odpowiada orientacji urządzenia:
Tylny aparat mógłby wygenerować bufor obrazu w tej samej orientacji.
jako bufor powyżej, ale SENSOR_ORIENTATION
ma 90 stopni. W rezultacie
jest obrócony o 90 stopni w prawo.
Obracanie urządzenia
Obrót urządzenia to liczba stopni obrócenia urządzenia orientacji ekranu. Na przykład telefon w orientacji poziomej o 90 lub 270 stopni, w zależności od kierunku obrotu.
Bufor obrazu z czujnika aparatu musi być obrócony o taką samą liczbę stopni jak obrotu urządzenia (oprócz stopni pochylenia czujnika) w by podgląd z aparatu był ustawiony pionowo.
Obliczanie orientacji
Prawidłowa orientacja podglądu z aparatu uwzględnia czujnika. orientację i obrót urządzenia.
Ogólny obrót bufora obrazu czujnika można obliczyć za pomocą funkcji następujący wzór:
rotation = (sensorOrientationDegrees - deviceOrientationDegrees * sign + 360) % 360
gdzie sign
to 1
– przednie aparaty, -1
– aparat tylny.
W przypadku aparatów przednich bufor obrazu jest obracany w lewo (od naturalnej orientacji czujnika). W przypadku aparatów tylnych bufor obrazu jest obrócony w prawo.
Wyrażenie deviceOrientationDegrees * sign + 360
konwertuje obrót urządzenia
z tyłu na przeciwnie do ruchu wskazówek zegara dla aparatów z tyłu (na przykład
możesz zmienić 270 stopni w lewo na 90 stopni w prawo). Modulo
skaluje wynik do 360 stopni (na przykład skalowanie do 540 stopni)
stopni obrotu do 180 stopni).
Różne interfejsy API raportują rotację urządzeń w różny sposób:
Display#getRotation()
obraca urządzenie w lewo (od punktu użytkownika widoku). Ta wartość zostaje dodana do powyższej formuły w niezmienionej formie.OrientationEventListener#onOrientationChanged()
zwraca obrót urządzenia w prawo (z punktu widzenia użytkownika). Zamień wartość na potrzeby użycia w powyższej formule.
Przednie aparaty
Na ilustracji 2 pokazujemy bufor obrazu wygenerowany przez czujnik aparatu:
Bufor musi być obrócony o 270 stopni w lewo, aby dostosować go do czujnika orientacja (zobacz Orientacja aparatu powyżej):
Następnie bufor jest obrócony o dodatkowe 90 stopni w lewo, biorąc pod uwagę obrót urządzenia, co powinno zapewnić jego prawidłową orientację. podgląd aparatu na ilustracji 2:
Oto obraz obrócony w prawo i poziomo:
Bufor obrazu:
Bufor musi być obrócony o 270 stopni w lewo, aby dostosować go do czujnika orientacja:
Następnie bufor jest obrócony o kolejne 270 stopni w lewo, aby uwzględnić obrót urządzenia:
Tylne kamery
Tylne aparaty mają zazwyczaj orientację 90 stopni widoczne z tyłu urządzenia). Podczas ustawiania podglądu z aparatu funkcja bufor obrazu czujnika jest obrócony w prawo zgodnie z intensywnością obrotu czujnika (a nie w lewo, jak w przypadku przednich aparatów), a następnie obraz bufor jest obrócony w lewo zgodnie z obrotem urządzenia.
Na ilustracji 4 widać bufor obrazu z czujnika aparatu:
Bufor musi być obrócony o 90 stopni w prawo, aby dostosować go do czujnika orientacja:
Następnie bufor obraca się o 270 stopni w lewo, by uwzględnić rotacja:
Format obrazu
Współczynnik proporcji wyświetlacza zmienia się wraz ze zmianą orientacji urządzenia, ale także wtedy, gdy urządzenia składane można składać i rozwijać, gdy rozmiar okien zmienia się w trybie wielu okien. i otwierają się na dodatkowych ekranach.
Bufor obrazu z czujnika aparatu musi być zorientowany i przeskalowany tak, aby orientacja i współczynnik proporcji elementu interfejsu wizjera. dynamicznie zmienia orientację – niezależnie od tego, czy zmienia się urządzenie orientacji ekranu.
W przypadku nowych formatów, trybów z wieloma oknami i różnymi wyświetlaczami, jeśli aplikacja przyjmuje, że podgląd z aparatu ma taką samą orientację jak urządzenie (pionowej lub poziomej) podgląd może mieć nieprawidłową orientację lub przeskalowanie nieprawidłowo lub jedno i drugie.
Na ilustracji 5 aplikacja błędnie uznała, że urządzenie zostało obrócone o 90 stopni. stopni w lewo; więc aplikacja obróciła podgląd tyle samo.
Na ilustracji 6 aplikacja nie dostosowała formatu obrazu bufora do włącz jego odpowiednie skalowanie, aby pasowało do nowych wymiarów interfejsu podglądu aparatu. .
W aplikacjach o stałej orientacji ekranu zazwyczaj występują problemy na urządzeniach składanych i na innych urządzeniach z dużym ekranem, takich jak laptopy:
Na ilustracji 7 interfejs aplikacji aparatu jest obrócony, ponieważ orientacja aplikacji jest ograniczona tylko do orientacji pionowej. Obraz w wizjerze ma prawidłową orientację względem czujnika aparatu.
Tryb wstawki w orientacji pionowej
aplikacje aparatu, które nie obsługują trybu wielu okien;
(resizeableActivity="false"
)
i ograniczyć orientację,
(screenOrientation="portrait"
)
lub screenOrientation="landscape"
)
można umieścić w orientacji pionowej na urządzeniach z dużym ekranem, aby zapewnić ich odpowiednią orientację
podgląd z aparatu.
Aplikacje tylko w orientacji pionowej w trybie pionowym nawet jeśli jest ustawiony w orientacji poziomej. W przypadku aplikacji tylko w orientacji poziomej są wyświetlane czarne pasy, mimo że format obrazu jest pionowy. Obraz z aparatu jest obrócony w celu wyrównania z interfejsem aplikacji, przycięte tak, aby pasowały do formatu obrazu podglądu z aparatu, a następnie przeskalowany, by wypełnić podgląd.
Tryb wstawienia obrazu pionowego jest wyzwalany po wybraniu formatu obrazu z aparatu z czujnikiem i współczynnikiem proporcji głównej aktywności aplikacji nie są zgodne.
Na ilustracji 8 obrócono aplikację aparatu w orientacji pionowej, aby wyświetlić interfejs. pionowo na wyświetlaczu laptopa. W aplikacji pojawiają się czarne pasy z powodu różnicy proporcje między aplikacją w orientacji pionowej a ekranem w orientacji poziomej. Aparat obraz podglądu został obrócony w celu skompensowania obrócenia interfejsu aplikacji (w wyniku w trybie pionowym), a obraz został przycięty i przeskalowany do orientacji pionowej, co zmniejszy pole widzenia.
Obracanie, przycinanie, skalowanie
Tryb wstawki w orientacji pionowej jest wywoływany w przypadku aplikacji aparatu przeznaczonego tylko do wyświetlania w orientacji pionowej na ekranie w orientacji poziomej:
Aplikacja ma poziome pasy w orientacji pionowej:
Obraz z kamery jest obrócony o 90 stopni, aby dostosować aplikacja:
Obraz jest przycinany do formatu podglądu z aparatu, a następnie skalowany wypełnij podgląd (pole widzenia jest zmniejszone):
W przypadku urządzeń składanych czujnik może być w orientacji pionowej. a wyświetlacz jest w orientacji poziomej:
Podgląd z aparatu jest obracany w celu dostosowania się do orientacji czujnika, Zdjęcie jest właściwie zorientowane w wizjerze, ale aplikacja tylko do wyświetlania w orientacji pionowej jest obrócone.
Wbudowany tryb pionowy wymaga tylko dodania czarnych pasów do aplikacji w orientacji pionowej aby zapewnić prawidłową orientację aplikacji i podglądu z aparatu:
Interfejs API
Od Androida 12 (poziom interfejsu API 31) aplikacje mogą też bezpośrednio sterować wbudowaną obrazem w orientacji pionowej.
za pomocą
SCALER_ROTATE_AND_CROP
właściwość CaptureRequest
zajęcia.
Wartość domyślna to
SCALER_ROTATE_AND_CROP_AUTO
,
który umożliwia systemowi wywoływanie trybu wstawienia w pionie.
SCALER_ROTATE_AND_CROP_90
jak działa
wbudowana orientacja pionowa.
Nie wszystkie urządzenia obsługują wszystkie wartości SCALER_ROTATE_AND_CROP
. Aby uzyskać listę
obsługiwanych wartości, odwołanie
CameraCharacteristics#SCALER_AVAILABLE_ROTATE_AND_CROP_MODES
Aparat X
biblioteka Jetpack CameraX, umożliwia stworzenie wizjera aparatu pasującego do orientacji czujnika to proste zadanie.
Element układu PreviewView
tworzy podgląd z aparatu, automatycznie dostosowując się do orientacji czujnika,
obrót i skalowanie urządzenia. PreviewView
zachowuje format obrazu
i obrazu z aparatu, stosując
FILL_CENTER
.
typ skali, który wyśrodkowuje obraz, ale może go przyciąć w celu dopasowania do wymiarów
PreviewView
. Aby obraz z aparatu był w formie czarnych pasów, ustaw typ skali na
FIT_CENTER
Podstawowe informacje na temat tworzenia podglądu z kamery w PreviewView
znajdziesz w tych artykułach:
Zaimplementuj podgląd.
Pełną przykładową implementację znajdziesz w
CameraXBasic
w repozytorium GitHub.
Wizjer aparatu
Podobnie jak w przypadku użycia funkcji Podgląd, wizjer aparatu. biblioteka udostępnia zestaw narzędzi ułatwiających tworzenie podglądu z aparatu. Nie wymaga ona modelu CameraX Core, więc możesz płynnie zintegrować go istniejącą bazę kodu Camera2.
Zamiast używać atrybutu
Surface
bezpośrednio, możesz użyć funkcji
CameraViewfinder
widżet do wyświetlania obrazu z kamery Aparat2.
Funkcja CameraViewfinder
wewnętrznie używa TextureView
lub SurfaceView
aby wyświetlić obraz z kamery i zastosować wymagane przekształcenia
poprawnie wyświetlać wizjer.
Wiąże się to z skorygowaniem formatu obrazu, skali i obrotu.
Aby poprosić o powierzchnię z obiektu CameraViewfinder
, musisz
utwórz element ViewfinderSurfaceRequest
.
To żądanie zawiera wymagania dotyczące rozdzielczości powierzchni i aparatu
informacje z: CameraCharacteristics
.
Dzwonię pod numer requestSurfaceAsync()
wysyła żądanie do dostawcy powierzchni, którym jest TextureView
lub
SurfaceView
i otrzymuje ListenableFuture
o wartości Surface
.
Dzwonię pod numer markSurfaceSafeToRelease()
powiadamia dostawcę powierzchni, że nie jest ona potrzebna i jest powiązana
zasobów, które można zwolnić.
Kotlin
fun startCamera(){ val previewResolution = Size(width, height) val viewfinderSurfaceRequest = ViewfinderSurfaceRequest(previewResolution, characteristics) val surfaceListenableFuture = cameraViewfinder.requestSurfaceAsync(viewfinderSurfaceRequest) Futures.addCallback(surfaceListenableFuture, object : FutureCallback<Surface> { override fun onSuccess(surface: Surface) { /* create a CaptureSession using this surface as usual */ } override fun onFailure(t: Throwable) { /* something went wrong */} }, ContextCompat.getMainExecutor(context)) }
Java
void startCamera(){ Size previewResolution = new Size(width, height); ViewfinderSurfaceRequest viewfinderSurfaceRequest = new ViewfinderSurfaceRequest(previewResolution, characteristics); ListenableFuture<Surface> surfaceListenableFuture = cameraViewfinder.requestSurfaceAsync(viewfinderSurfaceRequest); Futures.addCallback(surfaceListenableFuture, new FutureCallback<Surface>() { @Override public void onSuccess(Surface result) { /* create a CaptureSession using this surface as usual */ } @Override public void onFailure(Throwable t) { /* something went wrong */} }, ContextCompat.getMainExecutor(context)); }
SurfaceView
SurfaceView
to
do podglądu z aparatu, jeśli podgląd
wymagają przetworzenia i nie jest animowany.
SurfaceView
automatycznie obraca bufor obrazu z czujnika aparatu, aby dopasować
orientacji wyświetlacza, uwzględniając zarówno orientację czujnika,
i rotacji. Bufor obrazu jest jednak skalowany tak, aby pasował do: SurfaceView
bez uwzględniania formatu obrazu.
Musisz się upewnić, że format bufora obrazu jest zgodny z formatem
współczynnika SurfaceView
, którą można uzyskać, skalując zawartość
z SurfaceView
w komponencie
onMeasure()
.
:
(Kod źródłowy computeRelativeRotation()
znajduje się w
Rotacja względna poniżej).
Kotlin
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { val width = MeasureSpec.getSize(widthMeasureSpec) val height = MeasureSpec.getSize(heightMeasureSpec) val relativeRotation = computeRelativeRotation(characteristics, surfaceRotationDegrees) if (previewWidth > 0f && previewHeight > 0f) { /* Scale factor required to scale the preview to its original size on the x-axis. */ val scaleX = if (relativeRotation % 180 == 0) { width.toFloat() / previewWidth } else { width.toFloat() / previewHeight } /* Scale factor required to scale the preview to its original size on the y-axis. */ val scaleY = if (relativeRotation % 180 == 0) { height.toFloat() / previewHeight } else { height.toFloat() / previewWidth } /* Scale factor required to fit the preview to the SurfaceView size. */ val finalScale = min(scaleX, scaleY) setScaleX(1 / scaleX * finalScale) setScaleY(1 / scaleY * finalScale) } setMeasuredDimension(width, height) }
Java
@Override void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); int relativeRotation = computeRelativeRotation(characteristics, surfaceRotationDegrees); if (previewWidth > 0f && previewHeight > 0f) { /* Scale factor required to scale the preview to its original size on the x-axis. */ float scaleX = (relativeRotation % 180 == 0) ? (float) width / previewWidth : (float) width / previewHeight; /* Scale factor required to scale the preview to its original size on the y-axis. */ float scaleY = (relativeRotation % 180 == 0) ? (float) height / previewHeight : (float) height / previewWidth; /* Scale factor required to fit the preview to the SurfaceView size. */ float finalScale = Math.min(scaleX, scaleY); setScaleX(1 / scaleX * finalScale); setScaleY(1 / scaleY * finalScale); } setMeasuredDimension(width, height); }
Więcej informacji o implementowaniu funkcji SurfaceView
w trybie podglądu aparatu znajdziesz tutaj:
Orientacje aparatu.
Widok tekstury
TextureView
jest mniej wydajny niż
SurfaceView
– i więcej pracy – ale TextureView
daje Ci maksimum
nad podglądem z aparatu.
TextureView
obraca bufor obrazu czujnika na podstawie orientacji czujnika, ale
nie obsługuje obracania urządzeń ani skalowania podglądu.
Skalowanie i obrót można zakodować
Transformacja matrycy. Aby dowiedzieć się, jak:
poprawnie przeskalować i obrócić TextureView
, patrz
Obsługa powierzchni z możliwością zmiany rozmiaru w aplikacji Aparat
Rotacja względna
Względny obrót czujnika aparatu to wartość obrotu wymagana do dopasuj dane wyjściowe czujnika aparatu do orientacji urządzenia.
Obrót względny jest używany przez komponenty takie jak SurfaceView
i TextureView
w celu określenia współczynników skalowania x i y dla obrazu podglądu. Jest też używany do
i określić obrót bufora obrazu czujnika.
CameraCharacteristics
oraz
Zajęcia Surface
umożliwiają obliczenie:
względna obrót czujnika aparatu:
Kotlin
/** * Computes rotation required to transform the camera sensor output orientation to the * device's current orientation in degrees. * * @param characteristics The CameraCharacteristics to query for the sensor orientation. * @param surfaceRotationDegrees The current device orientation as a Surface constant. * @return Relative rotation of the camera sensor output. */ public fun computeRelativeRotation( characteristics: CameraCharacteristics, surfaceRotationDegrees: Int ): Int { val sensorOrientationDegrees = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION)!! // Reverse device orientation for back-facing cameras. val sign = if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT ) 1 else -1 // Calculate desired orientation relative to camera orientation to make // the image upright relative to the device orientation. return (sensorOrientationDegrees - surfaceRotationDegrees * sign + 360) % 360 }
Java
/** * Computes rotation required to transform the camera sensor output orientation to the * device's current orientation in degrees. * * @param characteristics The CameraCharacteristics to query for the sensor orientation. * @param surfaceRotationDegrees The current device orientation as a Surface constant. * @return Relative rotation of the camera sensor output. */ public int computeRelativeRotation( CameraCharacteristics characteristics, int surfaceRotationDegrees ){ Integer sensorOrientationDegrees = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION); // Reverse device orientation for back-facing cameras. int sign = characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT ? 1 : -1; // Calculate desired orientation relative to camera orientation to make // the image upright relative to the device orientation. return (sensorOrientationDegrees - surfaceRotationDegrees * sign + 360) % 360; }
Dane dotyczące okien
Rozmiar ekranu nie powinien być stosowany do określania wymiarów kamery wizjer; aplikacja aparatu może być uruchomiona na części ekranu w trybie wielu okien na urządzeniach mobilnych lub w trybie Free-from w ChromeOS.
WindowManager#getCurrentWindowMetrics()
(dodane na poziomie interfejsu API 30) zwraca rozmiar okna aplikacji, a nie
do rozmiaru ekranu. Metody biblioteki Jetpack WindowManager
WindowMetricsCalculator#computeCurrentWindowMetrics()
oraz
WindowInfoTracker#currentWindowMetrics()
zapewniają podobną pomoc dzięki zgodności wstecznej z interfejsem API poziomu 14.
Obrót o 180 stopni
Obrót urządzenia o 180 stopni (na przykład z orientacji naturalnej do
naturalnej orientacji do góry nogami) nie powoduje
onConfigurationChanged()
oddzwanianie. W związku z tym podgląd z aparatu może być do góry nogami.
Aby wykryć obrót o 180 stopni, zaimplementuj funkcję
DisplayListener
i sprawdź obrót urządzenia, wysyłając wywołanie do
Display#getRotation()
w
onDisplayChanged()
oddzwanianie.
Wyjątkowe materiały
Przed Androidem 10 tylko najbardziej widoczna aktywność w trybie wielu okien
środowisko było w stanie RESUMED
. Było to mylące dla użytkowników, ponieważ
system nie wskaże, która aktywność została wznowiona.
W Androidzie 10 (poziom interfejsu API 29) wprowadzono wielokrotne wznawianie, w których wszystkie widoczne działania
są w stanie RESUMED
. Widoczne aktywności nadal mogą trafiać do pola PAUSED
jeśli na przykład nad działaniem znajduje się przezroczysta aktywność lub
aktywności nie można zaznaczyć, na przykład w trybie obrazu w obrazie (patrz
Obsługa funkcji obraz w obrazie).
Aplikacja używająca kamery, mikrofonu lub dowolnych bądź innych
zasób singleton na poziomie API 29 lub wyższym musi obsługiwać wielokrotne wznawianie. Dla:
Jeśli na przykład 3 wznowione działania chcą korzystać z kamery, tylko jedna z nich
na dostęp do tego wyjątkowego zasobu. Każde działanie musi implementować
onDisconnected()
wywołanie zwrotne, aby zwracać uwagę na zapobiegawczy dostęp do kamery przez wyższy priorytet
działania.
Więcej informacji: Wielokrotne wznowienie.
Dodatkowe materiały
- Przykładowe treści znajdziesz w sekcji Camera2 Basic. w GitHubie.
- Więcej informacji o przypadku użycia podglądu AparatuX znajdziesz na stronie Aparat X Zaimplementuj podgląd.
- Aby zobaczyć przykładową implementację podglądu aparatu CameraX, zobacz AparatXPodstawowe w repozytorium GitHub.
- Informacje o podglądzie z aparatu w ChromeOS znajdziesz w tych artykułach: Orientacje aparatu.
- Informacje o programowaniu na urządzenia składane znajdziesz na stronie Więcej informacji o urządzeniach składanych