הטמעת תצוגה מקדימה

כשמוסיפים תצוגה מקדימה לאפליקציה, משתמשים ב-PreviewView, שהוא View שאפשר לחתוך, לשנות את הגודל שלו ולסובב אותו כדי להציג אותו בצורה נכונה.

התצוגה המקדימה של התמונה מוצגת ב-PreviewView כשהמצלמה מופעלת.

שימוש ב-PreviewView

כדי להטמיע תצוגה מקדימה ל-CameraX באמצעות PreviewView, צריך לבצע את השלבים הבאים, שמפורטים בקטעים הבאים:

  1. אפשר להגדיר CameraXConfig.Provider.
  2. מוסיפים PreviewView לפריסה.
  3. מבקשים ProcessCameraProvider.
  4. כשיוצרים View, צריך לבדוק את ProcessCameraProvider.
  5. בוחרים מצלמה ומקשרים את מחזור החיים ותרחישי השימוש.

יש כמה מגבלות לשימוש ב-PreviewView. כשמשתמשים ב-PreviewView, אי אפשר לבצע את הפעולות הבאות:

  • יוצרים SurfaceTexture כדי להגדיר ב-TextureView וב-Preview.SurfaceProvider.
  • מאחזרים את SurfaceTexture מ-TextureView ומגדירים אותו ב-Preview.SurfaceProvider.
  • משיגים את Surface מ-SurfaceView ומגדירים אותו ב-Preview.SurfaceProvider.

אם אחד מהמקרים האלה קורה, ה-Preview מפסיק להעביר פריימים בסטרימינג אל ה-PreviewView.

הוספת PreviewView לפריסה

בדוגמה הבאה מוצג PreviewView בפריסה:

<FrameLayout
    android:id="@+id/container">
        <androidx.camera.view.PreviewView
            android:id="@+id/previewView" />
</FrameLayout>

בקשה ל-CameraProvider

הקוד הבא מראה איך לבקש CameraProvider:

// import androidx.camera.lifecycle.ProcessCameraProvider
// import com.google.common.util.concurrent.ListenableFuture

class MainActivity : ComponentActivity() {
    private lateinit var cameraProviderFuture: ListenableFuture<ProcessCameraProvider>
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        cameraProviderFuture = ProcessCameraProvider.getInstance(this)
    }
}

בדיקה אם CameraProvider זמין

אחרי ששולחים בקשה ל-CameraProvider, צריך לוודא שההפעלה שלו הצליחה כשהתצוגה נוצרה. הקוד הבא מראה איך לעשות את זה:

cameraProviderFuture.addListener(
    Runnable {
        val cameraProvider = cameraProviderFuture.get()
        bindPreview(cameraProvider)
    },
    ContextCompat.getMainExecutor(this)
)

דוגמה לשימוש בפונקציה bindPreview מופיעה בקוד שבקטע הבא.

בוחרים מצלמה ומקשרים את מחזור החיים ותרחישי השימוש

אחרי שיוצרים ומאשרים את ה-CameraProvider, מבצעים את הפעולות הבאות:

  1. יוצרים Preview.
  2. בוחרים את אפשרות המצלמה LensFacing הרצויה.
  3. מקשרים את המצלמה שנבחרה ואת כל תרחישי השימוש למחזור החיים.
  4. מחברים את Preview אל PreviewView.

הקוד הבא מציג דוגמה:

fun bindPreview(cameraProvider: ProcessCameraProvider) {
    var preview: Preview = Preview.Builder()
        .build()

    var cameraSelector: CameraSelector = CameraSelector.Builder()
        .requireLensFacing(CameraSelector.LENS_FACING_BACK)
        .build()

    preview.setSurfaceProvider(previewView.getSurfaceProvider())

    var camera = cameraProvider.bindToLifecycle(this as LifecycleOwner, cameraSelector, preview)
}

שימו לב שהפונקציה bindToLifecycle() מחזירה אובייקט Camera. למידע נוסף על שליטה בפלט של המצלמה, כמו זום וחשיפה, ראו פלט מצלמה.

