หมายเหตุ: หน้านี้เกี่ยวข้องกับแพ็กเกจ camera2 เราขอแนะนำให้ใช้ cameraX เว้นแต่ว่าแอปของคุณต้องใช้ฟีเจอร์ระดับต่ำที่เฉพาะเจาะจงจาก Camera2 ทั้ง CameraX และ Camera2 รองรับ Android 5.0 (API ระดับ 21) ขึ้นไป
กล้องและการแสดงตัวอย่างจากกล้องใน Android ไม่ได้วางแนวแตกต่างกันเสมอไป อุปกรณ์
กล้องจะมีตำแหน่งคงที่ในอุปกรณ์ ไม่ว่าอุปกรณ์จะ คือโทรศัพท์ แท็บเล็ต หรือคอมพิวเตอร์ เมื่อการวางแนวของอุปกรณ์เปลี่ยน การเปลี่ยนการวางแนวกล้อง
ด้วยเหตุนี้ แอปกล้องถ่ายรูปมักมีความสัมพันธ์ที่ตายตัวระหว่าง การวางแนวของอุปกรณ์และสัดส่วนภาพแสดงตัวอย่างจากกล้อง เมื่อ โทรศัพท์อยู่ในแนวตั้ง ภาพตัวอย่างจากกล้องจะสูงกว่า มากกว่าความกว้าง เมื่อหมุนโทรศัพท์ (และกล้อง) เป็นแนวนอน การแสดงตัวอย่างจากกล้องควรจะกว้างกว่าความสูง
แต่สมมติฐานเหล่านี้ท้าทายโดยรูปแบบของอุปกรณ์ใหม่ๆ เช่น อุปกรณ์แบบพับได้ อุปกรณ์ และโหมดการแสดงผล เช่น หลายหน้าต่าง และ multi-display อุปกรณ์แบบพับได้เปลี่ยนขนาดการแสดงผลและสัดส่วนการแสดงผลโดยไม่เปลี่ยน การวางแนว โหมดหลายหน้าต่างจะจำกัดแอปกล้องให้เป็นส่วนหนึ่งของ ปรับขนาดภาพตัวอย่างจากกล้องโดยไม่คำนึงถึงการวางแนวของอุปกรณ์ โหมดหลายจอแสดงผลทำให้สามารถใช้จอแสดงผลสำรองที่อาจไม่ เป็นแนวเดียวกับจอแสดงผลหลัก
การวางแนวของกล้อง
คำจำกัดความความเข้ากันได้กับ Android ระบุว่าเซ็นเซอร์ภาพของกล้อง "ต้องตั้งทิศทางเพื่อให้ ของกล้องจะอยู่ในแนวเดียวกับด้านยาวของหน้าจอ นั่นคือเมื่อ ถืออุปกรณ์ในแนวนอน กล้องต้องจับภาพ การวางแนวแนวนอน การดำเนินการนี้จะมีผลเสมอไม่ว่าอุปกรณ์จะ การวางแนว กล่าวคือ จะใช้กับอุปกรณ์หลักแนวนอน อุปกรณ์หลักในแนวตั้ง"
การจัดเรียงกล้องให้เข้ากับหน้าจอจะขยายพื้นที่แสดงผลของกล้องให้สูงที่สุด ช่องมองภาพในแอปกล้อง นอกจากนี้ เซ็นเซอร์ภาพมักจะส่งออกข้อมูล สัดส่วนภาพแนวนอนที่ 4:3 เป็นสิ่งที่ใช้กันมากที่สุด
![เซ็นเซอร์ของโทรศัพท์และกล้องทั้งในแนวตั้ง](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_preview_portrait_front_facing.png?authuser=2&hl=th)
การวางแนวตามธรรมชาติของเซ็นเซอร์กล้องจะเป็นแนวนอน ในรูปที่ 1 เซ็นเซอร์ ของกล้องด้านหน้า (กล้องจะชี้ไปในทิศทางเดียวกับ ) จะหมุนไป 270 องศาโดยสัมพันธ์กับโทรศัพท์เพื่อให้เป็นไปตาม คำจำกัดความความเข้ากันได้กับ Android
เพื่อแสดงการหมุนเซ็นเซอร์กับแอป
camera2 API ประกอบด้วย
SENSOR_ORIENTATION
คงที่ สำหรับโทรศัพท์และแท็บเล็ตส่วนใหญ่ อุปกรณ์จะรายงานการวางแนวเซ็นเซอร์
270 องศาสำหรับกล้องหน้า และ 90 องศา (มุมมองจาก
ด้านหลังอุปกรณ์) สำหรับกล้องหลัง ซึ่งจะจัดให้ขอบด้านยาวของ
เซ็นเซอร์ที่มีขอบด้านยาวของอุปกรณ์ โดยทั่วไปแล้ว กล้องแล็ปท็อปจะรายงานว่า
การวางแนวเซ็นเซอร์ 0 หรือ 180 องศา
เนื่องจากเซ็นเซอร์รูปภาพของกล้องจะส่งออกข้อมูล (บัฟเฟอร์รูปภาพ) ใน
การวางแนวตามธรรมชาติของเซ็นเซอร์ (แนวนอน) บัฟเฟอร์ภาพจะต้องหมุน
จำนวนองศาที่ระบุโดย SENSOR_ORIENTATION
สำหรับการแสดงตัวอย่างของกล้อง
จะปรากฏขึ้นตั้งตรงตามการวางแนวธรรมชาติของอุปกรณ์ สำหรับกล้องหน้า
การหมุนจะทวนเข็มนาฬิกา สำหรับกล้องหลังตามเข็มนาฬิกา
เช่น สำหรับกล้องหน้ารูปที่ 1 บัฟเฟอร์รูปภาพ ที่ผลิตโดยเซ็นเซอร์กล้องมีลักษณะดังนี้
![เซ็นเซอร์กล้องหมุนให้อยู่ในแนวนอนโดยมีรูปภาพ
ไปด้านข้าง, ด้านบนซ้าย](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_sensor_portrait_rotated_90.png?authuser=2&hl=th)
ต้องหมุนรูปภาพทวนเข็มนาฬิกา 270 องศาเพื่อให้ภาพตัวอย่าง การวางแนวตรงกับการวางแนวของอุปกรณ์:
![เซ็นเซอร์กล้องในแนวตั้งโดยตั้งรูปภาพตั้งตรง](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_sensor_portrait_without_coordinates.png?authuser=2&hl=th)
กล้องหลังจะถ่ายบัฟเฟอร์รูปภาพที่มีการวางแนวเดียวกัน
เป็นบัฟเฟอร์ด้านบน แต่ SENSOR_ORIENTATION
เป็น 90 องศา ด้วยเหตุนี้ ฟิลด์
บัฟเฟอร์จะถูกหมุนตามเข็มนาฬิกา 90 องศา
การหมุนอุปกรณ์
การหมุนอุปกรณ์คือจำนวนองศาที่หมุนจากอุปกรณ์ตามปกติ การวางแนว ตัวอย่างเช่น โทรศัพท์ในแนวนอนมีอุปกรณ์ การหมุน 90 หรือ 270 องศา ขึ้นอยู่กับทิศทางการหมุน
บัฟเฟอร์ภาพเซ็นเซอร์ของกล้องจะต้องหมุนในจำนวนองศาเท่ากับ การหมุนอุปกรณ์ (นอกเหนือจากองศาการวางแนวของเซ็นเซอร์) ภาพตัวอย่างจากกล้องจะปรากฏขึ้นตั้งตรง
การคำนวณการวางแนว
การวางแนวที่เหมาะสมของการแสดงตัวอย่างจากกล้องจะพิจารณาจากเซ็นเซอร์ การวางแนวและการหมุนอุปกรณ์
การหมุนโดยรวมของบัฟเฟอร์ภาพเซ็นเซอร์สามารถคำนวณได้โดยใช้ สูตรต่อไปนี้
rotation = (sensorOrientationDegrees - deviceOrientationDegrees * sign + 360) % 360
โดย sign
คือ 1
สำหรับกล้องหน้า -1
สำหรับกล้องหลัง
สำหรับกล้องหน้า บัฟเฟอร์ภาพจะหมุนทวนเข็มนาฬิกา (จาก การวางแนวตามธรรมชาติของเซ็นเซอร์) สำหรับกล้องหลัง เซ็นเซอร์ บัฟเฟอร์ภาพถูกหมุนตามเข็มนาฬิกา
นิพจน์ deviceOrientationDegrees * sign + 360
แปลงการหมุนอุปกรณ์
สำหรับกล้องหลัง (เช่น
แปลง 270 องศาทวนเข็มนาฬิกาเป็น 90 องศาตามเข็มนาฬิกา) มอดูโล
การดำเนินการนี้จะปรับขนาดผลลัพธ์ให้น้อยกว่า 360 องศา (ตัวอย่างเช่น การปรับขนาด 540)
องศาการหมุนเป็น 180)
API ที่ต่างกันจะรายงานการหมุนอุปกรณ์แตกต่างกันดังนี้
Display#getRotation()
ให้การหมุนทวนเข็มนาฬิกาของอุปกรณ์ (จากจุดของผู้ใช้ ของมุมมอง) ค่านี้จะสอดคล้องกับสูตรด้านบนตามที่เป็นOrientationEventListener#onOrientationChanged()
จะแสดงการหมุนตามเข็มนาฬิกาของอุปกรณ์ (จากมุมมองของผู้ใช้) ลบค่าเพื่อใช้ในสูตรด้านบน
กล้องหน้า
![แสดงตัวอย่างจากกล้องและเซ็นเซอร์ทั้งในแนวนอนและเซ็นเซอร์
อยู่ทางขวา](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_preview_landscape_counterclockwise_front_facing.png?authuser=2&hl=th)
นี่คือบัฟเฟอร์ภาพที่เซ็นเซอร์ของกล้องสร้างขึ้นในรูปที่ 2
![เซ็นเซอร์กล้องในแนวนอนโดยรูปภาพตั้งขึ้น](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_sensor_landscape.png?authuser=2&hl=th)
บัฟเฟอร์ต้องหมุนทวนเข็มนาฬิกา 270 องศาเพื่อปรับเซ็นเซอร์ การวางแนว (ดูการวางแนวกล้องด้านบน)
![เซ็นเซอร์กล้องหมุนให้อยู่ในแนวแนวตั้งโดยมีรูปภาพตะแคงข้าง
ที่ด้านขวาบน](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_sensor_landscape_rotated_270.png?authuser=2&hl=th)
จากนั้นบัฟเฟอร์จะหมุนทวนเข็มนาฬิกาอีก 90 องศาเพื่อ คำนึงถึงการหมุนอุปกรณ์ ซึ่งทำให้การวางแนวของ ตัวอย่างจากกล้องในรูปที่ 2:
![เซ็นเซอร์กล้องหมุนให้อยู่ในแนวนอนโดยมีรูปภาพ
ตั้งตรง](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_sensor_landscape_without_coordinates.png?authuser=2&hl=th)
กล้องหันไปทางขวาเพื่อวางแนวนอน ดังนี้
![แสดงตัวอย่างจากกล้องและเซ็นเซอร์ทั้งในแนวนอน แต่
เซ็นเซอร์กลับหัว](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_preview_landscape_clockwise_front_facing.png?authuser=2&hl=th)
ต่อไปนี้คือบัฟเฟอร์รูปภาพ
![เซ็นเซอร์กล้องหมุนให้อยู่ในแนวนอนโดยที่รูปภาพกลับด้าน
ลง](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_sensor_landscape_clockwise.png?authuser=2&hl=th)
บัฟเฟอร์ต้องหมุนทวนเข็มนาฬิกา 270 องศาเพื่อปรับเซ็นเซอร์ การวางแนว:
![เซ็นเซอร์กล้องที่จัดประเภทตามการวางแนวตั้งและแสดงรูปภาพตะแคงข้าง
ด้านบนซ้าย](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_sensor_landscape_clockwise_rotated_270.png?authuser=2&hl=th)
จากนั้นบัฟเฟอร์จะหมุนทวนเข็มนาฬิกาอีก 270 องศาเพื่อรองรับ การหมุนอุปกรณ์:
![เซ็นเซอร์กล้องหมุนให้อยู่ในแนวนอนโดยมีรูปภาพ
ตั้งตรง](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_sensor_landscape_without_coordinates.png?authuser=2&hl=th)
กล้องหลัง
สำหรับกล้องหลัง กล้องหลังจะมีการวางแนวเซ็นเซอร์ 90 องศา (เช่น โดยดูจากด้านหลังของอุปกรณ์) เมื่อจัดแนวการแสดงตัวอย่างของกล้อง บัฟเฟอร์ภาพเซ็นเซอร์หมุนตามเข็มนาฬิกาตามปริมาณการหมุนเซ็นเซอร์ (แทนทวนเข็มนาฬิกาเหมือนกล้องหน้า) จากนั้นภาพ บัฟเฟอร์จะถูกหมุนทวนเข็มนาฬิกาตามปริมาณการหมุนของอุปกรณ์
![แสดงตัวอย่างจากกล้องและเซ็นเซอร์ทั้งในแนวนอน แต่
เซ็นเซอร์กลับหัว](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_preview_landscape_clockwise_back_facing.png?authuser=2&hl=th)
นี่คือบัฟเฟอร์รูปภาพจากเซ็นเซอร์กล้องในรูปที่ 4
![เซ็นเซอร์กล้องหมุนให้อยู่ในแนวนอนโดยที่รูปภาพกลับด้าน
ลง](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_sensor_landscape_clockwise.png?authuser=2&hl=th)
บัฟเฟอร์ต้องหมุนตามเข็มนาฬิกา 90 องศาเพื่อปรับเซ็นเซอร์ การวางแนว:
![เซ็นเซอร์กล้องที่จัดประเภทตามการวางแนวตั้งและแสดงรูปภาพตะแคงข้าง
ด้านบนซ้าย](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_sensor_landscape_clockwise_rotated_270.png?authuser=2&hl=th)
จากนั้นบัฟเฟอร์จะหมุนทวนเข็มนาฬิกา 270 องศาเพื่อรองรับอุปกรณ์ การหมุน:
![เซ็นเซอร์กล้องหมุนให้อยู่ในแนวนอนโดยมีรูปภาพ
ตั้งตรง](https://developer.android.com/static/images/training/camera/camera2/camera-preview/camera_sensor_landscape_without_coordinates.png?authuser=2&hl=th)
สัดส่วนภาพ
อัตราส่วนการแสดงผลจะเปลี่ยนเมื่อการวางแนวของอุปกรณ์เปลี่ยน แต่เมื่อเปลี่ยนตามแนว อุปกรณ์แบบพับได้พับและกางออกเมื่อปรับขนาดหน้าต่างในหลายหน้าต่าง สภาพแวดล้อม และเมื่อแอปเปิดขึ้นในจอแสดงผลรอง
บัฟเฟอร์ภาพเซ็นเซอร์ของกล้องถ่ายรูปจะต้องอยู่ในแนวและปรับขนาดให้ตรงกับ การวางแนวและสัดส่วนภาพขององค์ประกอบ UI ของช่องมองภาพเป็น UI เปลี่ยนการวางแนวแบบไดนามิก ไม่ว่าอุปกรณ์จะเปลี่ยนหรือไม่ การวางแนว
ในรูปแบบของอุปกรณ์ใหม่ๆ หรือในสภาพแวดล้อมหลายหน้าต่างหรือหลายจอแสดงผล หาก แอปจะถือว่าตัวอย่างจากกล้องมีการวางแนวเดียวกันกับอุปกรณ์ (แนวตั้งหรือแนวนอน) ตัวอย่างของคุณอาจจัดวางไม่ถูกต้อง มีการปรับขนาด ไม่ถูกต้อง หรือทั้งคู่
![อุปกรณ์แบบพับได้กางออกและเปิดการแสดงตัวอย่างด้วยกล้องแนวตั้ง
ไปด้านข้าง](https://developer.android.com/static/images/training/camera/camera2/camera-preview/foldable_with_rotation_problem.png?authuser=2&hl=th)
ในรูปที่ 5 แอปพลิเคชันเข้าใจผิดว่าอุปกรณ์หมุน 90 องศา องศาทวนเข็มนาฬิกา และแอปจะหมุนตัวอย่างในจำนวนที่เท่ากัน
![อุปกรณ์แบบพับได้กางออกพร้อมการแสดงตัวอย่างจากกล้องตั้งตรงแต่บีบ
เพราะการปรับขนาดไม่ถูกต้อง](https://developer.android.com/static/images/training/camera/camera2/camera-preview/foldable_with_scaling_problem.png?authuser=2&hl=th)
ในรูปที่ 6 แอปไม่ได้ปรับสัดส่วนภาพของบัฟเฟอร์รูปภาพเป็น โปรดเปิดใช้การปรับขนาดอย่างเหมาะสมเพื่อให้พอดีกับขนาดใหม่ของ UI การแสดงตัวอย่างจากกล้อง
โดยปกติแล้ว แอปกล้องที่ปรับทิศทางจะมีปัญหากับอุปกรณ์แบบพับได้และ อุปกรณ์ที่มีหน้าจอขนาดใหญ่อื่นๆ เช่น แล็ปท็อป
![ภาพตัวอย่างจากกล้องบนแล็ปท็อปตั้งตรง แต่ UI ของแอปตะแคงข้าง](https://developer.android.com/static/images/training/camera/camera2/camera-preview/laptop_camera_preview_fixed-orientation_app.png?authuser=2&hl=th)
ในรูปที่ 7 UI ของแอปกล้องตะแคงข้างเนื่องจากการวางแนวของแอป จำกัดเฉพาะแนวตั้งเท่านั้น ภาพในช่องมองภาพอยู่ในแนวที่ถูกต้อง ที่สัมพันธ์กับเซ็นเซอร์ของกล้อง
โหมดภาพแนวตั้ง
แอปกล้องที่ไม่รองรับโหมดหลายหน้าต่าง
(resizeableActivity="false"
)
และจำกัดการวางแนว
(screenOrientation="portrait"
)
หรือ screenOrientation="landscape"
)
สามารถวางในโหมดภาพบุคคลบนหน้าจอขนาดใหญ่ เพื่อจัดแนวอย่างเหมาะสม
การแสดงตัวอย่างจากกล้อง
ฝังแอปโหมดแนวตั้งแบบแนวตั้ง (Insets) แบบแนวตั้งเท่านั้นในแนวตั้ง การวางแนวแม้ว่าสัดส่วนการแสดงผลจะเป็นแนวนอนก็ตาม แอปแนวนอนเท่านั้นจะมีแถบดำด้านบน-ล่างของภาพในแนวนอน สัดส่วนการแสดงผลคือแนวตั้ง หมุนรูปภาพจากกล้องเพื่อจัดแนว กับ UI ของแอป มีการครอบตัดเพื่อให้ตรงกับสัดส่วนภาพของตัวอย่างจากกล้อง และ จากนั้นก็ปรับขนาดให้เต็มตัวอย่าง
โหมดภาพบุคคลภายในจะทริกเกอร์เมื่อสัดส่วนภาพของรูปภาพจากกล้อง เซ็นเซอร์และอัตราส่วนกิจกรรมหลักของแอปพลิเคชันไม่ตรงกัน
![การแสดงตัวอย่างจากกล้องและ UI ของแอปในแนวตั้งอย่างเหมาะสมบนแล็ปท็อป
ปรับขนาดและครอบตัดรูปภาพตัวอย่างแบบกว้างให้พอดีกับแนวตั้ง
การวางแนว](https://developer.android.com/static/images/training/camera/camera2/camera-preview/laptop_inset_portrait_mode.png?authuser=2&hl=th)
ในรูปที่ 8 แอปกล้องแนวตั้งเท่านั้นได้หมุนเพื่อแสดง UI ตั้งตรงบนจอแสดงผลของแล็ปท็อป แอปมีแถบดำด้านบน-ล่างของภาพเนื่องจากความแตกต่าง ในอัตราส่วนระหว่างแอปแนวตั้งและแนวนอน กล้อง มีการหมุนภาพตัวอย่างเพื่อชดเชยการหมุน UI ของแอป (เนื่องจาก โหมดแนวตั้งภายใน) และรูปภาพถูกครอบตัดและปรับขนาดให้พอดีกับ การวางแนวตั้งขึ้น ซึ่งจะลดขอบเขตการมองเห็น
หมุน ครอบตัด ปรับขนาด
ระบบเรียกใช้โหมดภาพบุคคลแบบซ้อนสำหรับแอปกล้องสำหรับภาพบุคคลในจอแสดงผล ที่มีสัดส่วนภาพแนวนอน ดังนี้
![ภาพตัวอย่างจากกล้องบนแล็ปท็อปตั้งตรง แต่ UI ของแอปตะแคงข้าง](https://developer.android.com/static/images/training/camera/camera2/camera-preview/laptop_inset_portrait_mode_fixed-orientation_app.png?authuser=2&hl=th)
แอปมีแถบดำด้านบน-ล่างของภาพในแนวตั้ง:
![แอปหมุนไปเป็นแนวตั้งและมีแถบดำด้านบน-ล่างของภาพ ภาพคือ
ตะแคงข้าง ไปด้านบนทางขวา](https://developer.android.com/static/images/training/camera/camera2/camera-preview/laptop_inset_portrait_mode_rotate_ui.png?authuser=2&hl=th)
ภาพจากกล้องจะหมุน 90 องศาเพื่อปรับทิศทางของ แอป:
![ภาพเซ็นเซอร์จะหมุน 90 องศาเพื่อทำให้ตั้งตรง](https://developer.android.com/static/images/training/camera/camera2/camera-preview/laptop_inset_portrait_mode_rotate_sensor_image.png?authuser=2&hl=th)
รูปภาพจะถูกครอบตัดตามสัดส่วนภาพของตัวอย่างจากกล้อง จากนั้นจึงปรับขนาดเป็น เติมเต็มตัวอย่าง (ขอบเขตการมองเห็นลดลง):
![รูปภาพจากกล้องที่ครอบตัดแล้วปรับขนาดให้เต็มตัวอย่างจากกล้อง](https://developer.android.com/static/images/training/camera/camera2/camera-preview/laptop_inset_portrait_mode_crop_and_scale.png?authuser=2&hl=th)
การวางแนวของเซ็นเซอร์กล้องอาจเป็นแนวตั้งในอุปกรณ์แบบพับได้ ในขณะที่สัดส่วนการแสดงผลเป็นแนวนอน
![การแสดงตัวอย่างในกล้องและ UI ของแอปหันไปด้านข้างของจอแสดงผลแบบกว้างที่กางออก](https://developer.android.com/static/images/training/camera/camera2/camera-preview/unfolded_phone_camera_preview_fixed-orientation_app.png?authuser=2&hl=th)
เนื่องจากการแสดงตัวอย่างจากกล้องจะมีการหมุนเพื่อปรับตามการวางแนวเซ็นเซอร์ ภาพอยู่ในช่องมองภาพอย่างถูกต้อง แต่แอปสำหรับภาพแนวตั้งเท่านั้น ที่อยู่ข้างๆ
โหมดภาพบุคคลจะต้องใส่แถบดำด้านบน-ล่างของภาพแอปในแนวตั้งเท่านั้น เพื่อปรับแนวการแสดงตัวอย่างของแอปและกล้องให้ถูกต้อง ดังนี้
![แอปที่มีแถบดำด้านบน-ล่างของภาพในการวางแนวแบบแนวตั้ง พร้อมภาพตัวอย่างจากกล้อง
ตั้งตรงบนอุปกรณ์แบบพับได้](https://developer.android.com/static/images/training/camera/camera2/camera-preview/unfolded_phone_inset_portrait_mode.png?authuser=2&hl=th)
API
สำหรับแอป Android 12 (API ระดับ 31) ยังควบคุมการตั้งค่าแนวตั้งอย่างชัดแจ้งได้ด้วย
โดยวิธีการ
SCALER_ROTATE_AND_CROP
ของพร็อพเพอร์ตี้ CaptureRequest
ค่าเริ่มต้นคือ
SCALER_ROTATE_AND_CROP_AUTO
ซึ่งทำให้ระบบสามารถเรียกใช้โหมดแนวตั้งภายใน
SCALER_ROTATE_AND_CROP_90
คือลักษณะการทำงานของโหมดภาพบุคคลตามที่อธิบายข้างต้น
อุปกรณ์บางรุ่นไม่รองรับค่า SCALER_ROTATE_AND_CROP
ทุกค่า หากต้องการดูรายการ
ค่าที่รองรับ การอ้างอิง
CameraCharacteristics#SCALER_AVAILABLE_ROTATE_AND_CROP_MODES
กล้องถ่ายรูป X
ไลบรารี Jetpack CameraX ทำให้การสร้างช่องมองภาพของกล้อง ที่รองรับการวางแนวเซ็นเซอร์และ การหมุนอุปกรณ์ให้เป็นงานง่ายๆ
องค์ประกอบเลย์เอาต์ PreviewView
สร้างการแสดงตัวอย่างจากกล้อง ปรับ
การวางแนวเซ็นเซอร์โดยอัตโนมัติ
การหมุนอุปกรณ์และการปรับขนาด PreviewView
จะรักษาอัตราส่วนของ
รูปภาพจากกล้องโดยใช้
FILL_CENTER
ประเภทมาตราส่วน ซึ่งกำหนดให้รูปภาพอยู่กึ่งกลาง แต่อาจครอบตัดให้พอดีกับขนาด
ของPreviewView
หากต้องการให้มีแถบดำด้านบน-ล่างของภาพในกล้อง ให้กำหนดประเภทมาตราส่วนเป็น
FIT_CENTER
หากต้องการเรียนรู้พื้นฐานในการสร้างตัวอย่างจากกล้องด้วย PreviewView
โปรดดู
ใช้การแสดงตัวอย่าง
ดูตัวอย่างการติดตั้งใช้งานที่สมบูรณ์ได้ที่
CameraXBasic
ใน GitHub
ช่องมองภาพของกล้อง
ซึ่งคล้ายกับกรณีการใช้งานของตัวอย่าง กล้องมองภาพ ไลบรารีมีชุดเครื่องมือที่ช่วยให้การสร้างการแสดงตัวอย่างจากกล้องง่ายขึ้น วิธีนี้ไม่ได้ขึ้นอยู่กับ CameraX Core คุณจึงผสานรวมเข้ากับ ฐานของโค้ด Camera2 ที่มีอยู่
แทนที่จะใช้
Surface
โดยตรง คุณสามารถใช้
CameraViewfinder
วิดเจ็ตเพื่อแสดงฟีดกล้องสำหรับ Camera2
CameraViewfinder
ใช้ TextureView
หรือ SurfaceView
เป็นการภายใน
เพื่อแสดงฟีดกล้อง และใช้การเปลี่ยนรูปแบบที่จําเป็นกับ
แสดงช่องมองภาพได้อย่างถูกต้อง
ซึ่งรวมถึงการแก้ไขสัดส่วนภาพ ขนาด และการหมุน
ในการขอพื้นผิวจากออบเจ็กต์ CameraViewfinder
คุณต้อง
สร้าง ViewfinderSurfaceRequest
คำขอนี้มีข้อกำหนดสำหรับความละเอียดของพื้นผิวและอุปกรณ์กล้อง
ข้อมูลจาก CameraCharacteristics
กำลังโทรหา requestSurfaceAsync()
ส่งคำขอไปยังผู้ให้บริการแพลตฟอร์ม ไม่ว่าจะเป็น TextureView
หรือ
SurfaceView
และรับ ListenableFuture
เป็น Surface
กำลังโทรหา markSurfaceSafeToRelease()
แจ้งผู้ให้บริการพื้นผิวว่าพื้นผิวดังกล่าวไม่จำเป็นต้องใช้และมีความเกี่ยวข้องกัน
จะสามารถปล่อยทรัพยากรได้
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
จะหมุนบัฟเฟอร์ภาพเซ็นเซอร์ของกล้องโดยอัตโนมัติให้ตรงกัน
การวางแนวจอแสดงผล ซึ่งพิจารณาทั้งการวางแนวเซ็นเซอร์และอุปกรณ์
การหมุน แต่บัฟเฟอร์รูปภาพจะมีการปรับขนาดให้พอดีกับ SurfaceView
โดยไม่ต้องพิจารณาสัดส่วนการแสดงผล
คุณต้องตรวจสอบว่าสัดส่วนภาพของบัฟเฟอร์รูปภาพตรงกับ
ของ SurfaceView
ซึ่งทำได้โดยการปรับขนาดเนื้อหา
ของ SurfaceView
ในคอมโพเนนต์
onMeasure()
วิธีการ:
(ซอร์สโค้ด computeRelativeRotation()
อยู่ใน
การหมุนเวียนแบบสัมพัทธ์ด้านล่าง)
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); }
ดูรายละเอียดเพิ่มเติมเกี่ยวกับการใช้ SurfaceView
เป็นตัวอย่างจากกล้องได้ที่
การวางแนวกล้อง
มุมมองพื้นผิว
TextureView
มีประสิทธิภาพน้อยกว่า
SurfaceView
และงานอื่นๆ เพิ่มเติม แต่ TextureView
ให้ขีดจำกัดสูงสุด
การควบคุมการแสดงตัวอย่างจากกล้อง
TextureView
จะหมุนบัฟเฟอร์รูปภาพเซ็นเซอร์ตามการวางแนวเซ็นเซอร์
ไม่ได้จัดการการหมุนอุปกรณ์หรือการปรับขนาดตัวอย่าง
การปรับขนาดและการหมุนสามารถเข้ารหัสใน
เมทริกซ์ ดูวิธีการ
ปรับขนาดและหมุน TextureView
อย่างถูกต้อง โปรดดู
รองรับพื้นผิวที่ปรับขนาดได้ในแอปกล้อง
การหมุนเวียนแบบสัมพัทธ์
การหมุนสัมพัทธ์ของเซ็นเซอร์กล้องคือปริมาณการหมุนที่จำเป็นต้องใช้เพื่อ จัดแนวเอาต์พุตเซ็นเซอร์ของกล้องให้ตรงกับการวางแนวของอุปกรณ์
คอมโพเนนต์ เช่น SurfaceView
และ TextureView
ใช้การหมุนเวียนแบบสัมพัทธ์
เพื่อกำหนดตัวคูณมาตราส่วน x และ y สำหรับรูปภาพตัวอย่าง นอกจากนี้ยังใช้เพื่อ
ระบุการหมุนของบัฟเฟอร์ภาพเซ็นเซอร์
CameraCharacteristics
และ
Surface
ชั้นเรียนเปิดใช้การคํานวณ
การหมุนสัมพัทธ์ของเซ็นเซอร์กล้อง:
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; }
เมตริกกรอบเวลา
ไม่ควรใช้ขนาดหน้าจอในการกำหนดขนาดของกล้อง ช่องมองภาพ แอปกล้องอาจกำลังทำงานในส่วนใดของหน้าจอหนึ่ง ในโหมดหลายหน้าต่างบนอุปกรณ์เคลื่อนที่หรือโหมดอิสระใน ChromeOS
WindowManager#getCurrentWindowMetrics()
(เพิ่มใน API ระดับ 30) แสดงผลขนาดของหน้าต่างแอปพลิเคชันแทน
ขนาดหน้าจอ เมธอดไลบรารี Jetpack WindowManager
WindowMetricsCalculator#computeCurrentWindowMetrics()
และ
WindowInfoTracker#currentWindowMetrics()
ให้การสนับสนุนที่คล้ายกันโดยมีความเข้ากันได้แบบย้อนหลังกับ API ระดับ 14
การหมุน 180 องศา
การหมุน 180 องศาของอุปกรณ์ (เช่น จากการวางแนวตามธรรมชาติเป็น
การวางแนวแบบธรรมชาติกลับหัว) จะไม่ทริกเกอร์
onConfigurationChanged()
Callback ด้วยเหตุนี้ การแสดงตัวอย่างจากกล้องจึงอาจกลับหัวกลับหาง
หากต้องการตรวจหาการหมุน 180 องศา ให้ใช้
DisplayListener
และตรวจสอบการหมุนอุปกรณ์
โดยให้มีการเรียก
Display#getRotation()
ในช่วง
onDisplayChanged()
Callback
แหล่งข้อมูลสุดพิเศษ
เวอร์ชันก่อนหน้า Android 10 มีเฉพาะกิจกรรมที่มองเห็นได้ง่ายสุดในหน้าต่างหลายหน้าต่าง
สภาพแวดล้อมเคยอยู่ในสถานะ RESUMED
ซึ่งทำให้ผู้ใช้สับสนเนื่องจาก
ระบบไม่ได้ระบุว่ากิจกรรมใดกลับมาทำงานต่อ
Android 10 (API ระดับ 29) กลับมาให้บริการอีกครั้งเมื่อกิจกรรมที่มองเห็นได้ทั้งหมด
อยู่ในสถานะ RESUMED
กิจกรรมที่มองเห็นได้จะยังคงเข้าสู่ PAUSED
ได้
ตัวอย่างเช่น หากกิจกรรมแบบโปร่งใสซ้อนทับกิจกรรม หรือ
โฟกัสที่กิจกรรมไม่ได้ เช่น ในโหมดการแสดงภาพซ้อนภาพ (โปรดดู
การรองรับการแสดงภาพซ้อนภาพ)
แอปพลิเคชันที่ใช้กล้อง ไมโครโฟน หรือโปรแกรม
ทรัพยากร Singleton ใน API ระดับ 29 ขึ้นไปต้องรองรับการทำงานต่อหลายรายการ สำหรับ
เช่น หากกิจกรรมที่ทำต่อ 3 กิจกรรมต้องการใช้กล้อง จะมีเพียงกิจกรรมเดียว
เพื่อเข้าถึงแหล่งข้อมูลสุดพิเศษนี้ แต่ละกิจกรรมต้องใช้
onDisconnected()
Callback เพื่อรับทราบสิทธิ์ล่วงหน้าในการเข้าถึงกล้องตามลำดับความสำคัญที่สูงกว่า
กิจกรรม
สำหรับข้อมูลเพิ่มเติม โปรดดู เล่นต่อหลายรายการ
แหล่งข้อมูลเพิ่มเติม
- สำหรับตัวอย่างของ Camera2 โปรดดูที่แอป Camera2Basic ใน GitHub
- ดูข้อมูลเกี่ยวกับกรณีการใช้งานตัวอย่างจากกล้อง CameraX ได้ที่ CameraX ใช้การแสดงตัวอย่าง
- สำหรับตัวอย่างการใช้งานตัวอย่างจากกล้อง CameraX ให้ดูที่ กล้องถ่ายรูป X พื้นฐาน ใน GitHub
- ดูข้อมูลเกี่ยวกับการแสดงตัวอย่างจากกล้องใน ChromeOS ได้ที่ การวางแนวกล้อง
- ดูข้อมูลเกี่ยวกับการพัฒนาสำหรับอุปกรณ์แบบพับได้ได้ที่ ดูข้อมูลเกี่ยวกับอุปกรณ์พับได้