diff --git a/README.en.md b/README.en.md index e0796075c4f809803996feedceea6955cc280146..3daaaf2870d08b0eeaab371a8f81edaf337185f9 100644 --- a/README.en.md +++ b/README.en.md @@ -24,6 +24,6 @@ Learn how to edit images based on image encoding and decoding, including croppin ### Constraints 1. The sample is only supported on Huawei phones with standard systems. -2. HarmonyOS: HarmonyOS 5.0.2 Release or later. -3. DevEco Studio: DevEco Studio 5.0.2 Release or later. -4. HarmonyOS SDK: HarmonyOS 5.0.2 Release SDK or later. \ No newline at end of file +2. HarmonyOS: HarmonyOS 5.0.5 Release or later. +3. DevEco Studio: DevEco Studio 5.0.5 Release or later. +4. HarmonyOS SDK: HarmonyOS 5.0.5 Release SDK or later. \ No newline at end of file diff --git a/README.md b/README.md index 27086d79f1b42b395a33d71ce57dbb424e4d1244..4460d343a709dc049236857a8804d519de172f86 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,6 @@ ### 约束与限制 1. 本示例仅支持标准系统上运行,支持设备:华为手机。 -2. HarmonyOS系统:HarmonyOS 5.0.2 Release及以上。 -3. DevEco Studio版本:DevEco Studio 5.0.2 Release及以上。 -4. HarmonyOS SDK版本:HarmonyOS 5.0.2 Release SDK及以上。 +2. HarmonyOS系统:HarmonyOS 5.0.5 Release及以上。 +3. DevEco Studio版本:DevEco Studio 5.0.5 Release及以上。 +4. HarmonyOS SDK版本:HarmonyOS 5.0.5 Release SDK及以上。 diff --git a/build-profile.json5 b/build-profile.json5 index 7b8c01ae1bd2328bcf74106fceee1cee89bde26e..b3b0115f9d4cbe8c6d6acbf5a703f5fc47bc8d64 100644 --- a/build-profile.json5 +++ b/build-profile.json5 @@ -4,7 +4,7 @@ { "name": "default", "signingConfig": "default", - "compatibleSdkVersion": "5.0.2(14)", + "compatibleSdkVersion": "5.0.5(17)", "runtimeOS": "HarmonyOS" } ], diff --git a/entry/build-profile.json5 b/entry/build-profile.json5 index 1b201a683e8f963ca8c249344b83ae08b3cf3a25..3c6b2c85a7df0d4e47ec1e6e1cb112a3e96530a4 100644 --- a/entry/build-profile.json5 +++ b/entry/build-profile.json5 @@ -3,8 +3,7 @@ "buildOption": { "sourceOption": { "workers": [ - "./src/main/ets/workers/AdjustSaturationWork.ts", - "./src/main/ets/workers/AdjustBrightnessWork.ts" + "./src/main/ets/workers/AdjustWork.ets" ] } }, diff --git a/entry/src/main/ets/common/constant/CommonConstants.ts b/entry/src/main/ets/common/constant/CommonConstants.ts index a5e244ee58a650894fdf7c9a73c81df40e1857c7..eef0deee4cd7c02c375b47b6eea2e13ba7382884 100644 --- a/entry/src/main/ets/common/constant/CommonConstants.ts +++ b/entry/src/main/ets/common/constant/CommonConstants.ts @@ -168,16 +168,10 @@ export class CommonConstants { * Encode file permission. */ static readonly ENCODE_FILE_PERMISSION: string = 'rw'; - - /** - * Brightness worker file. - */ - static readonly BRIGHTNESS_WORKER_FILE = 'entry/ets/workers/AdjustBrightnessWork.ts'; - /** * Brightness worker file. */ - static readonly SATURATION_WORKER_FILE = 'entry/ets/workers/AdjustSaturationWork.ts'; + static readonly WORKER_FILE = 'entry/ets/workers/AdjustWork.ets'; /** * Image name. diff --git a/entry/src/main/ets/entryability/EntryAbility.ets b/entry/src/main/ets/entryability/EntryAbility.ets index bf4e047dcb290ecae7308181e69d508766abe2cb..85b513a397ee37166ca94ccc7937cd2c4f621abb 100644 --- a/entry/src/main/ets/entryability/EntryAbility.ets +++ b/entry/src/main/ets/entryability/EntryAbility.ets @@ -16,6 +16,7 @@ import { UIAbility, abilityAccessCtrl, Permissions, Want, AbilityConstant } from '@kit.AbilityKit'; import { window } from '@kit.ArkUI'; import { hilog } from '@kit.PerformanceAnalysisKit'; +import { WorkerManager } from '../workers/WorkerManager'; export default class EntryAbility extends UIAbility { onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { @@ -23,6 +24,7 @@ export default class EntryAbility extends UIAbility { } onDestroy() { + WorkerManager.terminalSelf(); hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); } diff --git a/entry/src/main/ets/view/AdjustContentView.ets b/entry/src/main/ets/view/AdjustContentView.ets index 873514c483da985f043a04a82d13d3301a619091..868c4c5d4edafc19df3de4b503e08028927cba48 100644 --- a/entry/src/main/ets/view/AdjustContentView.ets +++ b/entry/src/main/ets/view/AdjustContentView.ets @@ -14,13 +14,13 @@ */ import { image } from '@kit.ImageKit'; -import { worker, MessageEvents } from '@kit.ArkTS'; +import { MessageEvents } from '@kit.ArkTS'; import { adjustIconList, IconStatus } from '../viewModel/IconListViewModel'; import { adjustOpacity } from '../utils/OpacityUtil'; import { CommonConstants } from '../common/constant/CommonConstants'; import { AdjustId } from '../viewModel/OptionViewModel'; import { MessageItem } from '../viewModel/MessageItem'; -import Logger from '../utils/LoggerUtil'; +import { WorkerManager } from '../workers/WorkerManager'; @Component @@ -101,6 +101,14 @@ struct SliderCustom { customStyle: true }); + aboutToAppear(): void { + WorkerManager.onMessage((event: MessageEvents) => { + this.updatePixelMap(event); + }) + WorkerManager.onExit(); + WorkerManager.onMessageError(); + } + build() { Column() { Text(`${this.currentAdjustData[this.currentIndex]}`) @@ -131,7 +139,7 @@ struct SliderCustom { this.currentAdjustData[this.currentIndex] = Math.round(value); switch (this.currentIndex) { case AdjustId.BRIGHTNESS: - this.postToWorker(AdjustId.BRIGHTNESS, value, CommonConstants.BRIGHTNESS_WORKER_FILE); + this.postToWorker(AdjustId.BRIGHTNESS, value); break; case AdjustId.TRANSPARENCY: if (this.pixelMap) { @@ -145,7 +153,7 @@ struct SliderCustom { } break; case AdjustId.SATURATION: - this.postToWorker(AdjustId.SATURATION, value, CommonConstants.SATURATION_WORKER_FILE); + this.postToWorker(AdjustId.SATURATION, value); break; default: break; @@ -153,36 +161,25 @@ struct SliderCustom { } } - postToWorker(type: AdjustId, value: number, workerName: string) { + postToWorker(type: AdjustId, value: number) { if (!this.pixelMap) { return; } let sliderValue = type === AdjustId.BRIGHTNESS ? this.brightnessLastSlider : this.saturationLastSlider; - let workerInstance = new worker.ThreadWorker(workerName); const bufferArray = new ArrayBuffer(this.pixelMap.getPixelBytesNumber()); this.pixelMap.readPixelsToBuffer(bufferArray) .then(() => { - let message = new MessageItem(bufferArray, sliderValue, value); - workerInstance.postMessage(message); + let message = new MessageItem(bufferArray, sliderValue, value, type); + WorkerManager.postMessage(message); if (this.postState) { this.deviceListDialogController.open(); } this.postState = false; - workerInstance.onmessage = (event: MessageEvents) => { - this.updatePixelMap(event); - workerInstance.terminate(); - } if (type === AdjustId.BRIGHTNESS) { this.brightnessLastSlider = Math.round(value); } else { this.saturationLastSlider = Math.round(value); } - workerInstance.onexit = () => { - if (workerInstance !== undefined) { - workerInstance.terminate(); - Logger.info('AdjustContentView', 'main thread terminate'); - } - } }); } diff --git a/entry/src/main/ets/viewModel/MessageItem.ets b/entry/src/main/ets/viewModel/MessageItem.ets index d5d30e7d553f3972c176e1850cef75806b6ffc24..f13400e54fb3dd0426452a96704ef53ff94997ed 100644 --- a/entry/src/main/ets/viewModel/MessageItem.ets +++ b/entry/src/main/ets/viewModel/MessageItem.ets @@ -12,15 +12,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { AdjustId } from "./OptionViewModel"; /** * Multithreading transmission message. */ export class MessageItem { - constructor(buf: ArrayBuffer, last: number, cur: number) { + constructor(buf: ArrayBuffer, last: number, cur: number, type: AdjustId) { this.buf = buf; this.last = last; this.cur = cur; + this.type = type; } /** @@ -37,4 +39,9 @@ export class MessageItem { * Current slider value. */ cur: number; + + /** + * MessageType + */ + type: AdjustId; } \ No newline at end of file diff --git a/entry/src/main/ets/workers/AdjustWork.ets b/entry/src/main/ets/workers/AdjustWork.ets new file mode 100644 index 0000000000000000000000000000000000000000..d43fc4c9a49118e801b67a96430efb21a765b725 --- /dev/null +++ b/entry/src/main/ets/workers/AdjustWork.ets @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2025 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 '@kit.PerformanceAnalysisKit'; +import { worker, ThreadWorkerGlobalScope, MessageEvents, ErrorEvent } from '@kit.ArkTS'; +import { adjustImageValue, adjustSaturation } from '../utils/AdjustUtil'; +import { AdjustId } from '../viewModel/OptionViewModel'; + +let workerPort: ThreadWorkerGlobalScope = worker.workerPort; + +/** + * Defines the event handler to be called when the worker thread receives a message sent by the host thread. + * The event handler is executed in the worker thread. + * + * @param e message data + */ +workerPort.onmessage = (event: MessageEvents) => { + let bufferArray: ArrayBuffer = event.data.buf; + let last: number = event.data.last; + let cur: number = event.data.cur; + let type: AdjustId = event.data.type; + if (type === AdjustId.BRIGHTNESS) { + workerPort.postMessage(adjustImageValue(bufferArray, last, cur)); + return; + } + workerPort.postMessage(adjustSaturation(bufferArray, last, cur)); +} + +/** + * Defines the event handler to be called when the worker receives a message that cannot be deserialized. + * The event handler is executed in the worker thread. + * + * @param e message data + */ +workerPort.onmessageerror = (event: MessageEvents) => { + hilog.error(0x0000, 'AdjustWork', 'Failed to load the content. Cause: %{public}s', + `on message error ${JSON.stringify(event)}`); +} + +/** + * Defines the event handler to be called when an exception occurs during worker execution. + * The event handler is executed in the worker thread. + * + * @param e error message + */ +workerPort.onerror = (error: ErrorEvent) => { + hilog.error(0x0000, 'AdjustWork', 'Failed to load the content. Cause: %{public}s', + `on worker error ${JSON.stringify(error)}`); +} \ No newline at end of file diff --git a/entry/src/main/ets/workers/WorkerManager.ets b/entry/src/main/ets/workers/WorkerManager.ets new file mode 100644 index 0000000000000000000000000000000000000000..1a9ba37fa61c0a325ed81cc41511dd9017ce093b --- /dev/null +++ b/entry/src/main/ets/workers/WorkerManager.ets @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025 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 { MessageEvents, worker } from "@kit.ArkTS"; +import { CommonConstants } from "../common/constant/CommonConstants"; +import { hilog } from "@kit.PerformanceAnalysisKit"; +import { MessageItem } from "../viewModel/MessageItem"; + +/** + * Main thread worker + */ +export class WorkerManager { + private static instance: worker.ThreadWorker | undefined = undefined; + + private constructor() { + } + + public static getInstance(): worker.ThreadWorker { + if (!WorkerManager.instance) { + WorkerManager.instance = new worker.ThreadWorker(CommonConstants.WORKER_FILE); + } + return WorkerManager.instance; + } + + public static postMessage(message: MessageItem): void { + try { + WorkerManager.getInstance().postMessage(message); + } catch (error) { + hilog.error(0x0000, 'WorkerManager', 'Failed to possMessage', `on message error ${JSON.stringify(error)}`); + } + } + + public static onExit(): void { + WorkerManager.getInstance().onexit = () => { + hilog.info(0x0000, 'WorkerManager', 'worker exit. Cause: %{public}s'); + } + } + + public static onMessageError(): void { + WorkerManager.getInstance().onmessageerror = (event: MessageEvents) => { + hilog.error(0x0000, 'WorkerManager', 'Main thread post message error. Cause: %{public}s', + `on worker error ${JSON.stringify(event)}`); + } + } + + public static onMessage(callback: (event: MessageEvents) => void): void { + WorkerManager.getInstance().onmessage = callback; + } + + public static terminalSelf(): void { + try { + WorkerManager.getInstance().terminate(); + hilog.info(0x0000, 'WorkerManager', 'worker terminal success'); + } catch (error) { + hilog.error(0x0000, 'WorkerManager', 'Failed to terminalSelf. Cause: %{public}s', + `on worker error ${JSON.stringify(error)}`); + } + } +} \ No newline at end of file diff --git a/hvigor/hvigor-config.json5 b/hvigor/hvigor-config.json5 index f70ecd4112d94f9aa555adf898d53f18bf58f3e9..a2a2e3781820ac1b548a01481b50e88b0f2e5cfa 100644 --- a/hvigor/hvigor-config.json5 +++ b/hvigor/hvigor-config.json5 @@ -1,5 +1,5 @@ { - "modelVersion": "5.0.0", + "modelVersion": "5.0.5", "dependencies": { } } \ No newline at end of file diff --git a/oh-package.json5 b/oh-package.json5 index 0102ccfffc04d7eb3cf77190f9a71a15f28b9765..90c3c4d9f19217cf956a1d88ef8b1654b4e68479 100644 --- a/oh-package.json5 +++ b/oh-package.json5 @@ -1,5 +1,5 @@ { - "modelVersion": "5.0.0", + "modelVersion": "5.0.5", "license": "", "devDependencies": { },