סיימתם להטמיע את התצוגה המקדימה של המצלמה. מפתחים את האפליקציה ומוודאים שהתצוגה המקדימה מופיעה באפליקציה ופועלת כמו שרוצים.

אמצעי בקרה נוספים ל-PreviewView

‫CameraX PreviewView מספק כמה ממשקי API נוספים להגדרת מאפיינים כמו:

מצב הטמעה

‫PreviewView יכול להשתמש באחד מהמצבים הבאים כדי לעבד סטרימינג של תצוגה מקדימה ב-View היעד:

  • PERFORMANCE הוא מצב ברירת המחדל. ‫PreviewView משתמש ב-SurfaceView כדי להציג את שידור הווידאו, אבל במקרים מסוימים הוא חוזר ל-TextureView. ל-SurfaceView יש משטח ציור ייעודי, שיש סיכוי גבוה יותר שיוטמע עם שכבת-על של חומרה על ידי הקומפוזיטור הפנימי של החומרה, במיוחד כשאין רכיבים אחרים בממשק המשתמש (כמו לחצנים) מעל הסרטון בתצוגה המקדימה. כשמבצעים עיבוד באמצעות שכבת-על של חומרה, הפריימים של הסרטון לא עוברים דרך ה-GPU, וכך אפשר להפחית את צריכת החשמל ואת זמן האחזור של הפלטפורמה.

  • COMPATIBLE. במצב הזה, PreviewView משתמש ב-TextureView שבניגוד ל-SurfaceView, אין לו משטח ציור ייעודי. כתוצאה מכך, הסרטון מעובד עם מיזוג כדי שיהיה אפשר להציג אותו. בשלב הנוסף הזה, האפליקציה יכולה לבצע עיבוד נוסף, כמו שינוי קנה מידה וסיבוב של סרטונים ללא הגבלה.

משתמשים ב-PreviewView.setImplementationMode() כדי לבחור את מצב ההטמעה שמתאים לאפליקציה. אם מצב ברירת המחדל PERFORMANCE לא מתאים לאפליקציה, בדוגמת הקוד הבאה מוסבר איך להגדיר את המצב COMPATIBLE:

// viewFinder is a PreviewView instance.
viewFinder.implementationMode = PreviewView.ImplementationMode.COMPATIBLE

סוג הסולם

כשרזולוציית התצוגה המקדימה של הסרטון שונה מהמידות של היעד PreviewView, צריך להתאים את קטע הווידאו לתצוגה על ידי חיתוך או הוספת פסים שחורים (שמירה על יחס הגובה-רוחב המקורי). לצורך כך, PreviewView מספק את ScaleTypes הבאים:

  • FIT_CENTER, FIT_START, ו-FIT_END ל-letterboxing. תוכן הסרטון המלא מותאם (מוגדל או מוקטן) לגודל המקסימלי שאפשר להציג ב-PreviewView היעד. עם זאת, למרות שכל הפריים של הסרטון גלוי, יכול להיות שחלק מהמסך יהיה ריק. בהתאם לסוג קנה המידה שתבחרו, הפריים ייושר למרכז, להתחלה או לסוף של התצוגה.

  • FILL_CENTER, FILL_START, FILL_END לחיתוך. אם הסרטון לא תואם ליחס הגובה-רוחב של PreviewView, רק חלק מהתוכן יהיה גלוי, אבל הסרטון ימלא את כל ה-PreviewView.

סוג קנה המידה שמוגדר כברירת מחדל ב-CameraX הוא FILL_CENTER. כדי להגדיר את סוג קנה המידה שהכי מתאים לאפליקציה, משתמשים ב-PreviewView.setScaleType(). דוגמת הקוד הבאה מגדירה את סוג הסולם FIT_CENTER:

// viewFinder is a PreviewView instance.
viewFinder.scaleType = PreviewView.ScaleType.FIT_CENTER

