預覽是在相機啟動后實時顯示場景畫面,通常在拍照和錄像前執行。
開發步驟
創建預覽Surface
如果想在屏幕上顯示預覽畫面,一般由XComponent組件為預覽流提供Surface(通過XComponent的getXcomponentSurfaceId方法獲取surfaceid),而XComponent的能力由UI提供,相關介紹可參考XComponent組件。
// xxx.ets
// 創建XComponentController
@Component
struct XComponentPage {// 創建XComponentControllermXComponentController: XComponentController = new XComponentController;surfaceId: string = '';build() {Flex() {// 創建XComponentXComponent({id: '',type: 'surface',libraryname: '',controller: this.mXComponentController}).onLoad(() => {// 設置Surface寬高(以1920*1080為例)this.mXComponentController.setXComponentSurfaceSize({surfaceWidth:1920,surfaceHeight:1080});// 獲取Surface idthis.surfaceId = this.mXComponentController.getXComponentSurfaceId();}).width('1920px').height('1080px')}}
}
創建預覽輸出流
通過getSupportedOutputCapability方法獲取到的CameraOutputCapability類中的previewProfiles屬性表示當前設備支持的預覽配置信息集合,設備能夠支持多種不同的預覽能力。通過createPreviewOutput方法創建預覽輸出流,其中,createPreviewOutput方法中的兩個參數分別是previewProfilesArray數組中的某一項和上一步獲取的surfaceId。
import { camera } from '@kit.CameraKit';
import { BusinessError } from '@kit.BasicServicesKit';function getPreviewOutput(cameraManager: camera.CameraManager, cameraOutputCapability: camera.CameraOutputCapability, surfaceId: string): camera.PreviewOutput | undefined {let previewProfilesArray: Array<camera.Profile> = cameraOutputCapability.previewProfiles;let previewOutput: camera.PreviewOutput | undefined = undefined;try {// 可根據用戶需求選擇不同的previewProfilepreviewOutput = cameraManager.createPreviewOutput(previewProfilesArray[0], surfaceId);} catch (error) {let err = error as BusinessError;console.error("Failed to create the PreviewOutput instance. error code: " + err.code);}return previewOutput;
}
啟動預覽
通過Session.start方法開始輸出預覽流。
async function startPreviewOutput(cameraManager: camera.CameraManager, previewOutput: camera.PreviewOutput): Promise<void> {let cameraArray: Array<camera.CameraDevice> = [];cameraArray = cameraManager.getSupportedCameras();if (cameraArray.length == 0) {console.error('no camera.');return;}// 獲取支持的模式類型。let sceneModes: Array<camera.SceneMode> = cameraManager.getSupportedSceneModes(cameraArray[0]);let isSupportPhotoMode: boolean = sceneModes.indexOf(camera.SceneMode.NORMAL_PHOTO) >= 0;if (!isSupportPhotoMode) {console.error('photo mode not support');return;}let cameraInput: camera.CameraInput | undefined = undefined;cameraInput = cameraManager.createCameraInput(cameraArray[0]);if (cameraInput === undefined) {console.error('cameraInput is undefined');return;}// 打開相機。await cameraInput.open();let session: camera.PhotoSession = cameraManager.createSession(camera.SceneMode.NORMAL_PHOTO) as camera.PhotoSession;session.beginConfig();session.addInput(cameraInput);session.addOutput(previewOutput);await session.commitConfig();await session.start();
}
注:4.0版本需通過調用PreviewOutput.start方法開始輸出預覽流,從4.1版本開始廢棄該方法,改用session.start啟動會話同時輸出預覽流。
停止預覽
通過Session.stop方法停止輸出預覽流。4.0版本需通過調用PreviewOutput.stop方法停止輸出預覽流,從4.1版本開始廢棄該方法,改用session.stop停止會話同時停止輸出預覽流。
function stopCaptureSession(session: camera.Session): void {session.stop((err: BusinessError) => {if (err) {console.error(`Failed to stop the session, error code: ${err.code}.`);return;}console.info('Callback invoked to indicate the session stop success.');});
狀態監聽
在相機應用開發過程中,可以隨時監聽預覽輸出流的狀態,包括預覽流啟動、預覽流結束、預覽流輸出錯誤信息。
通過注冊"frameStart"回調函數獲取監聽預覽啟動結果,previewOutput創建成功時即可監聽,底層第一次開始曝光時觸發該事件并返回,有該事件返回結果則認為預覽流已啟動。
function callback(err: BusinessError): void {if (err !== undefined && err.code !== 0) {console.error(`Callback Error, errorCode: ${err.code}`);return;}console.info('Preview frame started');
}function registerPreviewOutputFrameStart(previewOutput: camera.PreviewOutput): void {previewOutput.on('frameStart', callback);
}
通過注冊的"frameEnd"回調函數獲取監聽預覽結束結果,previewOutput創建成功時即可監聽,預覽完全結束最后一幀時觸發該事件并返回,有該事件返回結果則認為預覽流已結束。
function callback(err: BusinessError): void {if (err !== undefined && err.code !== 0) {console.error(`Callback Error, errorCode: ${err.code}`);return;}console.info('Preview frame ended');
}function registerPreviewOutputFrameEnd(previewOutput: camera.PreviewOutput): void {previewOutput.on('frameEnd', callback);
}
通過注冊"error"回調函數獲取監聽預覽輸出的錯誤事件。
function onPreviewOutputError(previewOutput: camera.PreviewOutput): void {previewOutput.on('error', (previewOutputError: BusinessError) => {console.error(`Preview output error code: ${previewOutputError.code}`);});
}
預覽流配置信息
支持查詢預覽流支持的幀率范圍、預覽旋轉角度等信息;支持配置預覽流幀率范圍、預覽旋轉角度等。
function setFrameRateRange(previewOutput: camera.PreviewOutput): void {let supportedFrameRatesArray: Array<camera.FrameRateRange> = previewOutput.getSupportedFrameRates();previewOutput.setFrameRate(supportedFrameRatesArray[0].min, supportedFrameRatesArray[0].max);let activeFrameRate: camera.FrameRateRange = previewOutput.getActiveFrameRate();
}function setPreviewRotation(previewOutput: camera.PreviewOutput, previewRotation : camera.ImageRotation, isDisplayLocked: boolean): void {previewOutput.setPreviewRotation(previewRotation, isDisplayLocked);
}
API參考
createPreviewOutput
createPreviewOutput(profile: Profile, surfaceId: string): PreviewOutput
創建預覽輸出對象,同步返回結果。
createPreviewOutput(surfaceId: string): PreviewOutput
創建無配置信息的預覽輸出對象,同步返回結果。該接口需配合Session.preconfig方法一起使用。
PreviewOutput
預覽輸出類。繼承CameraOutput。
on(type: 'frameStart', callback: AsyncCallback<void>): void
off(type: 'frameStart', callback?: AsyncCallback<void>): void
on(type: 'frameEnd', callback: AsyncCallback<void>): void
off('frameEnd')
on('error')
off(type: 'error', callback?: ErrorCallback): void// 查詢支持的幀率范圍
getSupportedFrameRates(): Array<FrameRateRange>// 設置預覽流幀率范圍,設置的范圍必須在支持的幀率范圍內。 進行設置前,可通過getSupportedFrameRates查詢支持的幀率范圍
setFrameRate(minFps: number, maxFps: number): void// 獲取已設置的幀率范圍,使用setFrameRate對預覽流設置過幀率后可查詢。
getActiveFrameRate(): FrameRateRange// 獲取當前生效的配置信息
getActiveProfile(): Profile// 獲取預覽旋轉角度
getPreviewRotation(displayRotation: number): ImageRotation// 設置預覽旋轉角度
setPreviewRotation(previewRotation: ImageRotation, isDisplayLocked?: boolean): void