2024-01-05 11:11:15 +08:00
|
|
|
|
import camera from '@ohos.multimedia.camera';
|
2024-06-04 11:19:22 +08:00
|
|
|
|
import image from '@ohos.multimedia.image';
|
|
|
|
|
|
import TopLogo from '../compontents/topLogo';
|
2024-01-05 11:11:15 +08:00
|
|
|
|
|
|
|
|
|
|
import buffer from '@ohos.buffer';
|
|
|
|
|
|
|
|
|
|
|
|
@Component
|
2024-06-04 11:19:22 +08:00
|
|
|
|
export default struct FaceCompare {
|
|
|
|
|
|
@State imageBase64: string = 'data:image/jpeg;base64,'
|
2024-01-05 11:11:15 +08:00
|
|
|
|
private cameraObj: any = null;
|
|
|
|
|
|
private cameraManager: any = null;
|
2024-06-04 11:19:22 +08:00
|
|
|
|
private surfaceId: string = '';
|
2024-01-05 11:11:15 +08:00
|
|
|
|
private xcomponentController: XComponentController = new XComponentController();
|
|
|
|
|
|
// 相机会话
|
|
|
|
|
|
private captureSession: any = null;
|
|
|
|
|
|
// 相机输入流
|
|
|
|
|
|
private cameraInput: any = null;
|
|
|
|
|
|
// 预览输出流
|
|
|
|
|
|
private previewOutput: any = null;
|
|
|
|
|
|
// 拍照输出流
|
|
|
|
|
|
private photoOutput: any = null;
|
|
|
|
|
|
// 照片接收对象
|
|
|
|
|
|
private imageRecever: any = null;
|
|
|
|
|
|
private timeSetTimeout: number = 0; //定时器执行次数
|
|
|
|
|
|
private timer: any = 0; //定时器
|
|
|
|
|
|
|
2024-06-04 11:19:22 +08:00
|
|
|
|
constructor() {
|
|
|
|
|
|
super()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
build() {
|
2024-01-05 11:11:15 +08:00
|
|
|
|
Column() {
|
2024-06-04 11:19:22 +08:00
|
|
|
|
TopLogo({
|
|
|
|
|
|
outFlag: false
|
|
|
|
|
|
})
|
2024-01-05 11:11:15 +08:00
|
|
|
|
Row() {
|
|
|
|
|
|
XComponent({
|
|
|
|
|
|
id: 'xcomponent',
|
|
|
|
|
|
type: 'surface',
|
|
|
|
|
|
controller: this.xcomponentController
|
|
|
|
|
|
})
|
|
|
|
|
|
.onLoad(async () => {
|
2024-06-04 11:19:22 +08:00
|
|
|
|
this.xcomponentController.setXComponentSurfaceSize({ surfaceWidth: 640, surfaceHeight: 480 });
|
2024-01-05 11:11:15 +08:00
|
|
|
|
this.surfaceId = this.xcomponentController.getXComponentSurfaceId()
|
|
|
|
|
|
console.log('jiangsong: xcomponentController this.surfaceId = ' + this.surfaceId)
|
|
|
|
|
|
await this.initCamera();
|
|
|
|
|
|
})
|
|
|
|
|
|
.width('420px')
|
|
|
|
|
|
.height('240px')
|
|
|
|
|
|
}
|
|
|
|
|
|
.backgroundColor(Color.Yellow)
|
2024-06-04 11:19:22 +08:00
|
|
|
|
.position({ x: 0, y: 0 })
|
2024-01-05 11:11:15 +08:00
|
|
|
|
|
|
|
|
|
|
Row() {
|
|
|
|
|
|
Text('拍照')
|
|
|
|
|
|
.width('100px')
|
|
|
|
|
|
.height('55px')
|
|
|
|
|
|
.backgroundColor(Color.Blue)
|
|
|
|
|
|
.onClick(() => {
|
|
|
|
|
|
this.takePhoto()
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
2024-06-04 11:19:22 +08:00
|
|
|
|
|
2024-01-05 11:11:15 +08:00
|
|
|
|
Row() {
|
|
|
|
|
|
Image(this.imageBase64)
|
|
|
|
|
|
.width(420).height(240).border({ width: 1 })
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
.width('100%')
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async aboutToAppear() {
|
|
|
|
|
|
}
|
2024-06-04 11:19:22 +08:00
|
|
|
|
|
2024-01-05 11:11:15 +08:00
|
|
|
|
async aboutToDisappear() {
|
|
|
|
|
|
// 停止当前会话
|
|
|
|
|
|
this.captureSession.stop()
|
|
|
|
|
|
// 释放相机输入流
|
|
|
|
|
|
this.cameraInput.close()
|
|
|
|
|
|
// 释放预览输出流
|
|
|
|
|
|
this.previewOutput.release()
|
|
|
|
|
|
// 释放拍照输出流
|
|
|
|
|
|
this.photoOutput.release()
|
|
|
|
|
|
// 释放会话
|
|
|
|
|
|
this.captureSession.release()
|
|
|
|
|
|
// 会话置空
|
|
|
|
|
|
this.captureSession = null
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-06-04 11:19:22 +08:00
|
|
|
|
async initCamera() {
|
2024-01-05 11:11:15 +08:00
|
|
|
|
let cameraManager = await camera.getCameraManager(globalThis.context)
|
|
|
|
|
|
if (!cameraManager) {
|
|
|
|
|
|
console.error("jiangsong camera.getCameraManager error")
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 监听相机状态变化
|
|
|
|
|
|
cameraManager.on('cameraStatus', (err, cameraStatusInfo) => {
|
|
|
|
|
|
console.info(`jiangsong camera : ${cameraStatusInfo.camera.cameraId}`);
|
|
|
|
|
|
console.info(`jiangsong status: ${cameraStatusInfo.status}`);
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
// 获取相机列表
|
|
|
|
|
|
let cameraArray = await cameraManager.getSupportedCameras();
|
|
|
|
|
|
if (cameraArray.length <= 0) {
|
|
|
|
|
|
console.error("jiangsong cameraManager.getSupportedCameras error")
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (let index = 0; index < cameraArray.length; index++) {
|
2024-06-04 11:19:22 +08:00
|
|
|
|
console.info('cameraId : ' + cameraArray[index].cameraId); // 获取相机ID
|
|
|
|
|
|
console.info('cameraPosition : ' + cameraArray[index].cameraPosition); // 获取相机位置
|
|
|
|
|
|
console.info('cameraType : ' + cameraArray[index].cameraType); // 获取相机类型
|
|
|
|
|
|
console.info('connectionType : ' + cameraArray[index].connectionType); // 获取相机连接类型
|
2024-01-05 11:11:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 创建相机输入流
|
|
|
|
|
|
try {
|
|
|
|
|
|
this.cameraInput = cameraManager.createCameraInput(cameraArray[0]);
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('jiangsong Failed to createCameraInput errorCode = ' + error.code);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 监听cameraInput错误信息
|
|
|
|
|
|
let cameraDevice = cameraArray[0];
|
|
|
|
|
|
this.cameraInput.on('error', cameraDevice, (error) => {
|
|
|
|
|
|
console.info(`jiangsong Camera input error code: ${error.code}`);
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
// 打开相机
|
|
|
|
|
|
await this.cameraInput.open((err) => {
|
|
|
|
|
|
if (err) {
|
|
|
|
|
|
console.error(`jiangsong Failed to open the camera. ${err.code}`);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
console.log('jiangsong Callback returned with camera opened.');
|
|
|
|
|
|
});
|
|
|
|
|
|
// 获取相机设备支持的输出流能力
|
|
|
|
|
|
let cameraOutputCap = await cameraManager.getSupportedOutputCapability(cameraArray[0]);
|
|
|
|
|
|
if (!cameraOutputCap) {
|
|
|
|
|
|
console.error("jiangsong cameraManager.getSupportedOutputCapability error")
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
console.info("outputCapability: " + JSON.stringify(cameraOutputCap));
|
|
|
|
|
|
|
|
|
|
|
|
let previewProfilesArray = cameraOutputCap.previewProfiles;
|
|
|
|
|
|
if (!previewProfilesArray) {
|
|
|
|
|
|
console.error("jiangsong createOutput previewProfilesArray == null || undefined")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let photoProfilesArray = cameraOutputCap.photoProfiles;
|
|
|
|
|
|
if (!photoProfilesArray) {
|
|
|
|
|
|
console.error("jiangsong createOutput photoProfilesArray == null || undefined")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 创建预览输出流,其中参数 surfaceId 参考上文 XComponent 组件,预览流为XComponent组件提供的surface
|
|
|
|
|
|
try {
|
|
|
|
|
|
this.previewOutput = cameraManager.createPreviewOutput(previewProfilesArray[0], this.surfaceId)
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error("jiangsong Failed to create the PreviewOutput instance.")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 监听预览输出错误信息
|
|
|
|
|
|
this.previewOutput.on('error', (error) => {
|
|
|
|
|
|
console.info(`jiangosng Preview output error code: ${error.code}`);
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
// 创建ImageReceiver对象,并设置照片参数:分辨率大小是根据前面 photoProfilesArray 获取的当前设备所支持的拍照分辨率大小去设置
|
|
|
|
|
|
this.imageRecever = await image.createImageReceiver(1920, 1080, 4, 8)
|
|
|
|
|
|
// 获取照片显示SurfaceId
|
|
|
|
|
|
let photoSurfaceId = await this.imageRecever.getReceivingSurfaceId()
|
|
|
|
|
|
// 创建拍照输出流
|
|
|
|
|
|
try {
|
|
|
|
|
|
this.photoOutput = cameraManager.createPhotoOutput(photoProfilesArray[0], photoSurfaceId)
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('jiangsong Failed to createPhotoOutput errorCode = ' + error.code);
|
|
|
|
|
|
}
|
|
|
|
|
|
//创建会话
|
|
|
|
|
|
try {
|
|
|
|
|
|
this.captureSession = cameraManager.createCaptureSession()
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('jiangsong Failed to create the CaptureSession instance. errorCode = ' + error.code);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 监听session错误信息
|
|
|
|
|
|
this.captureSession.on('error', (error) => {
|
|
|
|
|
|
console.info(`jiangsong Capture session error code: ${error.code}`);
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
// 开始配置会话
|
|
|
|
|
|
try {
|
|
|
|
|
|
this.captureSession.beginConfig()
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('jiangsong Failed to beginConfig. errorCode = ' + error.code);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 向会话中添加相机输入流
|
|
|
|
|
|
try {
|
|
|
|
|
|
this.captureSession.addInput(this.cameraInput)
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('jiangsong Failed to addInput. errorCode = ' + error.code);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 向会话中添加预览输出流
|
|
|
|
|
|
try {
|
|
|
|
|
|
this.captureSession.addOutput(this.previewOutput)
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('jiangsong Failed to addOutput(previewOutput). errorCode = ' + error.code);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 向会话中添加拍照输出流
|
|
|
|
|
|
try {
|
|
|
|
|
|
this.captureSession.addOutput(this.photoOutput)
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('jiangsong Failed to addOutput(photoOutput). errorCode = ' + error.code);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 提交会话配置
|
|
|
|
|
|
await this.captureSession.commitConfig()
|
|
|
|
|
|
|
|
|
|
|
|
// 启动会话
|
|
|
|
|
|
await this.captureSession.start().then(() => {
|
|
|
|
|
|
console.info('jiangsong Promise returned to indicate the session start success.');
|
|
|
|
|
|
})
|
|
|
|
|
|
// 判断设备是否支持闪光灯
|
|
|
|
|
|
let flashStatus
|
|
|
|
|
|
try {
|
|
|
|
|
|
flashStatus = this.captureSession.hasFlash()
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('jiangsong Failed to hasFlash. errorCode = ' + error.code);
|
|
|
|
|
|
}
|
|
|
|
|
|
console.info('jiangsong Promise returned with the flash light support status:' + flashStatus);
|
|
|
|
|
|
|
|
|
|
|
|
if (flashStatus) {
|
|
|
|
|
|
// 判断是否支持自动闪光灯模式
|
|
|
|
|
|
let flashModeStatus
|
|
|
|
|
|
try {
|
|
|
|
|
|
let status = this.captureSession.isFlashModeSupported(camera.FlashMode.FLASH_MODE_AUTO)
|
|
|
|
|
|
flashModeStatus = status
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('jiangsong Failed to check whether the flash mode is supported. errorCode = ' + error.code);
|
|
|
|
|
|
}
|
2024-06-04 11:19:22 +08:00
|
|
|
|
if (flashModeStatus) {
|
2024-01-05 11:11:15 +08:00
|
|
|
|
// 设置自动闪光灯模式
|
|
|
|
|
|
try {
|
|
|
|
|
|
this.captureSession.setFlashMode(camera.FlashMode.FLASH_MODE_AUTO)
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('jiangsong Failed to set the flash mode. errorCode = ' + error.code);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
takePhoto() {
|
|
|
|
|
|
let settings = {
|
2024-06-04 11:19:22 +08:00
|
|
|
|
quality: camera.QualityLevel.QUALITY_LEVEL_HIGH, // 设置图片质量高
|
2024-01-05 11:11:15 +08:00
|
|
|
|
rotation: camera.ImageRotation.ROTATION_0 // 设置图片旋转角度0
|
|
|
|
|
|
}
|
|
|
|
|
|
// 使用当前拍照设置进行拍照
|
|
|
|
|
|
this.photoOutput.capture(settings, async (err) => {
|
|
|
|
|
|
if (err) {
|
|
|
|
|
|
console.error(`jiangsong Failed to capture the photo ${err.message}` + JSON.stringify(err));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
console.info('jiangsong Callback invoked to indicate the photo capture request success.');
|
|
|
|
|
|
|
2024-06-04 11:19:22 +08:00
|
|
|
|
this.imageRecever.getReceivingSurfaceId().then(id => {
|
2024-01-05 11:11:15 +08:00
|
|
|
|
console.log('jiangsong getReceivingSurfaceId succeeded.');
|
|
|
|
|
|
}).catch(error => {
|
|
|
|
|
|
console.log('jiangsong getReceivingSurfaceId failed.');
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
this.getPhoto();
|
|
|
|
|
|
this.timeSetTimeout = 0;
|
2024-06-04 11:19:22 +08:00
|
|
|
|
clearTimeout(this.timer);
|
2024-01-05 11:11:15 +08:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
getPhoto() {
|
|
|
|
|
|
this.imageRecever.readLatestImage((err, img) => {
|
2024-06-04 11:19:22 +08:00
|
|
|
|
if (err) {
|
|
|
|
|
|
console.log('jiangsong readLatestImage failed.' + JSON.stringify((err)));
|
|
|
|
|
|
this.timeSetTimeout++;
|
|
|
|
|
|
if (this.timeSetTimeout > 20) {
|
2024-01-05 11:11:15 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
this.timer = setTimeout(() => {
|
|
|
|
|
|
this.getPhoto()
|
|
|
|
|
|
}, 300)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.log('jiangsong img.clipRect.' + JSON.stringify(img.clipRect));
|
|
|
|
|
|
|
|
|
|
|
|
img.getComponent(4, (err, component) => {
|
2024-06-04 11:19:22 +08:00
|
|
|
|
if (err) {
|
2024-01-05 11:11:15 +08:00
|
|
|
|
console.log('jiangsong getComponent failed.' + JSON.stringify(err));
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
|
|
const imagePackerApi = image.createImagePacker();
|
2024-06-04 11:19:22 +08:00
|
|
|
|
let packOpts = { format: "image/jpeg", quality: 98 };
|
2024-01-05 11:11:15 +08:00
|
|
|
|
|
|
|
|
|
|
let buf = buffer.from(component.byteBuffer);
|
|
|
|
|
|
let str = buf.toString('base64')
|
|
|
|
|
|
this.imageBase64 = this.imageBase64 + str
|
|
|
|
|
|
// console.error('jiangsong this.imageBase64.length: ' + this.imageBase64.length);
|
|
|
|
|
|
// console.error('jiangsong this.imageBase64.length: ' + this.imageBase64.slice(1, 100));
|
|
|
|
|
|
//
|
|
|
|
|
|
// const imageSource = image.createImageSource(component.byteBuffer);
|
|
|
|
|
|
// imagePackerApi.packing(imageSource, packOpts).then(async data => {
|
|
|
|
|
|
// console.log('jiangsong encodeToStringSync data.' + typeof data);
|
|
|
|
|
|
// // let res = await writeFile({
|
|
|
|
|
|
// // fileName: '/test.jpg',
|
|
|
|
|
|
// // buffer: data
|
|
|
|
|
|
// // });
|
|
|
|
|
|
//
|
|
|
|
|
|
// let buf = buffer.from(data);
|
|
|
|
|
|
// let str = buf.toString('base64')
|
|
|
|
|
|
// this.imageBase64 = this.imageBase64 + str
|
|
|
|
|
|
// }).catch(error => {
|
|
|
|
|
|
// console.error('jiangsong Failed to pack the image. And the error is: ' + error);
|
|
|
|
|
|
// })
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|