این مبحث نحوه تنظیم موارد استفاده CameraX را در برنامه خود برای دریافت تصاویر با اطلاعات چرخش صحیح، چه از ImageAnalysis
یا ImageCapture
نشان می دهد. بنابراین:
-
Analyzer
مورد استفادهImageAnalysis
باید فریم هایی را با چرخش صحیح دریافت کند. - کیس استفاده
ImageCapture
باید با چرخش صحیح عکس بگیرد.
اصطلاحات
این مبحث از اصطلاحات زیر استفاده می کند، بنابراین درک معنای هر اصطلاح مهم است:
- جهت نمایش
- این به این اشاره دارد که کدام سمت دستگاه در موقعیت رو به بالا قرار دارد و می تواند یکی از چهار مقدار باشد: عمودی، منظره، پرتره معکوس، یا منظره معکوس.
- چرخش نمایشگر
- این مقداری است که توسط
Display.getRotation()
برگردانده شده است و نشان دهنده درجاتی است که دستگاه در خلاف جهت عقربه های ساعت از جهت طبیعی خود می چرخد. - چرخش هدف
- این نشان دهنده تعداد درجاتی است که از طریق آنها می توان دستگاه را در جهت عقربه های ساعت چرخاند تا به جهت طبیعی خود برسد.
نحوه تعیین چرخش هدف
مثال های زیر نحوه تعیین چرخش هدف برای یک دستگاه را بر اساس جهت گیری طبیعی آن نشان می دهد.
مثال 1: جهت گیری طبیعی پرتره
مثال دستگاه: Pixel 3 XL | |
---|---|
جهت گیری طبیعی = پرتره چرخش نمایشگر = 0 | |
جهت گیری طبیعی = پرتره چرخش نمایشگر = 90 |
مثال 2: جهت گیری طبیعی منظر
مثال دستگاه: Pixel C | |
---|---|
جهت گیری طبیعی = منظر چرخش نمایشگر = 0 | |
جهت گیری طبیعی = منظر چرخش نمایشگر = 270 |
چرخش تصویر
کدام پایان است؟ جهت سنسور در اندروید به عنوان یک مقدار ثابت تعریف می شود که نشان دهنده درجات (0، 90، 180، 270) چرخش سنسور از بالای دستگاه در زمانی که دستگاه در موقعیت طبیعی قرار دارد، می باشد. برای همه موارد در نمودارها، چرخش تصویر توضیح میدهد که چگونه دادهها باید در جهت عقربههای ساعت چرخانده شوند تا عمودی ظاهر شوند.
مثالهای زیر نشان میدهند که چرخش تصویر بسته به جهت سنسور دوربین چقدر باید باشد. آنها همچنین فرض می کنند که چرخش هدف روی چرخش نمایشگر تنظیم شده است.
مثال 1: سنسور 90 درجه چرخیده است
مثال دستگاه: Pixel 3 XL | |
---|---|
چرخش نمایشگر = 0 | |
چرخش نمایشگر = 90 |
مثال 2: سنسور 270 درجه چرخیده است
مثال دستگاه: Nexus 5X | |
---|---|
چرخش نمایشگر = 0 | |
چرخش نمایشگر = 90 |
مثال 3: سنسور 0 درجه چرخیده است
مثال دستگاه: Pixel C (تبلت) | |
---|---|
چرخش نمایشگر = 0 | |
چرخش نمایشگر = 270 |
محاسبه چرخش تصویر
تجزیه و تحلیل تصویر
ImageAnalysis
's Analyzer
تصاویر را از دوربین به شکل ImageProxy
s دریافت می کند. هر تصویر حاوی اطلاعات چرخش است که از طریق:
val rotation = imageProxy.imageInfo.rotationDegrees
این مقدار نشان دهنده درجه هایی است که تصویر باید در جهت عقربه های ساعت بچرخد تا با چرخش هدف ImageAnalysis
مطابقت داشته باشد. در زمینه یک برنامه اندروید، چرخش هدف ImageAnalysis
معمولاً با جهت صفحه نمایش مطابقت دارد.
ImageCapture
یک تماس پاسخ به یک نمونه ImageCapture
متصل می شود تا زمانی که نتیجه عکسبرداری آماده است، سیگنال دهد. نتیجه می تواند یا تصویر گرفته شده یا یک خطا باشد.
هنگام گرفتن عکس، پاسخ تماس ارائه شده می تواند یکی از انواع زیر باشد:
-
OnImageCapturedCallback
: تصویری را با دسترسی درون حافظه به شکلImageProxy
دریافت می کند. -
OnImageSavedCallback
: زمانی فراخوانی می شود که تصویر گرفته شده با موفقیت در مکان مشخص شده توسطImageCapture.OutputFileOptions
ذخیره شود. گزینه ها می توانند یکFile
، یکOutputStream
یا یک مکان درMediaStore
را مشخص کنند.
چرخش تصویر گرفته شده، صرف نظر از فرمت آن ( ImageProxy
، File
، OutputStream
، MediaStore Uri
) نشان دهنده درجه های چرخشی است که تصویر گرفته شده باید در جهت عقربه های ساعت بچرخد تا با چرخش هدف ImageCapture
مطابقت داشته باشد، که دوباره در زمینه یک برنامه اندروید، معمولاً با جهت صفحه نمایش مطابقت دارد.
بازیابی چرخش تصویر گرفته شده را می توان به یکی از روش های زیر انجام داد:
ImageProxy
val rotation = imageProxy.imageInfo.rotationDegrees
File
val exif = Exif.createFromFile(file) val rotation = exif.rotation
OutputStream
val byteArray = outputStream.toByteArray() val exif = Exif.createFromInputStream(ByteArrayInputStream(byteArray)) val rotation = exif.rotation
MediaStore uri
val inputStream = contentResolver.openInputStream(outputFileResults.savedUri) val exif = Exif.createFromInputStream(inputStream) val rotation = exif.rotation
چرخش یک تصویر را تأیید کنید
موارد استفاده ImageAnalysis
و ImageCapture
پس از درخواست موفقیت آمیز عکسبرداری، ImageProxy
را از دوربین دریافت می کنند. ImageProxy
یک تصویر و اطلاعات مربوط به آن، از جمله چرخش آن را بسته بندی می کند. این اطلاعات چرخش نشان دهنده درجاتی است که تصویر باید با چرخش هدف مورد استفاده مطابقت داشته باشد.
دستورالعمل های چرخش هدف ImageCapture/ImageAnalysis
از آنجایی که بسیاری از دستگاهها بهطور پیشفرض برای عمودی یا منظره معکوس نمیچرخند، برخی از برنامههای Android از این جهتگیریها پشتیبانی نمیکنند. اینکه آیا یک برنامه از آن پشتیبانی می کند یا نه، نحوه به روز رسانی چرخش هدف موارد استفاده را تغییر می دهد.
در زیر دو جدول وجود دارد که نحوه هماهنگ نگه داشتن چرخش هدف موارد استفاده با چرخش نمایشگر را تعریف می کند. اولی نشان می دهد که چگونه می توان این کار را در حین پشتیبانی از هر چهار جهت انجام داد. دومی فقط جهت گیری هایی را که دستگاه به طور پیش فرض می چرخد، کنترل می کند.
برای انتخاب دستورالعمل هایی که در برنامه خود دنبال کنید:
بررسی کنید که آیا «
Activity
دوربین» برنامه شما جهت قفل شده، جهت قفل آن قفل نیست یا تغییرات پیکربندی جهت را لغو می کند.تصمیم بگیرید که آیا
Activity
دوربین» برنامه شما باید هر چهار جهت دستگاه (عمودی، عمودی معکوس، افقی و منظره معکوس) را انجام دهد یا اینکه فقط باید جهت گیری هایی را که دستگاهی که روی آن اجرا می شود به طور پیش فرض پشتیبانی می کند، انجام دهد.
از هر چهار جهت پشتیبانی کنید
این جدول دستورالعملهای خاصی را برای مواردی که دستگاه برای پرتره معکوس نمیچرخد، ذکر میکند. همین امر را می توان برای دستگاه هایی اعمال کرد که برای معکوس کردن منظره نمی چرخند.
سناریو | رهنمودها | حالت تک پنجره ای | حالت چند پنجره ای تقسیم صفحه |
---|---|---|---|
جهت آنلاک | هر بار که Activity ایجاد میشود، موارد استفاده را تنظیم کنید، مانند پاسخ به تماس onCreate() Activity . | ||
از OrientationEventListener 's onOrientationChanged() استفاده کنید. در داخل callback، چرخش هدف موارد استفاده را به روز کنید. این کار مواردی را کنترل می کند که سیستم حتی پس از تغییر جهت، Activity را دوباره ایجاد نمی کند، مانند زمانی که دستگاه 180 درجه می چرخد. | همچنین زمانی که نمایشگر در جهت عمودی معکوس است و دستگاه به طور پیشفرض به حالت عمودی معکوس نمیچرخد، کنترل میکند. | همچنین مواردی را که هنگام چرخش دستگاه (مثلاً 90 درجه) « Activity ایجاد نمیشود، کنترل میکند. زمانی که برنامه نیمی از صفحه را اشغال میکند، این اتفاق در دستگاههای فاکتور کوچک و زمانی که برنامه دو سوم صفحه را اشغال میکند، روی دستگاههای بزرگتر اتفاق میافتد. | |
اختیاری: ویژگی screenOrientation Activity را در فایل AndroidManifest روی fullSensor تنظیم کنید. | این اجازه میدهد تا زمانی که دستگاه در حالت عمودی قرار دارد، رابط کاربری در حالت عمودی قرار گیرد و هر زمان که دستگاه به اندازه ۹۰ درجه چرخانده میشود، امکان بازآفرینی Activity توسط سیستم وجود دارد. | هیچ تاثیری روی دستگاههایی که بهطور پیشفرض برای پرتره معکوس نمیچرخند ندارد. در حالی که صفحه نمایش در جهت عمودی معکوس است، حالت چند پنجره ای پشتیبانی نمی شود. | |
جهت قفل شده | موارد استفاده را فقط یک بار تنظیم کنید، زمانی که Activity برای اولین بار ایجاد می شود، مانند پاسخ به تماس onCreate() Activity . | ||
از OrientationEventListener 's onOrientationChanged() استفاده کنید. در داخل فراخوان، چرخش هدف موارد استفاده به جز پیش نمایش را به روز کنید. | همچنین مواردی را که هنگام چرخش دستگاه (مثلاً 90 درجه) « Activity ایجاد نمیشود، کنترل میکند. زمانی که برنامه نیمی از صفحه را اشغال میکند، این اتفاق در دستگاههای فاکتور کوچک و زمانی که برنامه دو سوم صفحه را اشغال میکند، روی دستگاههای بزرگتر اتفاق میافتد. | ||
تنظیمات جهت یابی تغییرات لغو می شود | موارد استفاده را فقط یک بار تنظیم کنید، زمانی که Activity برای اولین بار ایجاد می شود، مانند پاسخ به تماس onCreate() Activity . | ||
از OrientationEventListener 's onOrientationChanged() استفاده کنید. در داخل callback، چرخش هدف موارد استفاده را به روز کنید. | همچنین مواردی را که هنگام چرخش دستگاه (مثلاً 90 درجه) « Activity ایجاد نمیشود، کنترل میکند. زمانی که برنامه نیمی از صفحه را اشغال میکند، این اتفاق در دستگاههای فاکتور کوچک و زمانی که برنامه دو سوم صفحه را اشغال میکند، روی دستگاههای بزرگتر اتفاق میافتد. | ||
اختیاری: ویژگی screenOrientation Activity را روی fullSensor در فایل AndroidManifest تنظیم کنید. | هنگامی که دستگاه در حالت عمودی قرار دارد، به رابط کاربری اجازه میدهد تا عمودی باشد. | هیچ تاثیری روی دستگاههایی که بهطور پیشفرض برای پرتره معکوس نمیچرخند ندارد. در حالی که صفحه نمایش در جهت عمودی معکوس است، حالت چند پنجره ای پشتیبانی نمی شود. |
فقط جهت گیری های پشتیبانی شده توسط دستگاه را پشتیبانی کنید
فقط جهتگیریهایی را که دستگاه بهطور پیشفرض از آن پشتیبانی میکند، پشتیبانی میکند (که ممکن است شامل عمودی معکوس/منظره معکوس باشد یا نباشد).
سناریو | رهنمودها | حالت چند پنجره ای تقسیم صفحه |
---|---|---|
جهت آنلاک | هر بار که Activity ایجاد میشود، موارد استفاده را تنظیم کنید، مانند پاسخ به تماس onCreate() Activity . | |
از DisplayListener 's onDisplayChanged() استفاده کنید. در داخل کال بک، چرخش هدف موارد استفاده را به روز کنید، مانند زمانی که دستگاه 180 درجه می چرخد. | همچنین مواردی را که هنگام چرخش دستگاه (مثلاً 90 درجه) « Activity ایجاد نمیشود، کنترل میکند. زمانی که برنامه نیمی از صفحه را اشغال میکند، این اتفاق در دستگاههای فاکتور کوچک و زمانی که برنامه دو سوم صفحه را اشغال میکند، روی دستگاههای بزرگتر اتفاق میافتد. | |
جهت قفل شده | موارد استفاده را فقط یک بار تنظیم کنید، زمانی که Activity برای اولین بار ایجاد می شود، مانند پاسخ به تماس onCreate() Activity . | |
از OrientationEventListener 's onOrientationChanged() استفاده کنید. در داخل callback، چرخش هدف موارد استفاده را به روز کنید. | همچنین مواردی را که هنگام چرخش دستگاه (مثلاً 90 درجه) « Activity ایجاد نمیشود، کنترل میکند. زمانی که برنامه نیمی از صفحه را اشغال میکند، این اتفاق در دستگاههای فاکتور کوچک و زمانی که برنامه دو سوم صفحه را اشغال میکند، روی دستگاههای بزرگتر اتفاق میافتد. | |
تنظیمات جهت یابی تغییرات لغو می شود | موارد استفاده را فقط یک بار تنظیم کنید، زمانی که Activity برای اولین بار ایجاد می شود، مانند پاسخ به تماس onCreate() Activity . | |
از DisplayListener 's onDisplayChanged() استفاده کنید. در داخل کال بک، چرخش هدف موارد استفاده را به روز کنید، مانند زمانی که دستگاه 180 درجه می چرخد. | همچنین مواردی را که هنگام چرخش دستگاه (مثلاً 90 درجه) « Activity ایجاد نمیشود، کنترل میکند. زمانی که برنامه نیمی از صفحه را اشغال میکند، این اتفاق در دستگاههای فاکتور کوچک و زمانی که برنامه دو سوم صفحه را اشغال میکند، روی دستگاههای بزرگتر اتفاق میافتد. |
جهت آنلاک
زمانی که جهت نمایشگر آن (مانند عمودی یا افقی) با جهت گیری فیزیکی دستگاه مطابقت داشته باشد، یک Activity
جهت قفل آن باز است، به استثنای حالت عمودی/منظره معکوس، که برخی از دستگاه ها به طور پیش فرض از آن پشتیبانی نمی کنند. برای وادار کردن دستگاه به چرخش به هر چهار جهت، ویژگی screenOrientation
Activity
را روی fullSensor
تنظیم کنید.
در حالت چند پنجرهای، دستگاهی که بهطور پیشفرض از پرتره/منظره معکوس پشتیبانی نمیکند، به حالت عمودی/منظره معکوس نمیچرخد، حتی زمانی که ویژگی screenOrientation
آن روی fullSensor
تنظیم شده باشد.
<!-- The Activity has an unlocked orientation, but might not rotate to reverse portrait/landscape in single-window mode if the device doesn't support it by default. --> <activity android:name=".UnlockedOrientationActivity" /> <!-- The Activity has an unlocked orientation, and will rotate to all four orientations in single-window mode. --> <activity android:name=".UnlockedOrientationActivity" android:screenOrientation="fullSensor" />
جهت قفل شده
هنگامی که یک صفحه نمایش بدون در نظر گرفتن جهت فیزیکی دستگاه در همان جهت نمایش (مانند عمودی یا افقی) باقی بماند، جهت قفل دارد. این کار را می توان با مشخص کردن ویژگی screenOrientation
یک Activity
در داخل اعلان آن در فایل AndroidManifest.xml
انجام داد.
هنگامی که نمایشگر جهت قفل دارد، سیستم با چرخاندن دستگاه، Activity
از بین نمی برد و دوباره ایجاد نمی کند.
<!-- The Activity keeps a portrait orientation even as the device rotates. --> <activity android:name=".LockedOrientationActivity" android:screenOrientation="portrait" />
تغییرات پیکربندی جهت لغو شد
هنگامی که یک Activity
تغییر پیکربندی جهت را لغو می کند، وقتی جهت فیزیکی دستگاه تغییر می کند، سیستم آن را از بین نمی برد و دوباره ایجاد نمی کند. سیستم رابط کاربری را بهروزرسانی میکند تا با جهت فیزیکی دستگاه مطابقت داشته باشد.
<!-- The Activity's UI might not rotate in reverse portrait/landscape if the device doesn't support it by default. --> <activity android:name=".OrientationConfigChangesOverriddenActivity" android:configChanges="orientation|screenSize" /> <!-- The Activity's UI will rotate to all 4 orientations in single-window mode. --> <activity android:name=".OrientationConfigChangesOverriddenActivity" android:configChanges="orientation|screenSize" android:screenOrientation="fullSensor" />
تنظیم موارد استفاده دوربین
در سناریوهایی که در بالا توضیح داده شد، موارد استفاده از دوربین را می توان در اولین ایجاد Activity
تنظیم کرد.
در مورد یک Activity
با جهت آنلاک، این تنظیم هر بار که دستگاه چرخانده می شود انجام می شود، زیرا سیستم باعث از بین رفتن و ایجاد مجدد Activity
on جهت تغییرات می شود. این باعث میشود که موارد استفاده چرخش هدف خود را بهطور پیشفرض هر بار با جهت نمایشگر مطابقت دهند.
در مورد یک Activity
با جهت قفل شده یا فعالیتی که تغییرات پیکربندی جهت را لغو می کند، این تنظیم یک بار انجام می شود، زمانی که Activity
برای اولین بار ایجاد می شود.
class CameraActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val cameraProcessFuture = ProcessCameraProvider.getInstance(this) cameraProcessFuture.addListener(Runnable { val cameraProvider = cameraProcessFuture.get() // By default, the use cases set their target rotation to match the // display’s rotation. val preview = buildPreview() val imageAnalysis = buildImageAnalysis() val imageCapture = buildImageCapture() cameraProvider.bindToLifecycle( this, cameraSelector, preview, imageAnalysis, imageCapture) }, mainExecutor) } }
تنظیم OrientationEventListener
استفاده از OrientationEventListener
به شما این امکان را می دهد که به طور مداوم چرخش هدف کیس های استفاده دوربین را با تغییر جهت دستگاه به روز کنید.
class CameraActivity : AppCompatActivity() { private val orientationEventListener by lazy { object : OrientationEventListener(this) { override fun onOrientationChanged(orientation: Int) { if (orientation == ORIENTATION_UNKNOWN) { return } val rotation = when (orientation) { in 45 until 135 -> Surface.ROTATION_270 in 135 until 225 -> Surface.ROTATION_180 in 225 until 315 -> Surface.ROTATION_90 else -> Surface.ROTATION_0 } imageAnalysis.targetRotation = rotation imageCapture.targetRotation = rotation } } } override fun onStart() { super.onStart() orientationEventListener.enable() } override fun onStop() { super.onStop() orientationEventListener.disable() } }
تنظیم DisplayListener
استفاده از DisplayListener
به شما این امکان را میدهد تا در موقعیتهای خاص، چرخش مورد نظر دوربین را بهروزرسانی کنید، به عنوان مثال زمانی که سیستم پس از چرخش 180 درجهای دستگاه، Activity
از بین نمیبرد و دوباره ایجاد نمیکند.
class CameraActivity : AppCompatActivity() { private val displayListener = object : DisplayManager.DisplayListener { override fun onDisplayChanged(displayId: Int) { if (rootView.display.displayId == displayId) { val rotation = rootView.display.rotation imageAnalysis.targetRotation = rotation imageCapture.targetRotation = rotation } } override fun onDisplayAdded(displayId: Int) { } override fun onDisplayRemoved(displayId: Int) { } } override fun onStart() { super.onStart() val displayManager = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager displayManager.registerDisplayListener(displayListener, null) } override fun onStop() { super.onStop() val displayManager = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager displayManager.unregisterDisplayListener(displayListener) } }