add image ets demo

Signed-off-by: fengzewu <fengzewu@huawei.com>
This commit is contained in:
fengzewu
2022-08-19 18:22:52 +08:00
parent 00f7461c3b
commit ebd7ffd4e9
115 changed files with 6184 additions and 0 deletions
@@ -0,0 +1,5 @@
/node_modules
/local.properties
/.idea
**/build
/.hvigor
@@ -0,0 +1,55 @@
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
{
"app": {
"signingConfigs": [
{
"name": "default",
"material": {
"certpath": "C:\\Users\\qiyi\\.ohos\\config\\openharmony\\auto_ohos_default.cer",
"storePassword": "0000001B660C4381B00F55A461D445803E34F0AA354E1D6597EEBEC1090D639564BF110CC4ECE46F1D491A",
"keyAlias": "debugKey",
"keyPassword": "0000001BA91ECB16B6010E4002D624DEF5BDC5FDA5D4B88E14A532A5F7C5BFCB121504F391CBDE972261DD",
"profile": "C:\\Users\\qiyi\\.ohos\\config\\openharmony\\auto_ohos_default_com.example.myapplication.p7b",
"signAlg": "SHA256withECDSA",
"storeFile": "C:\\Users\\qiyi\\.ohos\\config\\openharmony\\auto_ohos_default.p12"
}
}
],
"compileSdkVersion": 8,
"compatibleSdkVersion": 8,
"products": [
{
"name": "default",
"signingConfig": "default",
}
]
},
"modules": [
{
"name": "entry",
"srcPath": "./entry",
"targets": [
{
"name": "default",
"applyToProducts": [
"default"
]
}
]
}
]
}
@@ -0,0 +1,4 @@
/node_modules
/.preview
/build
/.cxx
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
{
"apiType": 'faMode',
"buildOption": {
},
"targets": [
{
"name": "default"
},
{
"name": "ohosTest",
}
]
}
@@ -0,0 +1,2 @@
// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently.
module.exports = require('@ohos/hvigor-ohos-plugin').legacyHapTasks
@@ -0,0 +1,5 @@
{
"name": "entry",
"version": "1.0.0",
"lockfileVersion": 1
}
@@ -0,0 +1,14 @@
{
"license": "ISC",
"devDependencies": {},
"name": "entry",
"ohos": {
"org": "huawei",
"directoryLevel": "module",
"buildTool": "hvigor"
},
"description": "example description",
"repository": {},
"version": "1.0.0",
"dependencies": {}
}
@@ -0,0 +1,73 @@
{
"app": {
"bundleName": "com.example.myapplication",
"vendor": "example",
"version": {
"code": 1000000,
"name": "1.0.0"
}
},
"deviceConfig": {},
"module": {
"package": "com.example.entry",
"name": ".entry",
"mainAbility": ".MainAbility",
"deviceType": [
"default",
"tablet"
],
"distro": {
"deliveryWithInstall": true,
"moduleName": "entry",
"moduleType": "entry",
"installationFree": false
},
"abilities": [
{
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
],
"orientation": "unspecified",
"formsEnabled": false,
"name": ".MainAbility",
"srcLanguage": "ets",
"srcPath": "MainAbility",
"icon": "$media:icon",
"description": "$string:MainAbility_desc",
"label": "$string:MainAbility_label",
"type": "page",
"visible": true,
"launchType": "standard"
}
],
"js": [
{
"mode": {
"syntax": "ets",
"type": "pageAbility"
},
"pages": [
"pages/index",
"pagesTwo/PixelMap",
"pagesTwo/Image",
"pagesTwo/ImagePacker",
"pagesTwo/ImageSource",
"pagesTwo/source1",
"pagesTwo/index1"
],
"name": ".MainAbility",
"window": {
"designWidth": 720,
"autoDesignWidth": false
}
}
]
}
}
@@ -0,0 +1,23 @@
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export default {
onCreate() {
console.info('Application onCreate')
},
onDestroy() {
console.info('Application onDestroy')
},
}
@@ -0,0 +1,174 @@
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// index.ets
import router from '@ohos.router';
@Entry
@Component
struct Index {
@State message: string = 'ImageTest'
build() {
Row() {
Column() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceEvenly }){
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
// 添加按钮,以响应用户点击
Button() {
Text('PixelMap')
.fontSize(30)
.fontWeight(FontWeight.Bold)
}
.type(ButtonType.Capsule)
.margin({
top: 20
})
.backgroundColor('#0D9FFB')
.width('60%')
.height('5%')
// 跳转按钮绑定onClick事件,点击时跳转到第二页
.onClick(() => {
router.push({ url: 'pagesTwo/PixelMap' })
})
Button() {
Text('ImageSource')
.fontSize(30)
.fontWeight(FontWeight.Bold)
}
.type(ButtonType.Capsule)
.margin({
top: 20
})
.backgroundColor('#0D9FFB')
.width('60%')
.height('5%')
// 跳转按钮绑定onClick事件,点击时跳转到第二页
.onClick(() => {
router.push({ url: 'pagesTwo/ImageSource' })
})
Button() {
Text('ImagePacker')
.fontSize(30)
.fontWeight(FontWeight.Bold)
}
.type(ButtonType.Capsule)
.margin({
top: 20
})
.backgroundColor('#0D9FFB')
.width('60%')
.height('5%')
// 跳转按钮绑定onClick事件,点击时跳转到第二页
.onClick(() => {
router.push({ url: 'pagesTwo/ImagePacker' })
})
Button() {
Text('ImageReceiver')
.fontSize(30)
.fontWeight(FontWeight.Bold)
}
.type(ButtonType.Capsule)
.margin({
top: 20
})
.backgroundColor('#0D9FFB')
.width('60%')
.height('5%')
// 跳转按钮绑定onClick事件,点击时跳转到第二页
.onClick(() => {
router.push({ url: 'pagesTwo/ImageReceiver' })
})
Button() {
Text('Image')
.fontSize(30)
.fontWeight(FontWeight.Bold)
}
.type(ButtonType.Capsule)
.margin({
top: 20
})
.backgroundColor('#0D9FFB')
.width('60%')
.height('5%')
// 跳转按钮绑定onClick事件,点击时跳转到第二页
.onClick(() => {
router.push({ url: 'pagesTwo/Image' })
})
Button() {
Text('source1')
.fontSize(30)
.fontWeight(FontWeight.Bold)
}
.type(ButtonType.Capsule)
.margin({
top: 20
})
.backgroundColor('#0D9FFB')
.width('60%')
.height('5%')
// 跳转按钮绑定onClick事件,点击时跳转到第二页
.onClick(() => {
router.push({ url: 'pagesTwo/source1' })
})
Button() {
Text('camera')
.fontSize(30)
.fontWeight(FontWeight.Bold)
}
.type(ButtonType.Capsule)
.margin({
top: 20
})
.backgroundColor('#0D9FFB')
.width('60%')
.height('5%')
// 跳转按钮绑定onClick事件,点击时跳转到第二页
.onClick(() => {
router.push({ url: 'pagesTwo/CameraPage' })
})
Button() {
Text('index1')
.fontSize(30)
.fontWeight(FontWeight.Bold)
}
.type(ButtonType.Capsule)
.margin({
top: 20
})
.backgroundColor('#0D9FFB')
.width('60%')
.height('5%')
// 跳转按钮绑定onClick事件,点击时跳转到第二页
.onClick(() => {
router.push({ url: 'pagesTwo/index1' })
})
}
}
.width('100%')
}
.height('100%')
}
}
@@ -0,0 +1,99 @@
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// @ts-nocheck
import router from '@ohos.router';
import multimedia_image from '@ohos.multimedia.image';
import resourceManager from '@ohos.resourceManager';
@Entry
@Component
struct Index1 {
@State imgSource: multimedia_image.ImageSource = undefined
@State _pixelMap: multimedia_image.PixelMap = undefined
async pxiel1() {
console.info('1111111 createPixelBYBuffer begin');
var color = new ArrayBuffer(96);
var bufferArr = new Uint8Array(color);
for (var i = 0; i < bufferArr.length; i++) {
bufferArr[i] = i + 100;
}
let opts = { editable: true, pixelFormat: 3, size: { height: 4, width: 6 } }
// 通过属性创建PixelMap,默认采用BGRA_8888格式处理数据,通过Promise返回结果。
multimedia_image.createPixelMap(color, opts).then((pixelMap)=>{
this._pixelMap = pixelMap;
})
}
async pxiel2() {
console.info('222222 createPixelBYBuffer begin');
var color = new ArrayBuffer(96);
var bufferArr = new Uint8Array(color);
for (var i = 0; i < bufferArr.length; i++) {
bufferArr[i] = i + 100;
}
let opts = { editable: true, pixelFormat: 3, size: { height: 4, width: 6 } }
// 通过属性创建PixelMap,默认采用BGRA_8888格式处理数据,通过callback返回结果。
multimedia_image.createPixelMap(color, opts, (error, pixelmap) => {
if(error) {
console.log('222222 Failed to create pixelmap.');
} else {
this._pixelMap = pixelMap;
console.log('222222 Succeeded in creating pixelmap.');
}
})
}
build() {
Row() {
Column() {
Button('提交').onClick(() => {
this.pxiel1()
}).height('10%')
.width('15%')
.margin(20)
Button('提交').onClick(() => {
this.pxiel2()
}).height('10%')
.width('15%')
.margin(20)
// Button('imageS').onClick(() => {
// this.imageS()
// }).height('10%')
// .width('15%')
// .margin(20)
Flex({ justifyContent: FlexAlign.SpaceAround }) {
Image(this._pixelMap)
.border({ width: 1, color: Color.Blue })
.width(50).height(50)
.objectFit(ImageFit.Cover)
// .backgroundColor(Color.Red)
}
}
.width('100%')
}
.height('100%')
}
}
@@ -0,0 +1,139 @@
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import router from '@ohos.router';
import multimedia_image from '@ohos.multimedia.image';
import resourceManager from '@ohos.resourceManager';
@Entry
@Component
struct imagePacker {
@State imgSource: multimedia_image.ImageSource = undefined
@State _pixelMap: multimedia_image.PixelMap = undefined
@State imagePackerApi: multimedia_image.ImagePacker = undefined
@State error: object = undefined
async getFd(fileName) {
let mgr = await resourceManager.getResourceManager()
let value = await mgr.getRawFileDescriptor(fileName)
return value.fd
}
async aboutToAppear() {
let fd = await this.getFd('test_exif.jpg')
this.imgSource = multimedia_image.createImageSource(fd)
}
async btn() {
let decodingOptions = {
editable: true,
desiredPixelFormat: 3
}
this.imgSource.createPixelMap(decodingOptions).then(async (pixelMap) => {
this._pixelMap = pixelMap
}).catch(error => {
this.error = error
console.log('q_yP1 pixelMap error' + error);
})
}
async pac() {
console.info("q_yP start")
this.imagePackerApi = multimedia_image.createImagePacker();
console.info("q_yP log1")
let packOpts = { format:"image/jpeg", quality:98 };
console.info("q_yP log2")
// 图片压缩或重新打包,使用callback形式返回结果。 failed
// this.imagePackerApi.packing(this.imgSource, packOpts, data => {
// console.info("q_yP2 The packed buffer is :" + data)
// })
// console.info("q_yP log3")
// 图片压缩或重新打包,使用Promise形式返回结果 success
this.imagePackerApi.packing(this.imgSource, packOpts)
.then( data => {
console.info("q_yP3 The packed buffer is :" + data)
}).catch(error => {
console.info('q_yP4 packing failed.');
})
console.info("q_yP log4")
// 图片压缩或重新打包,使用callback形式返回结果。 failed
// this.imagePackerApi.packing(this._pixelMap, packOpts, data => {
// console.info("q_yP5 The packed buffer is :" + data)
// })
// console.info("q_yP log5")
// const Color = new ArrayBuffer(96);
// var opts = { editable: true, pixelFormat: 2, size: { height: 4, width: 6 } }
// multimedia_image.createPixelMap(Color, opts)
// .then(pixelmap => {
// if (pixelmap == undefined) {
// console.info('q_yP create pixelmap error.');
// } else {
// this.imagePackerApi.packing(pixelmap, packOpts, (err, data) => {
// console.info("q_yP3 The packed buffer is :" + data)
// })
// }
// })
// 图片压缩或重新打包,使用Promise形式返回结果 success
// this.imagePackerApi.packing(this._pixelMap, packOpts)
// .then( data => {
// console.info("q_yP6 The packed buffer is :" + data)
// }).catch(error => {
// console.error('q_yP7 Failed to pack the image..');
// })
console.info("q_yP log6")
}
build() {
Row() {
Column() {
Button('提交').onClick(() => {
this.btn()
})
Button('packer').onClick(() => {
this.pac()
})
Flex({ justifyContent: FlexAlign.SpaceAround }) {
Image(this._pixelMap).border({ width: 1, color: Color.Blue }).width(500).height(500).objectFit(ImageFit.None).backgroundColor(Color.Red)
}
Button() {
Text('Back')
.fontSize(25)
.fontWeight(FontWeight.Bold)
}
.type(ButtonType.Capsule)
.margin({
top: 20
})
.backgroundColor('#0D9FFB')
.width('40%')
.height('5%')
// 返回按钮绑定onClick事件,点击按钮时返回到第一页
.onClick(() => {
router.back()
})
}
.width('100%')
}
.height('100%')
}
}
@@ -0,0 +1,260 @@
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// @ts-nocheck
import multimedia_image from '@ohos.multimedia.image';
import resourceManager from '@ohos.resourceManager';
import fileio from '@ohos.fileio';
import featureAbility from '@ohos.ability.featureAbility';
@Entry
@Component
struct Index1 {
@State imgSource: multimedia_image.ImageSource = undefined
@State _pixelMap: multimedia_image.PixelMap = undefined
@State op: number = 1
async getFd(fileName) {
console.info('q_yFd3 in')
let mgr = await resourceManager.getResourceManager()
let value = await mgr.getRawFileDescriptor(fileName)
console.info('q_yFd4 out')
return value.fd
}
async aboutToAppear() {
console.info('q_yFd1 in')
// 1.从沙箱路径读取图片
// 将图片推入沙箱路径(/data/app/el2/100/base/com.example.myapplication/haps/entry/cache)中
// 修改权限777后读取
let context = featureAbility.getContext()
let data = await context.getCacheDir()
console.info("q_y data = " + data)
let fd = fileio.openSync(data + '/test_exif.jpg', 0o2)
console.info('q_yFd1 in fd = ' + fd)
// // 2.从本地rawfile读取图片
// let fd = await this.getFd('test_exif.jpg')
this.imgSource = multimedia_image.createImageSource(fd)
if (this.imgSource == undefined) {
console.info('q_y create imageSource error')
}
console.info('q_yFd2 out')
}
async btn() {
console.info('q_yFd2 out')
let decodingOptions = {
editable: true,
desiredPixelFormat: 3
}
this.imgSource.createPixelMap(decodingOptions).then(async (pixelMap) => {
if (pixelMap == undefined) {
console.info('q_yP createPixelMap failed')
}
this._pixelMap = pixelMap
}).catch(error => {
this.error = error
console.log('pixelMap error' + error)
})
}
async imageS() {
// modifyImageProperty(key: string, value: string): Promise<void>
// 通过指定的键修改图片属性的值,使用Promise形式返回结果。 需要写入权限
// 参数名:key 类型:string 必填
// 参数名:value 类型string 必填
// key参数说明:图片属性名。
// value参数说明:属性值。
// 测试结果:success
this.imgSource.modifyImageProperty("Orientation", "2")
.then(() => {
this.imgSource.getImageProperty("Orientation").then(data => {
console.info(`q_yS1 Orientation = ` + data);
}).catch((err) => {
console.info(`q_yS2 getImageProperty failed, err`);
})
}).catch( error => {
console.info('q_yS3 failed to modifyImageProperty ')
})
// modifyImageProperty(key: string, value: string, callback: AsyncCallback<void>): void
// 通过指定的键修改图片属性的值,使用callback形式返回结果。 需要写入权限
// 参数名:key 类型:string 必填
// 参数名:value 类型:string 必填
// 参数名:callback 类型:AsyncCallback<void> 必填
// key参数说明:图片属性名。
// value参数说明:属性值。
// callback参数说明:修改属性值,以callback形式返回结果。
// 测试结果:success
this.imgSource.modifyImageProperty("Orientation", "2",() => {
this.imgSource.getImageProperty("Orientation").then(data => {
console.info(`q_yS4 Orientation = ` + data);
}).catch((err) => {
console.info(`q_yS5 getImageProperty failed, err`);
})
})
// 获取指定序号的图片信息,使用callback形式返回图片信息。 Success
this.imgSource.getImageInfo(0,(error, imageInfo) => {
if(error) {
console.info('q_yS6 getImageInfo failed.');
} else {
console.info('q_yS7 getImageInfo succeeded and width is ' + imageInfo.size.width);
console.info('q_yS8 getImageInfo succeeded and height is ' + imageInfo.size.height);
}
})
// 获取图片信息,使用callback形式返回图片信息 failed
this.imgSource.getImageInfo(imageInfo => {
console.info('q_yS9 getImageInfo succeeded and width is ' + imageInfo.size.width);
console.info('q_yS10 getImageInfo succeeded and height is ' + imageInfo.size.height);
})
// 获取图片信息,使用Promise形式返回图片信息。 Success
this.imgSource.getImageInfo(0)
.then(imageInfo => {
console.info('q_yS11 getImageInfo succeeded and width is ' + imageInfo.size.width);
console.info('q_yS12 getImageInfo succeeded and height is ' + imageInfo.size.height);
}).catch(error => {
console.log('q_yS13 Failed to obtain the image information.');
})
// 更新增量数据,使用Promise形式返回结果。 Success
const array = new ArrayBuffer(100);
this.imgSource.updateData(array, false, 0, 10).then(() => {
console.info('q_yS14 Succeeded in updating data.')
})
// 更新增量数据,callback形式返回结果。 Success
this.imgSource.updateData(array, false, 0, 10,(error,data )=> {
if(data !== undefined){
console.info('q_yS15 Succeeded in updating data.')
}
})
// 获取图片中给定索引处图像的指定属性键的值,用Promise形式返回结果。 Success
this.imgSource.getImageProperty("Orientation")
.then(data => {
console.info('q_yS16 Succeeded in getting the value of the specified attribute key of the image and the data is:' + data)
}).catch(error => {
console.info("q_yS17 Failed to get the value of the specified attribute.")
})
// 获取图片中给定索引处图像的指定属性键的值,用callback形式返回结果。 Success
this.imgSource.getImageProperty("GPSLatitude",(error, data) => {
if(error) {
console.info('q_yS18 Failed to get the value of the specified attribute key of the image.')
} else {
console.info('q_yS19 Succeeded in getting the value of the specified attribute key of the image and the data is:' + data)
}
})
// 获取图片指定属性键的值,callback形式返回结果。 Success
var property = {index: 1, defaultValue: '100'}
this.imgSource.getImageProperty("Orientation",property,(error,data) => {
if(error) {
console.info('q_yS20 Failed to get the value of the specified attribute key of the image.')
} else {
console.info('q_yS21 Succeeded in getting the value of the specified attribute key of the image and the data is:' + data)
}
})
// 通过图片解码参数创建PixelMap对象 Success
this.imgSource.createPixelMap().then(pixelmap => {
console.log('q_yS22 Succeeded in creating pixelmap object through image decoding parameters.');
}).catch(error => {
console.log('q_yS23 Failed to create pixelmap object through image decoding parameters.');
})
// 通过默认参数创建PixelMap对象,使用callback形式返回结果。 Success
this.imgSource.createPixelMap((err, pixelmap) => {
console.info('q_yS24 Succeeded in creating pixelmap object.')
})
// 通过默认参数创建PixelMap对象,使用callback形式返回结果。 Success
let decodingOptions = {
editable: true,
desiredPixelFormat: 3
}
this.imgSource.createPixelMap(decodingOptions, pixelmap => {
console.log('q_yS25 Succeeded in creating pixelmap object.');
})
//// 释放图片源实例,使用Promise形式返回结果。 Success
// this.imgSource.release().then(()=>{
// console.info('q_yS26 Success in releasing the image source instance.');
// })
//
//// 释放图片源实例,使用callback形式返回结果。 Success
// this.imgSource.release(() => {
// console.info('q_yS27 Success in releasing the image source instance.');
// })
}
build() {
Row() {
Column() {
Text('透明度:' + this.op)
.fontWeight(FontWeight.Bold).margin(15)
TextInput({ placeholder: '透明度' })
.type(InputType.Normal)
.placeholderColor(Color.Gray)
.placeholderFont({ size: 12 })
.onChange((value: string) => {
this.op = value
})
// Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center, wrap:FlexWrap.Wrap}) {
// Text('key' + this.key)
// .fontWeight(FontWeight.Bold)
// } .margin(20)
// Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
// TextInput({ placeholder: 'KEY' })
// .type(InputType.Normal)
// .placeholderColor(Color.Gray)
// .placeholderFont({ size: 12 })
// .onChange((value: string) => {
// this.key = value
// })
// } .margin(20)
Button('提交').onClick(() => {
this.btn()
}).height('8%')
.width('20%')
.margin(20)
Button('imageS').onClick(() => {
this.imageS()
}).height('8%')
.width('20%')
.margin(20)
Flex({ justifyContent: FlexAlign.SpaceAround }) {
Image(this._pixelMap)
.border({ width: 1, color: Color.Blue })
.width(500).height(500)
.objectFit(ImageFit.None)
.backgroundColor(Color.Red)
}
}
.width('100%')
}
.height('100%')
}
}
@@ -0,0 +1,460 @@
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// @ts-nocheck
import router from '@ohos.router';
import multimedia_image from '@ohos.multimedia.image';
import resourceManager from '@ohos.resourceManager';
@Entry
@Component
struct Index1 {
@State imgSource: multimedia_image.ImageSource = undefined
@State _pixelMap: multimedia_image.PixelMap = undefined
@State str1: number = 0
@State str2: number = 0
@State str1H: number = 0
@State str2H: number = 0
@State error: object = undefined
@State scaleX: number = 1
@State scaleY: number = 1
@State translateX: number = 0
@State translateY: number = 0
@State rotateC: number = 0
@State flipX: boolean = false
@State flipY: boolean = false
@State regionH: number = 0
@State regionW: number = 0
@State regionX: number = 0
@State regionY: number = 0
@State op: number = 1
// 通过访问指定资源文件下的fileName,获取fd
//文件路径为/resources/rawfile
async getFd(fileName) {
let mgr = await resourceManager.getResourceManager()
let value = await mgr.getRawFileDescriptor(fileName)
return value.fd
}
async aboutToAppear() {
let fd = await this.getFd('opacity.png')
this.imgSource = multimedia_image.createImageSource(fd)
}
async btn() {
let decodingOptions = {
editable: true,
desiredPixelFormat: 3
}
this.imgSource.createPixelMap(decodingOptions).then(async (pixelMap) => {
let orgInfo = await pixelMap.getImageInfo()
this.str1 = orgInfo.size.width
this.str1H = orgInfo.size.height
// 根据输入的尺寸对图片进行裁剪
let region = { size: { height: Number(this.regionH), width: Number(this.regionW) }, x: Number(this.regionX), y: Number(this.regionY) };
await pixelMap.crop(region);
// 根据输入的宽高对图片进行缩放。
await pixelMap.scale(Number(this.scaleX), Number(this.scaleY))
// 根据输入的坐标对图片进行位置变换。
await pixelMap.translate(Number(this.translateX), Number(this.translateY))
// 根据输入的角度对图片进行旋转。
await pixelMap.rotate(this.rotateC)
// 根据输入的条件对图片进行翻转
await pixelMap.flip(this.flipX, this.flipY);
// 通过设置透明比率来让PixelMap达到对应的透明效果
await pixelMap.opacity(Number(this.op)) //要求图片带有透明度通道
let newInfo = await pixelMap.getImageInfo()
this.str2 = newInfo.size.width
this.str2H = newInfo.size.height
// readPixelsToBuffer(dst: ArrayBuffer): Promise<void>
// 读取图像像素数据,结果写入ArrayBuffer里,使用promise形式返回。指定BGRA_8888格式创建pixelmap,读取的像素数据与原数据保持一致。
// 参数名:dst 类型:ArrayBuffer 必填
// dst参数说明:缓冲区,函数执行结束后获取的图像像素数据写入到该内存区域内。缓冲区大小由getPixelBytesNumber接口获取。
// 测试结果:success
const readBuffer = new ArrayBuffer(pixelMap.getPixelBytesNumber());
pixelMap.readPixelsToBuffer(readBuffer).then(() => {
//符合条件则进入
console.info('q_y2 Succeeded in reading image pixel data --promise.');
}).catch(error => {
//不符合条件则进入
console.info('q_y3 Failed to read image pixel data --promise.');
})
// readPixelsToBuffer(dst: ArrayBuffer, callback: AsyncCallback<void>): void
// 读取图像像素数据,结果写入ArrayBuffer里,使用callback形式返回。指定BGRA_8888格式创建pixelmap,读取的像素数据与原数据保持一致。
// 参数名:dst 类型:ArrayBuffer 必填
// 参数名:callback 类型:AsyncCallback<void> 必填
// dst参数说明:缓冲区,函数执行结束后获取的图像像素数据写入到该内存区域内。缓冲区大小由getPixelBytesNumber接口获取。
// callback参数说明:获取回调,失败时返回错误信息。
// 测试结果:success
pixelMap.readPixelsToBuffer(readBuffer, () => {
//符合条件则进入
console.info('q_y4 Succeeded in reading the image data in the area --promise.');
})
// readPixels(area: PositionArea): Promise<void>
// 读取区域内的图片数据,使用promise形式返回读取结果。
// 参数名:area 类型:PositionArea 必填
// area参数说明:区域大小,根据区域读取。
// 测试结果:success
const area = { pixels: new ArrayBuffer(8),
offset: 0,
stride: 8,
region: { size: { height: 1, width: 2 }, x: 0, y: 0 }
};
pixelMap.readPixels(area).then(() => {
console.info('q_y6 Succeeded in reading the image data in the area --promise.'); //符合条件则进入
}).catch(error => {
console.info('q_y7 Failed to read the image data in the area --promise.'); //不符合条件则进入
})
// readPixels(area: PositionArea, callback: AsyncCallback<void>): void
// 读取区域内的图片数据,使用callback形式返回读取结果。
// 参数名:area 类型:PositionArea 必填
// 参数名:callback 类型:AsyncCallback<void> 必填
// area参数说明:区域大小,根据区域读取。
// callback参数说明:获取回调,失败时返回错误信息。
// 测试结果:success
pixelMap.readPixels(area, () => {
console.info('q_y8 ReadPixels success --callback');
})
// writePixels(area: PositionArea): Promise<void>
// 将PixelMap写入指定区域内,使用promise形式返回写入结果。
// 参数名:area 类型:PositionArea 必填
// area参数说明:区域大小,根据区域写入。
// 测试结果:success
const writeArea = { pixels: new ArrayBuffer(8),
offset: 0,
stride: 8,
region: { size: { height: 1, width: 2 }, x: 0, y: 0 }
};
pixelMap.writePixels(writeArea).then(() => {
//符合条件则进入
console.info('q_y10 Succeeded in writing the image data in the area --promise.');
}).catch(error => {
//不符合条件则进入
console.info('q_y9 Failed to write the image data in the area --promise.');
})
// writePixels(area: PositionArea, callback: AsyncCallback<void>): void
// 将PixelMap写入指定区域内,使用callback形式返回写入结果。
// 参数名:area 类型:PositionArea 必填
// 参数名:callback 类型:AsyncCallback<void> 必填
// area参数说明:区域大小,根据区域写入。
// callback参数说明:获取回调,失败时返回错误信息。
// 测试结果:success
pixelMap.writePixels(writeArea, (error) => {
if (error != undefined) {
console.info('q_y11 Failed to write pixelMap into the specified area --callback.');
} else {
console.info('q_y12 Succeeded to write pixelMap into the specified area --callback.');
}
})
const writeColor = new ArrayBuffer(96);
// writeBufferToPixels(src: ArrayBuffer): Promise<void>
// 读取缓冲区中的图片数据,结果写入PixelMap中,使用callback形式返回。
// 参数名:src 类型:ArrayBuffer 必填
// src参数说明:图像像素数据。
// 测试结果:Failed
// var bufferArr = new Uint8Array(writeColor);
// for (var i = 0; i < bufferArr.length; i++) {
// bufferArr[i] = i + 1;
// }
// pixelMap.writeBufferToPixels(writeColor).then(() => {
// pixelMap.readPixelsToBuffer(readBuffer).then(() => {
// var res = true;
// for (var i = 0; i < bufferArr.length; i++) {
// if (bufferArr[i] == 0) {
// res = false;
// console.info('q_y13 failed');
// expect(false).assertTrue()
// done();
// break;
// }
// }
// if (res) {
// console.info('q_y14 success');
// expect(true).assertTrue();
// done();
// }
// })
// })
// writeBufferToPixels(src: ArrayBuffer, callback: AsyncCallback<void>): void
// 读取缓冲区中的图片数据,结果写入PixelMap中,使用callback形式返回。
// 参数名:src 类型:ArrayBuffer 必填
// 参数名:callback 类型:AsyncCallback<void> 必填
// src参数说明:图像像素数据。
// callback参数说明:获取回调,失败时返回错误信息。
// 测试结果:success
pixelMap.writeBufferToPixels(writeColor,() => {
pixelMap.readPixelsToBuffer(readBuffer,() => {
var bufferArr = new Uint8Array(readBuffer);
var res = true;
for (var i = 0; i < bufferArr.length; i++) {
if(res) {
if (bufferArr[i] == 0) {
res = false;
console.info('q_y15 Success writeBufferToPixels');
expect(true).assertTrue()
done();
break;
}
}
}
if (res) {
console.info('q_y16 no change after writeBuffer');
expect(false).assertTrue();
done();
}
})
})
// getImageInfo(): Promise<ImageInfo>
// 获取图像像素信息,使用promise形式返回获取的图像像素信息。
// 返回值类型:Promise<ImageInfo> 必填
// 返回值说明:Promise实例,用于异步获取图像像素信息,失败时返回错误信息。
// 测试结果:success
pixelMap.getImageInfo().then(function(info) {
console.info('q_y17 --promise info.width = ' + info.size.width);
console.info('q_y18 --promise info.height = ' + info.size.height);
}).catch((err) => {
console.info("q_y19 Failed to obtain the image pixel map information --promise.");
});
// getImageInfo(callback: AsyncCallback<ImageInfo>): void
// 获取图像像素信息,使用callback形式返回获取的图像像素信息。 success 但是打印不出宽高
// 参数名:callback 类型:AsyncCallback<ImageInfo> 必填
// callback参数说明:获取图像像素信息回调,异步返回图像像素信息,失败时返回错误信息。
// 测试结果:failed
pixelMap.getImageInfo((imageInfo) => {
console.info('q_y20 --callback imageInfo.width = ' + imageInfo.size.width);
console.info('q_y21 --callback imageInfo.height = ' + imageInfo.size.height);
})
// 获取图像像素每行字节数。
let rowCount = pixelMap.getBytesNumberPerRow();
console.info("q_y22 pixelBytesNumber =" + rowCount);
// 获取图像像素的总字节数。 success
const pixelBytesNumber = pixelMap.getPixelBytesNumber();
console.info("q_y23 pixelBytesNumber =" + pixelBytesNumber);
// 获取当前图像像素的密度。 success
const getDensity = pixelMap.getDensity();
console.info("q_y24 getDensity =" + getDensity);
// opacity(rate: number, callback: AsyncCallback<void>): void
// 通过设置透明比率来让PixelMap达到对应的透明效果,使用callback形式返回,要求图片带有开发通道。 success
// 参数名:rate 类型:number 必填
// 参数名:callback 类型:AsyncCallback<void> 必填
// rate参数说明:透明比率的值,取值范围:0-1。
// callback参数说明:获取回调,失败时返回错误信息。
// 测试结果:success
pixelMap.opacity((this.op),()=>{
console.info("q_y25 Succeeded in obtaining the opacity and the opacity is : " + this.op);
})
// createAlphaPixelmap(): Promise<PixelMap>
// 根据Alpha通道的信息,来生成一个仅包含Alpha通道信息的pixelMap,可用于阴影效果,使用promise形式返回。 success
// 返回值类型:Promise<PixelMap> 必填
// 返回值说明:Promise实例,返回pixelmap。
// 测试结果:success
pixelMap.createAlphaPixelmap(async (err, alphaPixelMap) => {
if (alphaPixelMap == undefined) {
console.error('q_y26 Failed to obtain new pixel map --promise.');
} else {
console.info('q_y27 Succeed in obtaining new pixel map --promise.');
}
})
// createAlphaPixelmap(callback: AsyncCallback<PixelMap>): void
// 根据Alpha通道的信息,来生成一个仅包含Alpha通道信息的pixelMap,可用于阴影效果,使用callback形式返回。 success
// 参数名:rate 类型:number 必填
// 参数名:callback 类型:AsyncCallback<PixelMap> 必填
// 参数说明:获取回调,异步返回PixelMap。
// 测试结果:success
pixelMap.createAlphaPixelmap(async (err, alphaPixelMap) => {
console.info('q_y28 Succeed in obtain new pixel map.');
})
this._pixelMap = pixelMap
// release():Promise<void>
// 释放PixelMap对象,使用promiss形式返回释放结果。 success
// pixelMap.release()
// .then(() => {
// console.info('q_y29 Succeeded in releasing pixelMap object.');
// }).catch(error => {
// console.info('q_y30 Failed to release pixelMap object.');
// })
//// 释放PixelMap对象,使用callback形式返回释放结果。 success
// pixelMap.release(() => {
// console.log('q_y31 Succeeded in releasing pixelmap object.');
// })
}).catch(error => {
this.error = error
console.log('pixelMap error' + error);
})
}
build() {
Row() {
Column() {
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center, wrap:FlexWrap.Wrap}) {
Text('原始宽度:' + this.str1)
.fontWeight(FontWeight.Bold)
Text('最终宽度:' + this.str2)
.fontWeight(FontWeight.Bold).margin(15)
Text('原始宽度:' + this.str1H)
.fontWeight(FontWeight.Bold)
Text('最终宽度:' + this.str2H)
.fontWeight(FontWeight.Bold).margin(15)
Text('缩放参数X' + this.scaleX)
.fontWeight(FontWeight.Bold).margin(15)
Text('缩放参数Y' + this.scaleY)
.fontWeight(FontWeight.Bold).margin(15)
Text('平移参数X' + this.translateX)
.fontWeight(FontWeight.Bold).margin(15)
Text('平移参数Y' + this.translateY)
.fontWeight(FontWeight.Bold).margin(15)
Text('旋转角度:' + this.rotateC)
.fontWeight(FontWeight.Bold).margin(15)
Text('水平翻转:' + this.flipX)
.fontWeight(FontWeight.Bold).margin(15)
Text('垂直翻转:' + this.flipY)
.fontWeight(FontWeight.Bold).margin(15)
Text('截取宽度:' + this.regionW)
.fontWeight(FontWeight.Bold).margin(15)
Text('截取高度:' + this.regionH)
.fontWeight(FontWeight.Bold).margin(15)
Text('截取X坐标:' + this.regionX)
.fontWeight(FontWeight.Bold).margin(15)
Text('截取Y坐标:' + this.regionY)
.fontWeight(FontWeight.Bold).margin(15)
Text('透明度:' + this.op)
.fontWeight(FontWeight.Bold).margin(15)
}
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
TextInput({ placeholder: '缩放参数X' })
.type(InputType.Normal)
.placeholderColor(Color.Gray)
.placeholderFont({ size: 12 })
.onChange((value: string) => {
this.scaleX = value
})
TextInput({ placeholder: '缩放参数Y' })
.type(InputType.Normal)
.placeholderColor(Color.Gray)
.placeholderFont({ size: 12 })
.onChange((value: string) => {
this.scaleY = value
})
TextInput({ placeholder: '平移参数X' })
.type(InputType.Normal)
.placeholderColor(Color.Gray)
.placeholderFont({ size: 12 })
.onChange((value: string) => {
this.translateX = value
})
TextInput({ placeholder: '平移参数Y' })
.type(InputType.Normal)
.placeholderColor(Color.Gray)
.placeholderFont({ size: 12 })
.onChange((value: string) => {
this.translateY = value
})
TextInput({ placeholder: '旋转角度' })
.type(InputType.Normal)
.placeholderColor(Color.Gray)
.placeholderFont({ size: 12 })
.onChange((value: string) => {
this.rotateC = value
})
Text('水平翻转'+this.flipX).onClick(()=>{
this.flipX = !this.flipX
}).border({width:1, color:Color.Gray, radius:5}).textAlign(TextAlign.Center).width(500)
Text('垂直翻转'+this.flipY).onClick(()=>{
this.flipY = !this.flipY
}).border({width:1, color:Color.Gray, radius:5}).textAlign(TextAlign.Center).width(500)
TextInput({ placeholder: '截取宽度' })
.type(InputType.Normal)
.placeholderColor(Color.Gray)
.placeholderFont({ size: 12 })
.onChange((value: string) => {
this.regionW = value
})
TextInput({ placeholder: '截取高度' })
.type(InputType.Normal)
.placeholderColor(Color.Gray)
.placeholderFont({ size: 12 })
.onChange((value: string) => {
this.regionH = value
})
TextInput({ placeholder: '截取X坐标' })
.type(InputType.Normal)
.placeholderColor(Color.Gray)
.placeholderFont({ size: 12 })
.onChange((value: string) => {
this.regionX = value
})
TextInput({ placeholder: '截取Y坐标' })
.type(InputType.Normal)
.placeholderColor(Color.Gray)
.placeholderFont({ size: 12 })
.onChange((value: string) => {
this.regionY = value
})
TextInput({ placeholder: '透明度' })
.type(InputType.Normal)
.placeholderColor(Color.Gray)
.placeholderFont({ size: 12 })
.onChange((value: string) => {
this.op = value
})
}
Button('提交').onClick(() => {
this.btn()
}).height('10%')
.width('15%')
Flex({ justifyContent: FlexAlign.SpaceAround }) {
Image($r("app.media.opacity"))
.border({ width: 1, color: Color.Blue })
.width(500)
.height(500)
.objectFit(ImageFit.None)
Image(this._pixelMap).border({ width: 1, color: Color.Blue }).width(500).height(500).objectFit(ImageFit.None)
.backgroundColor(Color.Red)
}
}
.width('100%')
}
.height('100%')
}
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,84 @@
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// @ts-nocheck
import router from '@ohos.router';
import multimedia_image from '@ohos.multimedia.image';
import resourceManager from '@ohos.resourceManager';
@Entry
@Component
struct Index1 {
@State imgSource: multimedia_image.ImageSource = undefined
@State _pixelMap: multimedia_image.PixelMap = undefined
aboutToAppear() {
this.imgSource = multimedia_image.createImageSource('resources/base/media/2.png')
if (this.imgSource == undefined) {
console.info('q_y createImageSource error')
}
}
btn() {
let decodingOptions = {
editable: true,
desiredPixelFormat: 3
}
this.imgSource.createPixelMap(decodingOptions).then(async (pixelMap) => {
this._pixelMap = pixelMap
}).catch(error => {
this.error = error
console.log('q_y pixelMap error' + error);
})
}
build() {
Row() {
Column() {
Button('提交').onClick(() => {
this.btn()
}).height('10%')
.width('15%')
Flex({ justifyContent: FlexAlign.SpaceAround }) {
Image($r("app.media.2"))
.border({ width: 1, color: Color.Blue })
.width(500)
.height(500)
.objectFit(ImageFit.None)
Image(this._pixelMap).border({ width: 1, color: Color.Blue }).width(500).height(500).objectFit(ImageFit.None).backgroundColor(Color.Red)
}
Button() {
Text('Back')
.fontSize(25)
.fontWeight(FontWeight.Bold)
}
.type(ButtonType.Capsule)
.margin({
top: 20
})
.backgroundColor('#0D9FFB')
.width('40%')
.height('5%')
// 返回按钮绑定onClick事件,点击按钮时返回到第一页
.onClick(() => {
router.back()
})
}
.width('100%')
}
.height('100%')
}
}
@@ -0,0 +1,8 @@
{
"color": [
{
"name": "white",
"value": "#FFFFFF"
}
]
}
@@ -0,0 +1,52 @@
{
"string": [
{
"name": "MainAbility_label",
"value": "eTSMultiMedia"
},
{
"name": "MainAbility_desc",
"value": "eTSMultiMedia Ability"
},
{
"name": "entry_desc",
"value": "eTSMultiMedia Ability"
},
{
"name": "delete_file",
"value": "Delete this file?"
},
{
"name": "rename_file",
"value": "Rename this file"
},
{
"name": "yes",
"value": "OK"
},
{
"name": "cancel",
"value": "Cancel"
},
{
"name": "save",
"value": "Save"
},
{
"name": "rename_placeholder",
"value": "Input new name"
},
{
"name": "photo",
"value": "Photo"
},
{
"name": "video",
"value": "Video"
},
{
"name": "album_empty",
"value": "The album is empty"
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg viewBox="0 0 76 76" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 63.1 (92452) - https://sketch.com -->
<title>ic/camera/shutter/take_photo_normal</title>
<desc>Created with Sketch.</desc>
<g id="ic/camera/shutter/take_photo_normal" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M38,0 C58.9868205,0 76,17.0131795 76,38 C76,58.9868205 58.9868205,76 38,76 C17.0131795,76 0,58.9868205 0,38 C0,17.0131795 17.0131795,0 38,0 Z M38,1 C17.5654643,1 1,17.5654643 1,38 C1,58.4345357 17.5654643,75 38,75 C58.4345357,75 75,58.4345357 75,38 C75,17.5654643 58.4345357,1 38,1 Z M38,11 C52.9116882,11 65,23.0883118 65,38 C65,52.9116882 52.9116882,65 38,65 C23.0883118,65 11,52.9116882 11,38 C11,23.0883118 23.0883118,11 38,11 Z" id="take_photo_normal" fill="#FFFFFF"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 947 B

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg viewBox="0 0 76 76" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 63.1 (92452) - https://sketch.com -->
<title>ic/camera/shutter/take_video_normal</title>
<desc>Created with Sketch.</desc>
<g id="ic/camera/shutter/take_video_normal" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M38,0 C58.9868205,0 76,17.0131795 76,38 C76,58.9868205 58.9868205,76 38,76 C17.0131795,76 0,58.9868205 0,38 C0,17.0131795 17.0131795,0 38,0 Z M38,1 C17.5654643,1 1,17.5654643 1,38 C1,58.4345357 17.5654643,75 38,75 C58.4345357,75 75,58.4345357 75,38 C75,17.5654643 58.4345357,1 38,1 Z M38,11 C52.9116882,11 65,23.0883118 65,38 C65,52.9116882 52.9116882,65 38,65 C23.0883118,65 11,52.9116882 11,38 C11,23.0883118 23.0883118,11 38,11 Z" id="Combined-Shape" fill="#FFFFFF"></path>
<circle id="Oval-4-Copy-2" fill="#FF0000" cx="38" cy="38" r="9"></circle>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg viewBox="0 0 76 76" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 63.1 (92452) - https://sketch.com -->
<title>ic/camera/shutter/take_video_stop</title>
<desc>Created with Sketch.</desc>
<g id="ic/camera/shutter/take_video_stop" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<rect id="Rectangle-11" fill="#FFFFFF" x="27" y="27" width="22" height="22" rx="2"></rect>
<path d="M38,76 C17.0131795,76 0,58.9868205 0,38 C0,17.0131795 17.0131795,0 38,0 C58.9868205,0 76,17.0131795 76,38 C76,58.9868205 58.9868205,76 38,76 Z M38,75 C58.4345357,75 75,58.4345357 75,38 C75,17.5654643 58.4345357,1 38,1 C17.5654643,1 1,17.5654643 1,38 C1,58.4345357 17.5654643,75 38,75 Z" id="Oval" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 903 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

@@ -0,0 +1,68 @@
{
"app": {
"bundleName": "com.example.myapplication",
"vendor": "example",
"version": {
"code": 1000000,
"name": "1.0.0"
}
},
"deviceConfig": {},
"module": {
"package": "com.example.entry_test",
"name": ".entry_test",
"mainAbility": ".TestAbility",
"srcPath": "",
"deviceType": [
"default",
"tablet"
],
"distro": {
"deliveryWithInstall": true,
"moduleName": "entry_test",
"moduleType": "feature",
"installationFree": false
},
"abilities": [
{
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
],
"orientation": "unspecified",
"visible": true,
"srcPath": "TestAbility",
"name": ".TestAbility",
"srcLanguage": "ets",
"icon": "$media:icon",
"description": "$string:description_TestAbility",
"formsEnabled": false,
"label": "$string:entry_TestAbility",
"type": "page",
"launchType": "standard"
}
],
"js": [
{
"mode": {
"syntax": "ets",
"type": "pageAbility"
},
"pages": [
"pages/index"
],
"name": ".TestAbility",
"window": {
"designWidth": 720,
"autoDesignWidth": false
}
}
]
}
}
@@ -0,0 +1,33 @@
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry'
import { Hypium } from '@ohos/hypium'
import testsuite from '../test/List.test'
export default {
onCreate() {
console.info('Application onCreate')
var abilityDelegator: any
abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
var abilityDelegatorArguments: any
abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments()
console.info('start run testcase!!!')
Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite)
},
onDestroy() {
console.info('Application onDestroy')
},
}
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import router from '@system.router';
@Entry
@Component
struct Index {
aboutToAppear() {
console.info('TestAbility index aboutToAppear')
}
@State message: string = 'Hello World'
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
Button() {
Text('next page')
.fontSize(20)
.fontWeight(FontWeight.Bold)
}.type(ButtonType.Capsule)
.margin({
top: 20
})
.backgroundColor('#0D9FFB')
.width('35%')
.height('5%')
.onClick(()=>{
})
}
.width('100%')
}
.height('100%')
}
}
@@ -0,0 +1,83 @@
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import TestRunner from '@ohos.application.testRunner'
import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry'
var abilityDelegator = undefined
var abilityDelegatorArguments = undefined
function translateParamsToString(parameters) {
const keySet = new Set([
'-s class', '-s notClass', '-s suite', '-s itName',
'-s level', '-s testType', '-s size', '-s timeout',
'-s package', '-s dryRun'
])
let targetParams = '';
for (const key in parameters) {
if (keySet.has(key)) {
targetParams += ' ' + key + ' ' + parameters[key]
}
}
return targetParams.trim()
}
async function onAbilityCreateCallback() {
console.log('onAbilityCreateCallback');
}
async function addAbilityMonitorCallback(err: any) {
console.info('addAbilityMonitorCallback : ' + JSON.stringify(err))
}
export default class OpenHarmonyTestRunner implements TestRunner {
constructor() {
}
onPrepare() {
console.info('OpenHarmonyTestRunner OnPrepare')
}
onRun() {
console.log('OpenHarmonyTestRunner onRun run')
abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments()
abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
let lMonitor = {
abilityName: testAbilityName,
onAbilityCreate: onAbilityCreateCallback,
};
var testAbilityName = abilityDelegatorArguments.parameters['-p'] + '.TestAbility'
abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback)
var cmd = 'aa start -d 0 -a ' + testAbilityName + ' -b ' + abilityDelegatorArguments.bundleName
cmd += ' '+translateParamsToString(abilityDelegatorArguments.parameters)
var debug = abilityDelegatorArguments.parameters["-D"]
if (debug == 'true')
{
cmd += ' -D'
}
console.info('cmd : '+cmd)
abilityDelegator.executeShellCommand(cmd,
(err: any, d: any) => {
console.info('executeShellCommand : err : ' + JSON.stringify(err));
console.info('executeShellCommand : data : ' + d.stdResult);
console.info('executeShellCommand : data : ' + d.exitCode);
})
console.info('OpenHarmonyTestRunner onRun call abilityDelegator.getAppContext')
var context = abilityDelegator.getAppContext()
console.info('getAppContext : ' + JSON.stringify(context))
console.info('OpenHarmonyTestRunner onRun end')
}
};
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'
export default function abilityTest() {
describe('ActsAbilityTest', function () {
it('assertContain',0, function () {
console.info("it begin")
let a = 'abc'
let b = 'b'
expect(a).assertContain(b)
expect(a).assertEqual(a)
})
})
}
@@ -0,0 +1,20 @@
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import abilityTest from './Ability.test'
export default function testsuite() {
abilityTest()
}
@@ -0,0 +1,12 @@
{
"string": [
{
"name": "description_TestAbility",
"value": "eTS_Empty Ability"
},
{
"name": "entry_TestAbility",
"value": "entry_TestAbility"
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

@@ -0,0 +1,2 @@
// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently.
module.exports = require('@ohos/hvigor-ohos-plugin').legacyAppTasks
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,18 @@
{
"license":"ISC",
"devDependencies":{},
"name":"myapplication",
"ohos":{
"org":"huawei",
"directoryLevel":"project",
"buildTool":"hvigor"
},
"description":"example description",
"repository":{},
"version":"1.0.0",
"dependencies":{
"@ohos/hypium":"1.0.1",
"@ohos/hvigor-ohos-plugin":"1.1.6",
"@ohos/hvigor":"1.1.6"
}
}
@@ -0,0 +1,12 @@
{
"totalTime": 736938600,
"moduleNum": 1,
"taskTime": {
"sdkDirInit": 4672100,
"compileETS": 0,
"compileJS": 0,
"compileResource": 0,
"packageHap": 0,
"signHap": 0
}
}
@@ -0,0 +1,15 @@
{
"BuildOptions":{
"SELECT_BUILD_TARGET":"default",
"BUILD_PATH":{
"OUTPUT_PATH":"C:\\Users\\qiyi\\Desktop\\code\\app_samples\\media\\MultiMedia\\entry\\build\\default\\outputs\\default",
"RES_PATH":"C:\\Users\\qiyi\\Desktop\\code\\app_samples\\media\\MultiMedia\\entry\\build\\default\\intermediates\\res\\default",
"ETS_SUPER_VISUAL_PATH":"C:\\Users\\qiyi\\Desktop\\code\\app_samples\\media\\MultiMedia\\entry\\build\\default\\cache\\default\\CompileETS",
"JS_ASSETS_PATH":"C:\\Users\\qiyi\\Desktop\\code\\app_samples\\media\\MultiMedia\\entry\\build\\default\\intermediates\\assets\\default",
"RES_PROFILE_PATH":"C:\\Users\\qiyi\\Desktop\\code\\app_samples\\media\\MultiMedia\\entry\\build\\default\\intermediates\\res\\default\\resources\\base\\profile",
"WORKER_LOADER":"C:\\Users\\qiyi\\Desktop\\code\\app_samples\\media\\MultiMedia\\entry\\build\\default\\intermediates\\loader\\default\\loader.json",
"MANIFEST_JSON":"C:\\Users\\qiyi\\Desktop\\code\\app_samples\\media\\MultiMedia\\entry\\build\\default\\intermediates\\manifest\\default",
"JS_SUPER_VISUAL_PATH":"C:\\Users\\qiyi\\Desktop\\code\\app_samples\\media\\MultiMedia\\entry\\build\\default\\cache\\default\\CompileJS"
}
}
}
@@ -0,0 +1,12 @@
{
"BuildOptions":{
"BUNDLE_NAME":"ohos.samples.multimedia",
"BUILD_PATH":{
"OUTPUT_PATH":"C:\\Users\\qiyi\\Desktop\\code\\app_samples\\media\\MultiMedia\\build\\outputs\\default"
},
"SELECT_BUILD_PRODUCT":"default"
},
"CommonInfo":{
"project.ide.version":"3.0.0.991"
}
}
@@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/build" />
<excludeFolder url="file://$MODULE_DIR$/node_modules" />
<excludeFolder url="file://$MODULE_DIR$/entry/build" />
<excludeFolder url="file://$MODULE_DIR$/entry/node_modules" />
<excludeFolder url="file://$MODULE_DIR$/entry/.cxx" />
<excludeFolder url="file://$MODULE_DIR$/entry/.preview" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module-library">
<library name="eTS-3.2.5.5" type="ArkUI">
<CLASSES />
<JAVADOC />
<SOURCES>
<root url="file://C:/Dev/ets/3.2.5.5/api" />
<root url="file://C:/Dev/ets/3.2.5.5/component" />
</SOURCES>
</library>
</orderEntry>
</component>
</module>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ConfigurationPersistentSettings">
<settings>
<entry configurationName="entry" moduleName="entry" />
</settings>
</component>
</project>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/MultiMedia.iml" filepath="$PROJECT_DIR$/.idea/MultiMedia.iml" />
</modules>
</component>
</project>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
</component>
</project>
@@ -0,0 +1,26 @@
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
{
"app": {
"bundleName": "ohos.samples.multimedia",
"vendor": "samples",
"versionCode": 1000000,
"versionName": "1.0.0",
"icon": "$media:app_icon",
"label": "$string:app_name",
"distributedNotificationEnabled": true
}
}
@@ -0,0 +1,8 @@
{
"string": [
{
"name": "app_name",
"value": "MultiMedia"
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

@@ -0,0 +1,23 @@
# Multimedia - Camera and Media Library
### Introduction
This demo shows how to invoke the camera to take photos and record videos in eTS and how to use the **MediaLibrary** APIs to add, delete, modify, and query media files.
### Usage
1. Start the demo app. After the user grants the permission, the home screen of the app displays the album information of the current device. It also listens for the album changes and updates the album information.
2. Touch **+** to display the camera, record, and text icons.
3. Touch the camera icon to enter the camera screen. By default, the camera mode is used. Touch the capture button at the bottom to take a photo. After the photo is taken, the preview image is displayed on the left at the bottom. Touch the video icon to switch to the video recording mode. Touch the button at the bottom to start video recording and touch the end button to stop recording. After the recording is complete, the video icon is displayed on the left at the bottom. Touch the system **Back** button or **Back** on the top of the page to return to the home screen.
4. Touch the record icon to enter the recording screen. Touch the **Start** button on the right to start recording. The button changes to the **Pause** button. Touch the button to pause or resume recording. Touch the **End** button on the left to stop recording and return to the home screen.
5. Touch the text icon to enter the text editing page. Enter the text content and touch **Save**. A text file is created, and then the home screen is displayed.
6. Touch the album to access the file list screen. The files in the album are displayed. The list contains the **Delete** and **Rename** buttons. You can touch a file to delete or rename it.
### Constraints
This sample can only be run on standard-system devices.
@@ -0,0 +1,46 @@
# 相机和媒体库
### 简介
此Demo展示如何在eTS中调用相机拍照和录像,以及如何使用媒体库接口进行媒体文件的增、删、改、查操作。实现效果如下:
![main](screenshots/devices/main.png)
### 相关概念
媒体库管理:媒体库管理提供接口对公共媒体资源文件进行管理,包括文件的增、删、改、查等。
相机:相机模块支持相机相关基础功能的开发,主要包括预览、拍照、录像等。。
### 相关权限
相机权限:ohos.permission.CAMERA
麦克风权限:ohos.permission.MICROPHONE
访问媒体文件地理位置信息权限:ohos.permission.MEDIA_LOCATION
读取公共媒体文件权限:ohos.permission.READ_MEDIA
读写公共媒体文件权限:ohos.permission.WRITE_MEDIA
### 使用说明
1.启动应用,在权限弹窗中授权后返回应用,首页显示当前设备的相册信息,首页监听相册变化会刷新相册列表。
2.点击 **+** 按钮,弹出相机、录音、文本文件三个图标。
3.点击**相机**图标,进入相机界面,默认是拍照模式,点击底部拍照按钮可以拍照,拍照完成会在底部左侧显示照片预览图。点击**录像**切换到录像模式,点击底部按钮开始录像,点击结束按钮结束录像,结束录像后底部左侧显示视频图标。点击系统**Back**键或界面顶部**返回**按钮返回首页。
4.点击**录音**图标进入录音界面,点击右侧**开始**按钮开始录音,按钮变为暂停按钮,点击可以暂停和继续录音,点击左侧**结束**按钮结束录音返回首页。
5.点击**文本**图标进入文本编辑界面,输入文本内容后点击**Save**按钮,会创建并写入文本文件,完成后返回首页。
6.点击相册进入文件列表界面,展示相册内的文件,列表中有**删除**和**重命名**按钮,点击可以删除文件和重命名文件。
7.安装视频播放VideoPlayer应用后,点击视频文件可以调起视频播放界面播放该视频。
### 约束与限制
1.rk3568底层录像功能有问题,暂不支持录像功能,当前拍照功能仅支持部分机型。
2.本示例仅支持标准系统上运行。
3.本示例为Stage模型,从API version 9开始支持。
4.本示例需要使用DevEco Studio 3.0 Beta3 (Build Version: 3.0.0.901, built on May 30, 2022)才可编译运行。。
@@ -0,0 +1,55 @@
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
{
"app": {
"signingConfigs": [
{
"name": "default",
"material": {
"certpath": "C:\\Users\\qiyi\\.ohos\\config\\openharmony\\auto_ohos_default.cer",
"storePassword": "0000001BDE5DC74F39C41946EA359AE73A655501525263F85501DC4C7121F8B17E3EEF188C0B98BEE1BC86",
"keyAlias": "debugKey",
"keyPassword": "0000001B1B4B41B891DB8B56BCD337F3CE102C0BB267EACD6A238D2FF9F19D8A6312581A3004F7DAEB03F7",
"profile": "C:\\Users\\qiyi\\.ohos\\config\\openharmony\\auto_ohos_default_ohos.samples.multimedia.p7b",
"signAlg": "SHA256withECDSA",
"storeFile": "C:\\Users\\qiyi\\.ohos\\config\\openharmony\\auto_ohos_default.p12"
}
}
],
"compileSdkVersion": 9,
"compatibleSdkVersion": 9,
"products": [
{
"name": "default",
"signingConfig": "default",
}
]
},
"modules": [
{
"name": "entry",
"srcPath": "./entry",
"targets": [
{
"name": "default",
"applyToProducts": [
"default"
]
}
]
}
]
}
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
{
"apiType": 'stageMode',
"buildOption": {
},
"targets": [
{
"name": "default",
},
{
"name": "ohosTest",
}
]
}
@@ -0,0 +1,2 @@
// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently.
module.exports = require('@ohos/hvigor-ohos-plugin').hapTasks
@@ -0,0 +1,5 @@
{
"name": "entry",
"version": "1.0.0",
"lockfileVersion": 1
}
@@ -0,0 +1,14 @@
{
"license": "ISC",
"devDependencies": {},
"name": "entry",
"ohos": {
"org": "huawei",
"directoryLevel": "module",
"buildTool": "hvigor"
},
"description": "example description",
"repository": {},
"version": "1.0.0",
"dependencies": {}
}
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import AbilityStage from "@ohos.application.AbilityStage"
import Logger from '../model/Logger'
export default class MyAbilityStage extends AbilityStage {
onCreate() {
Logger.info('MyAbilityStage', 'onCreate')
}
}
@@ -0,0 +1,51 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import Ability from '@ohos.application.Ability'
import Logger from '../model/Logger'
const TAG: string = 'MainAbility'
export default class MainAbility extends Ability {
onCreate(want, launchParam) {
Logger.info(TAG, 'MainAbility onCreate')
globalThis.abilityWant = want
globalThis.abilityContext = this.context
}
onDestroy() {
Logger.info(TAG, 'MainAbility onDestroy')
}
onWindowStageCreate(windowStage) {
// Main window is created, set main page for this ability
Logger.info(TAG, 'MainAbility onWindowStageCreate')
windowStage.setUIContent(this.context, "pages/Index", null)
}
onWindowStageDestroy() {
// Main window is destroyed, release UI related resources
Logger.info(TAG, 'MainAbility onWindowStageDestroy')
}
onForeground() {
// Ability has brought to foreground
Logger.info(TAG, 'MainAbility onForeground')
}
onBackground() {
// Ability has back to background
Logger.info(TAG, 'MainAbility onBackground')
}
};
@@ -0,0 +1,276 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import camera from '@ohos.multimedia.camera'
import fileio from '@ohos.fileio'
import image from '@ohos.multimedia.image'
import media from '@ohos.multimedia.media'
import mediaLibrary from '@ohos.multimedia.mediaLibrary'
import Logger from '../model/Logger'
import MediaUtils from '../model/MediaUtils'
const CameraMode = {
MODE_PHOTO: 0, // 拍照模式
MODE_VIDEO: 1 // 录像模式
}
const CameraSize = {
WIDTH: 1920,
HEIGHT: 1080
}
class CameraService {
private tag: string = 'CameraService'
private static instance: CameraService = new CameraService()
private mediaUtil = MediaUtils.getInstance()
private cameraManager: camera.CameraManager = undefined
private cameras: Array<camera.Camera> = undefined
private cameraId: string = ''
private cameraInput: camera.CameraInput = undefined
private previewOutput: camera.PreviewOutput = undefined
private photoOutPut: camera.PhotoOutput = undefined
private captureSession: camera.CaptureSession = undefined
private mReceiver: image.ImageReceiver = undefined
private photoUri: string = ''
private fileAsset: mediaLibrary.FileAsset = undefined
private fd: number = -1
private curMode = CameraMode.MODE_PHOTO
private handleTakePicture: (photoUri: string) => void = undefined
constructor() {
Logger.info(this.tag, 'q_y1 createImageReceiver')
this.mReceiver = image.createImageReceiver(CameraSize.WIDTH, CameraSize.HEIGHT, 4, 8)
Logger.info(this.tag, 'q_y1 createImageReceiver')
this.mReceiver.on('imageArrival', () => {
Logger.info(this.tag, 'q_y2 imageArrival')
//// 从ImageReceiver读取最新的图片,并使用callback返回结果。 success
// this.mReceiver.readLatestImage((err, image) => {
// Logger.info(this.tag, 'q_y3 readLatestImage')
// if (err || image === undefined) {
// Logger.error(this.tag, 'q_y4 failed to get valid image')
// return
// }
// image.getComponent(4, (errMsg, img) => {
// Logger.info(this.tag, 'q_y5 getComponent')
// if (errMsg || img === undefined) {
// Logger.info(this.tag, 'q_y6 failed to get valid buffer')
// return
// }
// let buffer = new ArrayBuffer(4096)
// if (img.byteBuffer) {
// buffer = img.byteBuffer
// } else {
// Logger.error(this.tag, ' q_y7 img.byteBuffer is undefined')
// }
// this.savePicture(buffer, image)
// })
// })
//// 从ImageReceiver读取最新的图片,并使用promise返回结果。 success
// this.mReceiver.readLatestImage().then(image => {
// Logger.info(this.tag, 'q_y8 readLatestImage')
// if (image === undefined) {
// Logger.error(this.tag, 'q_y9 failed to get valid image')
// return
// }
// image.getComponent(4, (errMsg, img) => {
// Logger.info(this.tag, 'q_y10 getComponent')
// if (errMsg || img === undefined) {
// Logger.info(this.tag, 'q_y11 failed to get valid buffer')
// return
// }
// let buffer = new ArrayBuffer(4096)
// if (img.byteBuffer) {
// buffer = img.byteBuffer
// } else {
// Logger.error(this.tag, ' q_y12 img.byteBuffer is undefined')
// }
// this.savePicture(buffer, image)
// })
// }).catch(error => {
// Logger.info('q_y13 readLatestImage failed.');
// })
// 从ImageReceiver读取下一张图片,并使用callback返回结果。 success
// this.mReceiver.readNextImage((err, image) => {
// Logger.info(this.tag, 'q_y14 readNextImage')
// if (err || image === undefined) {
// Logger.error(this.tag, 'q_y15 failed to get valid image')
// return
// }
// image.getComponent(4, (errMsg, img) => {
// Logger.info(this.tag, 'q_y16 getComponent')
// if (errMsg || img === undefined) {
// Logger.info(this.tag, 'q_y17 failed to get valid buffer')
// return
// }
// let buffer = new ArrayBuffer(4096)
// if (img.byteBuffer) {
// buffer = img.byteBuffer
// } else {
// Logger.error(this.tag, ' q_y18 img.byteBuffer is undefined')
// }
// this.savePicture(buffer, image)
// })
// })
// 从ImageReceiver读取下一张图片,并使用callback返回结果。
this.mReceiver.readNextImage().then(image => {
Logger.info(this.tag, 'q_y19 readNextImage')
if (image === undefined) {
Logger.error(this.tag, 'q_y20 failed to get valid image')
return
}
image.getComponent(4, (errMsg, img) => {
Logger.info(this.tag, 'q_y21 getComponent')
if (errMsg || img === undefined) {
Logger.info(this.tag, 'q_y22 failed to get valid buffer')
return
}
let buffer = new ArrayBuffer(4096)
if (img.byteBuffer) {
buffer = img.byteBuffer
} else {
Logger.error(this.tag, ' q_y23 img.byteBuffer is undefined')
}
this.savePicture(buffer, image)
})
}).catch(error => {
console.log('q_y24 readNextImage failed.');
})
// 用于获取一个surface id供Camera或其他组件使用。使用callback返回结果。 success
this.mReceiver.getReceivingSurfaceId((err, id) => {
if(err) {
Logger.error('q_y25 getReceivingSurfaceId failed.')
} else {
Logger.info('q_y26 getReceivingSurfaceId succeeded and id is ' + id)
}
})
// // 用于获取一个surface id供Camera或其他组件使用。使用promise返回结果。 success
// this.mReceiver.getReceivingSurfaceId().then( id => {
// Logger.info('q_y27 getReceivingSurfaceId succeeded and id is ' + id)
// }).catch(error => {
// Logger.error('q_y28 getReceivingSurfaceId failed.')
// })
})
// 释放ImageReceiver实例并使用promise返回结果. success
// this.mReceiver.release().then(() => {
// Logger.info('q_y29 release succeeded.');
// }).catch(error => {
// Logger.error('q_y30 release failed.');
// })
// 释放ImageReceiver实例并使用callback返回结果. success
// this.mReceiver.release(() => {
// Logger.info('q_y31 release succeeded.');
// })
}
async savePicture(buffer: ArrayBuffer, img: image.Image) {
Logger.info(this.tag, 'savePicture')
this.fileAsset = await this.mediaUtil.createAndGetUri(mediaLibrary.MediaType.IMAGE)
this.photoUri = this.fileAsset.uri
Logger.info(this.tag, `this.photoUri = ${this.photoUri}`)
this.fd = await this.mediaUtil.getFdPath(this.fileAsset)
Logger.info(this.tag, `this.fd = ${this.fd}`)
await fileio.write(this.fd, buffer)
await this.fileAsset.close(this.fd)
await img.release()
Logger.info(this.tag, 'save image done')
if (this.handleTakePicture) {
this.handleTakePicture(this.photoUri)
}
}
async initCamera(surfaceId: number) {
Logger.info(this.tag, 'initCamera')
if (this.curMode === CameraMode.MODE_VIDEO) {
await this.releaseCamera()
this.curMode = CameraMode.MODE_PHOTO
}
this.cameraManager = await camera.getCameraManager(globalThis.abilityContext)
Logger.info(this.tag, 'getCameraManager')
this.cameras = await this.cameraManager.getCameras()
Logger.info(this.tag, `get cameras ${this.cameras.length}`)
if (this.cameras.length === 0) {
Logger.info(this.tag, 'cannot get cameras')
return
}
this.cameraId = this.cameras[0].cameraId
this.cameraInput = await this.cameraManager.createCameraInput(this.cameraId)
Logger.info(this.tag, 'createCameraInput')
this.previewOutput = await camera.createPreviewOutput(surfaceId.toString())
Logger.info(this.tag, 'createPreviewOutput')
let mSurfaceId = await this.mReceiver.getReceivingSurfaceId()
this.photoOutPut = await camera.createPhotoOutput(mSurfaceId)
this.captureSession = await camera.createCaptureSession(globalThis.abilityContext)
Logger.info(this.tag, 'createCaptureSession')
await this.captureSession.beginConfig()
Logger.info(this.tag, 'beginConfig')
await this.captureSession.addInput(this.cameraInput)
await this.captureSession.addOutput(this.previewOutput)
await this.captureSession.addOutput(this.photoOutPut)
await this.captureSession.commitConfig()
await this.captureSession.start()
Logger.info(this.tag, 'captureSession start')
}
setTakePictureCallback(callback) {
this.handleTakePicture = callback
}
async takePicture() {
Logger.info(this.tag, 'takePicture')
if (this.curMode === CameraMode.MODE_VIDEO) {
this.curMode = CameraMode.MODE_PHOTO
}
let photoSettings = {
rotation: camera.ImageRotation.ROTATION_0,
quality: camera.QualityLevel.QUALITY_LEVEL_MEDIUM,
location: { // 位置信息,经纬度
latitude: 12.9698,
longitude: 77.7500,
altitude: 1000
},
mirror: false
}
await this.photoOutPut.capture(photoSettings)
Logger.info(this.tag, 'takePicture done')
}
async releaseCamera() {
Logger.info(this.tag, 'releaseCamera')
await this.captureSession.stop()
if (this.cameraInput) {
await this.cameraInput.release()
}
if (this.previewOutput) {
await this.previewOutput.release()
}
if (this.photoOutPut) {
await this.photoOutPut.release()
}
await this.cameraInput.release()
await this.captureSession.release()
}
}
export default new CameraService()
@@ -0,0 +1,64 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file 日期工具
*/
export default class DateTimeUtil {
/**
* 时分秒
*/
getTime() {
const DATETIME = new Date()
return this.concatTime(DATETIME.getHours(), DATETIME.getMinutes(), DATETIME.getSeconds())
}
/**
* 年月日
*/
getDate() {
const DATETIME = new Date()
return this.concatDate(DATETIME.getFullYear(), DATETIME.getMonth() + 1, DATETIME.getDate())
}
/**
* 日期不足两位补充0
* @param value-数据值
*/
fill(value: number) {
return (value > 9 ? '' : '0') + value
}
/**
* 年月日格式修饰
* @param year
* @param month
* @param date
*/
concatDate(year: number, month: number, date: number) {
return `${year}${this.fill(month)}${this.fill(date)}`
}
/**
* 时分秒格式修饰
* @param hours
* @param minutes
* @param seconds
*/
concatTime(hours: number, minutes: number, seconds: number) {
return `${this.fill(hours)}${this.fill(minutes)}${this.fill(seconds)}`
}
}
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import hilog from '@ohos.hilog'
class Logger {
private domain: number
private prefix: string
private format: string = "%{public}s, %{public}s"
constructor(prefix: string) {
this.prefix = prefix
this.domain = 0xFF00
}
debug(...args: any[]) {
hilog.debug(this.domain, this.prefix, this.format, args)
}
info(...args: any[]) {
hilog.info(this.domain, this.prefix, this.format, args)
}
warn(...args: any[]) {
hilog.warn(this.domain, this.prefix, this.format, args)
}
error(...args: any[]) {
hilog.error(this.domain, this.prefix, this.format, args)
}
}
export default new Logger('[MultiMedia]')
@@ -0,0 +1,179 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import mediaLibrary from '@ohos.multimedia.mediaLibrary'
import DateTimeUtil from '../model/DateTimeUtil'
import Logger from '../model/Logger'
export default class MediaUtils {
private tag: string = 'MediaUtils'
private mediaTest: mediaLibrary.MediaLibrary = mediaLibrary.getMediaLibrary(globalThis.abilityContext)
private static instance: MediaUtils = new MediaUtils()
public static getInstance() {
if (this.instance === undefined) {
this.instance = new MediaUtils()
}
return this.instance
}
async createAndGetUri(mediaType: number) {
let info = this.getInfoFromType(mediaType)
let dateTimeUtil = new DateTimeUtil()
let name = `${dateTimeUtil.getDate()}_${dateTimeUtil.getTime()}`
let displayName = `${info.prefix}${name}${info.suffix}`
Logger.info(this.tag, `displayName = ${displayName},mediaType = ${mediaType}`)
let publicPath = await this.mediaTest.getPublicDirectory(info.directory)
Logger.info(this.tag, `publicPath = ${publicPath}`)
return await this.mediaTest.createAsset(mediaType, displayName, publicPath)
}
async queryFile(dataUri: any) {
let fileKeyObj = mediaLibrary.FileKey
if (dataUri !== undefined) {
let args = dataUri.id.toString()
let fetchOp = {
selections: `${fileKeyObj.ID}=?`,
selectionArgs: [args],
}
const fetchFileResult = await this.mediaTest.getFileAssets(fetchOp)
Logger.info(this.tag, `fetchFileResult.getCount() = ${fetchFileResult.getCount()}`)
const fileAsset = await fetchFileResult.getAllObject()
return fileAsset[0]
}
}
async getFdPath(fileAsset: any) {
let fd = await fileAsset.open('Rw')
Logger.info(this.tag, `fd = ${fd}`)
return fd
}
async createFile(mediaType: number) {
let dataUri = await this.createAndGetUri(mediaType)
if (dataUri) {
let fileAsset = await this.queryFile(dataUri)
if (fileAsset) {
let fd = await this.getFdPath(fileAsset)
return fd
}
}
}
async getFileAssetsFromType(mediaType: number) {
Logger.info(this.tag, `getFileAssetsFromType,mediaType = ${mediaType}`)
let fileKeyObj = mediaLibrary.FileKey
let fetchOp = {
selections: `${fileKeyObj.MEDIA_TYPE}=?`,
selectionArgs: [`${mediaType}`],
}
const fetchFileResult = await this.mediaTest.getFileAssets(fetchOp)
Logger.info(this.tag, `getFileAssetsFromType,fetchFileResult.count = ${fetchFileResult.getCount()}`)
let fileAssets = []
if (fetchFileResult.getCount() > 0) {
fileAssets = await fetchFileResult.getAllObject()
}
return fileAssets
}
async getAlbums() {
Logger.info(this.tag, 'getAlbums begin')
let albums = []
const [ files, images, videos, audios ] = await Promise.all([
this.getFileAssetsFromType(mediaLibrary.MediaType.FILE),
this.getFileAssetsFromType(mediaLibrary.MediaType.IMAGE),
this.getFileAssetsFromType(mediaLibrary.MediaType.VIDEO),
this.getFileAssetsFromType(mediaLibrary.MediaType.AUDIO)
])
albums.push({
albumName: 'Documents', count: files.length, mediaType: mediaLibrary.MediaType.FILE
})
albums.push({
albumName: 'Pictures', count: images.length, mediaType: mediaLibrary.MediaType.IMAGE
})
albums.push({
albumName: 'Videos', count: videos.length, mediaType: mediaLibrary.MediaType.VIDEO
})
albums.push({
albumName: 'Audios', count: audios.length, mediaType: mediaLibrary.MediaType.AUDIO
})
return albums
}
deleteFile(media: any) {
let uri = media.uri
Logger.info(this.tag, `deleteFile,uri = ${uri}`)
return this.mediaTest.deleteAsset(uri)
}
onDateChange(callback: () => void) {
this.mediaTest.on('albumChange', () => {
Logger.info(this.tag, 'albumChange called')
callback()
})
this.mediaTest.on('imageChange', () => {
Logger.info(this.tag, 'imageChange called')
callback()
})
this.mediaTest.on('audioChange', () => {
Logger.info(this.tag, 'audioChange called')
callback()
})
this.mediaTest.on('videoChange', () => {
Logger.info(this.tag, 'videoChange called')
callback()
})
this.mediaTest.on('fileChange', () => {
Logger.info(this.tag, 'fileChange called')
callback()
})
}
offDateChange() {
this.mediaTest.off('albumChange')
this.mediaTest.off('imageChange')
this.mediaTest.off('audioChange')
this.mediaTest.off('videoChange')
this.mediaTest.off('fileChange')
}
getInfoFromType(mediaType: number) {
let result = {
prefix: '', suffix: '', directory: 0
}
switch (mediaType) {
case mediaLibrary.MediaType.FILE:
result.prefix = 'FILE_'
result.suffix = '.txt'
result.directory = mediaLibrary.DirectoryType.DIR_DOCUMENTS
break
case mediaLibrary.MediaType.IMAGE:
result.prefix = 'IMG_'
result.suffix = '.jpg'
result.directory = mediaLibrary.DirectoryType.DIR_IMAGE
break
case mediaLibrary.MediaType.VIDEO:
result.prefix = 'VID_'
result.suffix = '.mp4'
result.directory = mediaLibrary.DirectoryType.DIR_VIDEO
break
case mediaLibrary.MediaType.AUDIO:
result.prefix = 'AUD_'
result.suffix = '.wav'
result.directory = mediaLibrary.DirectoryType.DIR_AUDIO
break
}
return result
}
}
@@ -0,0 +1,142 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import prompt from '@ohos.prompt'
import Logger from '../model/Logger'
import CameraService from '../model/CameraService'
//import TitleBar from '../view/TitleBar'
const CameraMode = {
MODE_PHOTO: 0, // 拍照模式
MODE_VIDEO: 1 // 录像模式
}
@Entry
@Component
struct CameraPage {
private tag: string = 'CameraPage'
private mXComponentController: XComponentController = new XComponentController()
private surfaceId: number
@State imgThumbnail: string = ''
@State videoThumbnail: Resource | undefined = undefined
@State curModel: number = CameraMode.MODE_PHOTO
@State isRecording: boolean = false
aboutToAppear() {
this.surfaceId = this.mXComponentController.getXComponentSurfaceId()
Logger.info(this.tag, `aboutToAppear,surfaceId=${this.surfaceId}`)
CameraService.setTakePictureCallback(this.handleTakePicture.bind(this))
}
getCameraIcon() {
if (this.curModel === CameraMode.MODE_PHOTO) {
return $r('app.media.take_photo_normal')
} else {
if (this.isRecording) {
return $r('app.media.take_video_stop')
} else {
return $r('app.media.take_video_normal')
}
}
}
// refreshVideoState() {
// if (this.isRecording) {
// Logger.info(this.tag, 'stopVideo begin')
//// CameraService.stopVideo()
// this.isRecording = false
// this.videoThumbnail = $r('app.media.video_poster')
// } else {
// Logger.info(this.tag, 'startVideo begin')
// CameraService.startVideo()
// this.isRecording = true
// }
// }
handleTakePicture = (thumbnail: string) => {
this.imgThumbnail = thumbnail
Logger.info(this.tag, `takePicture end , thumbnail: ${this.imgThumbnail}`)
}
build() {
Column() {
// TitleBar()
Stack({ alignContent: Alignment.Bottom }) {
XComponent({
id: 'componentId',
type: 'surface',
controller: this.mXComponentController
})
.onLoad(() => {
Logger.info(this.tag, 'onLoad is called')
this.mXComponentController.setXComponentSurfaceSize({ surfaceWidth: 1920, surfaceHeight: 1080 })
this.surfaceId = this.mXComponentController.getXComponentSurfaceId()
Logger.info(this.tag, `onLoad surfaceId: ${this.surfaceId}`)
this.curModel = CameraMode.MODE_PHOTO
CameraService.initCamera(this.surfaceId)
})
.height('100%')
.width('100%')
.margin({ bottom: 130 })
Column() {
Row() {
Text($r('app.string.photo'))
.fontColor(this.curModel === CameraMode.MODE_PHOTO ? Color.White : Color.Gray)
.fontSize(25)
}
.size({ height: 40, width: '100%' })
.margin({ left: 50 })
.justifyContent(FlexAlign.Center)
Row() {
Image(this.imgThumbnail)
.size({ width: 70, height: 70 })
.aspectRatio(1)
.borderRadius(40)
.objectFit(ImageFit.Fill)
.backgroundColor(Color.Gray)
Image(this.getCameraIcon())
.size({ width: 70, height: 70 })
.margin({ left: 50 })
.onClick(() => {
if (this.curModel === CameraMode.MODE_PHOTO) {
Logger.info(this.tag, 'takePicture begin')
prompt.showToast({ message: '拍照中...', duration: 1000 })
CameraService.takePicture()
}
})
}
.size({ height: 80, width: '100%' })
.margin({ right: 50 })
.justifyContent(FlexAlign.Center)
}
.size({ height: 130, width: '100%' })
.padding({ bottom: 10 })
.backgroundColor(Color.Black)
}
.width('100%')
.height('100%')
.layoutWeight(1)
.backgroundColor(Color.Grey)
}
.width('100%')
.height('100%')
}
async aboutToDisappear() {
await CameraService.releaseCamera()
}
}
@@ -0,0 +1,105 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import router from '@ohos.router'
import Logger from '../model/Logger'
//import TitleBar from '../view/TitleBar'
//import MediaUtils from '../model/MediaUtils'
import { MediaView } from '../view/MediaView'
export default interface Album {
albumName: string,
count: string
}
const PERMISSIONS: Array<string> = [
'ohos.permission.CAMERA',
'ohos.permission.MICROPHONE',
'ohos.permission.READ_MEDIA',
'ohos.permission.WRITE_MEDIA',
'ohos.permission.MEDIA_LOCATION']
const TAG: string = 'Index'
@Entry
@Component
struct Index {
// private mediaUtils: MediaUtils = MediaUtils.getInstance()
@State albums: Array<Album> = []
@State selectIndex: number = 0
@State operateVisible: boolean = false
// getAlbums = async () => {
// this.albums = await this.mediaUtils.getAlbums()
// }
async aboutToAppear() {
await globalThis.abilityContext.requestPermissionsFromUser(PERMISSIONS)
Logger.info(TAG, 'grantPermission,requestPermissionsFromUser')
}
onPageShow() {
// if (this.albums.length === 0) {
// this.getAlbums()
// this.mediaUtils.onDateChange(this.getAlbums)
// }
}
@Builder OperateBtn(src, zIndex, translate, handleClick) {
Button() {
Image(src)
.size({ width: '70%', height: '70%' })
}
.type(ButtonType.Circle)
.size({ width: '40%', height: '40%' })
.backgroundColor('#0D9FFB')
.zIndex(zIndex)
.translate({ x: translate.x, y: translate.y })
.transition({ type: TransitionType.Insert, translate: { x: 0, y: 0 } })
.transition({ type: TransitionType.Delete, opacity: 0 })
.onClick(handleClick)
}
build() {
Stack({ alignContent: Alignment.BottomEnd }) {
Column() {
// TitleBar()
MediaView({ albums: $albums })
}
.width('100%')
.height('100%')
Stack({ alignContent: Alignment.Center }) {
this.OperateBtn($r('app.media.add'), 1, { x: 0, y: 0 }, () => {
animateTo({ duration: 500, curve: Curve.Ease }, () => {
this.operateVisible = !this.operateVisible
})
})
if (this.operateVisible) {
this.OperateBtn($r('app.media.icon_camera'), 0, { x: 0, y: '-120%' }, () => {
this.operateVisible = !this.operateVisible
router.push({ url: 'pages/CameraPage' })
})
}
}
.size({ width: '30%', height: '30%' })
.translate({ x: 10 })
.margin({ bottom: 50 })
}
.width('100%')
.height('100%')
}
// aboutToDisappear() {
// this.mediaUtils.offDateChange()
// }
}
@@ -0,0 +1,86 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import mediaLibrary from '@ohos.multimedia.mediaLibrary'
//import { getDurationString } from '../model/TimeUtils'
@Component
export struct MediaItem {
private media: mediaLibrary.FileAsset = undefined
private index: number = 0
private btnAction: (operate: string, index: number) => void
tempNum(number) {
if (number < 10) {
return "0" + number
}
return number.toString()
}
getTimeString() {
let date = new Date()
date.setMilliseconds(this.media.dateAdded)
return `${date.getFullYear()}/${this.tempNum(date.getMonth() + 1)}/${this.tempNum(date.getDate())}`
}
//
// getImgSrc() {
// switch (this.media.mediaType) {
// case mediaLibrary.MediaType.VIDEO:
// return $r('app.media.video_poster')
// case mediaLibrary.MediaType.AUDIO:
// return $r('app.media.ic_play')
// case mediaLibrary.MediaType.FILE:
// return $r('app.media.ic_document')
// break
// default:
// return this.media.uri
// break
// }
// }
build() {
Row() {
Button({ type: ButtonType.Circle, stateEffect: true }) {
Column() {
Image($r('app.media.ic_rename'))
.objectFit(ImageFit.Contain)
.size({ width: 40, height: 40 })
}
}
.size({ width: 50, height: 50 })
.backgroundColor('#F5F5F5')
.onClick(() => {
this.btnAction('rename', this.index)
})
Button({ type: ButtonType.Circle, stateEffect: true }) {
Column() {
Image($r('app.media.ic_delete'))
.objectFit(ImageFit.Contain)
.size({ width: 40, height: 40 })
}
}
.size({ width: 50, height: 50 })
.margin({ left: 15, right: 10 })
.backgroundColor('#F5F5F5')
.onClick(() => {
this.btnAction('delete', this.index)
})
}
.padding({ top: 10, bottom: 10, left: 10, right: 10 })
.margin({ left: 15, right: 15, top: 10 })
.backgroundColor('#FFFFFF')
.borderRadius(20)
}
}
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import router from '@ohos.router'
import Album from '../pages/Index'
@Component
export struct MediaView {
@Link albums: Array<Album>
build() {
Column() {
List() {
ForEach(this.albums, (item, index) => {
ListItem() {
Row() {
Text(item.albumName)
.fontSize(25)
.fontWeight(FontWeight.Bold)
.textAlign(TextAlign.Start)
Blank()
Text(`${item.count}`)
.fontSize(25)
.fontWeight(FontWeight.Bold)
.textAlign(TextAlign.End)
}
.width('100%')
.padding(16)
.constraintSize({ minHeight: 70 })
}
.onClick(() => {
if (item.count > 0) {
router.push({
url: 'pages/AlbumPage',
params: { albumName: item.albumName, mediaType: item.mediaType }
})
} else {
AlertDialog.show(
{
title: $r('app.string.album_empty'),
message: null,
primaryButton: {
value: $r('app.string.yes'),
fontColor: Color.Red,
action: () => {
}
}
}
)
}
})
}, item => item.albumName)
}
.divider({ strokeWidth: 1, color: Color.Gray, startMargin: 16, endMargin: 16 })
.layoutWeight(1)
}
.height('100%')
.width('100%')
}
}
@@ -0,0 +1,72 @@
/*
* Copyright (C) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
{
"module": {
"name": "entry",
"type": "entry",
"srcEntrance": "./ets/Application/AbilityStage.ts",
"description": "$string:entry_desc",
"mainElement": "MainAbility",
"deviceTypes": [
"default",
"tablet"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages",
"uiSyntax": "ets",
"abilities": [
{
"name": "MainAbility",
"srcEntrance": "./ets/MainAbility/MainAbility.ts",
"description": "$string:MainAbility_desc",
"icon": "$media:icon",
"label": "$string:MainAbility_label",
"visible": true,
"launchType": "singleton",
"startWindowIcon": "$media:icon",
"startWindowBackground": "$color:white",
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
]
}
],
"requestPermissions": [
{
"name": "ohos.permission.CAMERA"
},
{
"name": "ohos.permission.MICROPHONE"
},
{
"name": "ohos.permission.MEDIA_LOCATION"
},
{
"name": "ohos.permission.WRITE_MEDIA"
},
{
"name": "ohos.permission.READ_MEDIA"
}
]
}
}
@@ -0,0 +1,8 @@
{
"color": [
{
"name": "white",
"value": "#FFFFFF"
}
]
}
@@ -0,0 +1,52 @@
{
"string": [
{
"name": "MainAbility_label",
"value": "eTSMultiMedia"
},
{
"name": "MainAbility_desc",
"value": "eTSMultiMedia Ability"
},
{
"name": "entry_desc",
"value": "eTSMultiMedia Ability"
},
{
"name": "delete_file",
"value": "Delete this file?"
},
{
"name": "rename_file",
"value": "Rename this file"
},
{
"name": "yes",
"value": "OK"
},
{
"name": "cancel",
"value": "Cancel"
},
{
"name": "save",
"value": "Save"
},
{
"name": "rename_placeholder",
"value": "Input new name"
},
{
"name": "photo",
"value": "Photo"
},
{
"name": "video",
"value": "Video"
},
{
"name": "album_empty",
"value": "The album is empty"
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg viewBox="0 0 76 76" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 63.1 (92452) - https://sketch.com -->
<title>ic/camera/shutter/take_photo_normal</title>
<desc>Created with Sketch.</desc>
<g id="ic/camera/shutter/take_photo_normal" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<path d="M38,0 C58.9868205,0 76,17.0131795 76,38 C76,58.9868205 58.9868205,76 38,76 C17.0131795,76 0,58.9868205 0,38 C0,17.0131795 17.0131795,0 38,0 Z M38,1 C17.5654643,1 1,17.5654643 1,38 C1,58.4345357 17.5654643,75 38,75 C58.4345357,75 75,58.4345357 75,38 C75,17.5654643 58.4345357,1 38,1 Z M38,11 C52.9116882,11 65,23.0883118 65,38 C65,52.9116882 52.9116882,65 38,65 C23.0883118,65 11,52.9116882 11,38 C11,23.0883118 23.0883118,11 38,11 Z" id="take_photo_normal" fill="#FFFFFF"></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 947 B

Some files were not shown because too many files have changed in this diff Show More