התהליך של הצגת סרטון כולל את השלבים הבאים:

  1. כדי לשנות את קנה המידה של הסרטון:
    • בסוגי קנה מידה של FIT_*, משנים את קנה המידה של הסרטון באמצעות min(dst.width/src.width, dst.height/src.height).
    • בסוגי קנה מידה של FILL_*, משנים את קנה המידה של הסרטון באמצעות max(dst.width/src.width, dst.height/src.height).
  2. מיישרים את הסרטון המוקטן עם היעד PreviewView:
    • ב-FIT_CENTER/FILL_CENTER, צריך ליישר למרכז את הסרטון המותאם ואת היעד PreviewView.
    • ב-FIT_START/FILL_START, צריך ליישר את הסרטון המותאם ואת היעד PreviewView ביחס לפינה השמאלית העליונה של כל אחד מהם.
    • ב-FIT_END/FILL_END, מיישרים את הסרטון המותאם ואת היעד PreviewView ביחס לפינה הימנית התחתונה של כל אחד מהם.

לדוגמה, הנה סרטון מקור ברזולוציה של 640x480 וסרטון יעד ברזולוציה של 1920x1080 PreviewView:

תמונה שרואים בה סרטון ברזולוציה של 640x480 בהשוואה לתצוגה מקדימה ברזולוציה של 1920x1080

בתמונה הבאה מוצג תהליך ההתאמה לעומס (scaling) של FIT_START / FIT_CENTER / FIT_END:

תמונה שמראה את תהליך שינוי הגודל של FIT_START,‏ FIT_CENTER ו-FIT_END

ככה זה עובד:

  1. משנים את קנה המידה של הפריים (תוך שמירה על יחס הגובה-רוחב המקורי) באמצעות min(1920/640, 1080/480) = 2.25 כדי לקבל פריים ביניים של 1440x1080.
  2. מיישרים את הפריים של הסרטון ברזולוציה 1440x1080 עם PreviewView ברזולוציה 1920x1080.
    • ב-FIT_CENTER, ממקמים את הפריים של הסרטון במרכז החלון של PreviewView. העמודות של 240 הפיקסלים בהתחלה ובסוף של PreviewView ריקות.
    • ב-FIT_START, מיישרים את הפריים של הסרטון עם ההתחלה (הפינה השמאלית העליונה) של החלון של PreviewView. ‫480 הפיקסלים האחרונים של העמודות ב-PreviewView ריקים.
    • ב-FIT_END, מיישרים את הפריים של הסרטון עם הסוף (הפינה הימנית התחתונה) של החלון של PreviewView. עמודות הפיקסלים הראשונות (480) של PreviewView ריקות.

בתמונה הבאה מוצג תהליך ההתאמה לעומס (scaling) של FILL_START / FILL_CENTER / FILL_END:

תמונה שמראה את תהליך שינוי קנה המידה של FILL_START,‏ FILL_CENTER ו-FILL_END

ככה זה עובד:

  1. משנים את קנה המידה של הפריים באמצעות max(1920/640, 1080/480) = 3 כדי לקבל פריים ביניים בגודל 1920x1440 (גדול יותר מהגודל של PreviewView).
  2. חותכים את הפריים של הסרטון בגודל 1920x1440 כך שיתאים לחלון PreviewView בגודל 1920x1080.
    • ב-FILL_CENTER, חותכים 1920x1080 ממרכז הסרטון ששונה ל-1920x1440. 180 השורות העליונות והתחתונות של הסרטון לא מוצגות.
    • ב-FILL_START, חותכים 1920x1080 מההתחלה של הסרטון ששונה ל-1920x1440. 360 השורות התחתונות של הסרטון לא גלויות.
    • ב-FILL_END, חותכים 1920x1080 מסוף הסרטון ששונה ל-1920x1440. ‫360 השורות העליונות של הסרטון לא גלויות.

מקורות מידע נוספים

איפה אפשר למצוא מידע נוסף על CameraX?

Codelab

  • תחילת העבודה עם CameraX
  • דוגמת קוד

  • אפליקציות לדוגמה של CameraX