• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { Constants, Log, MediaItem } from '@ohos/common';
17import { PhotoEditCrop } from './crop/PhotoEditCrop';
18import { PhotoEditBase } from './base/PhotoEditBase';
19import { PhotoEditMode } from './base/PhotoEditType';
20import { PixelMapWrapper } from './base/PixelMapWrapper';
21import { ImageFilterStack } from './ImageFilterStack';
22import { Loader } from './Loader';
23import { Save } from './Save';
24import image from '@ohos.multimedia.image';
25
26const TAG: string = 'editor_PhotoEditorManager';
27
28export class PhotoEditorManager {
29  private currentMode: PhotoEditMode = PhotoEditMode.EDIT_MODE_MAIN;
30  private origin: PixelMapWrapper = undefined;
31  private item: MediaItem = undefined;
32  private editors: Array<PhotoEditBase> = undefined;
33  private historyManager: ImageFilterStack = undefined;
34
35  private constructor() {
36    this.historyManager = new ImageFilterStack();
37    this.editors = [];
38    this.editors[PhotoEditMode.EDIT_MODE_CROP] = new PhotoEditCrop();
39  }
40
41  static getInstance(): PhotoEditorManager {
42    if (AppStorage.Get(Constants.PHOTO_EDITOR_MANAGER) == null) {
43      AppStorage.SetOrCreate(Constants.PHOTO_EDITOR_MANAGER, new PhotoEditorManager());
44    }
45    return AppStorage.Get(Constants.PHOTO_EDITOR_MANAGER);
46  }
47
48  initialize(item: MediaItem, mode: PhotoEditMode, errCallback?: Function): void {
49    Log.info(TAG, `initialize mode[${mode}]`);
50    this.item = item;
51    Loader.loadPixelMapWrapper(item, true).then((pixelMap) => {
52      if (pixelMap) {
53        this.origin = pixelMap;
54        this.historyManager.setOriginPixelMap(this.origin);
55        this.switchMode(mode);
56      } else {
57        Log.error(TAG, 'initialize loadPixelMapWrapper failed');
58        errCallback && errCallback();
59      }
60    })
61  }
62
63  clear(): void {
64    Log.debug(TAG, 'clear');
65    this.item = undefined;
66    if (this.origin) {
67      this.origin.release();
68      this.origin = undefined;
69    }
70    this.historyManager.setOriginPixelMap(undefined);
71    this.historyManager.releaseAll();
72    if (this.editors[this.currentMode]) {
73      this.editors[this.currentMode].clearCanvas();
74    }
75    this.currentMode = PhotoEditMode.EDIT_MODE_MAIN;
76  }
77
78  getPhotoEditBaseInstance(mode: PhotoEditMode): PhotoEditBase {
79    return this.editors[mode];
80  }
81
82  getLastestPixelMap(): PixelMapWrapper {
83    let position = this.historyManager.getPosition();
84    Log.debug(TAG, `getLastestPixelMap position = ${position}`);
85    if (position < 0) {
86      return this.origin;
87    } else {
88      return this.historyManager.at(position).getCache();
89    }
90  }
91
92  switchMode(mode: PhotoEditMode): PhotoEditMode {
93    Log.info(TAG, `switchMode: currentMode[${this.currentMode}] mode[${mode}]`);
94    if (this.currentMode == mode) {
95      return mode;
96    }
97
98    // exit current edit mode
99    if (this.editors[this.currentMode] != undefined) {
100      const filter = this.editors[this.currentMode].exit();
101      if (filter != undefined) {
102        // save cache
103        if (!filter.isCached()) {
104          const prePixelMap = this.getLastestPixelMap();
105          filter.setCache(filter.render(prePixelMap));
106        }
107        this.historyManager.push(filter);
108      }
109    }
110
111    // entry next edit mode
112    let input = this.getLastestPixelMap();
113    if (input && this.editors[mode] != undefined) {
114      this.editors[mode].entry(input);
115      // update current edit mode
116      this.currentMode = mode;
117    }
118    return this.currentMode;
119  }
120
121  isRedoValid(): boolean {
122    return this.historyManager.isRedoValid();
123  }
124
125  isUndoValid(): boolean {
126    return this.historyManager.isUndoValid();
127  }
128
129  redo(): boolean {
130    if (this.isRedoValid() && this.editors[this.currentMode] != undefined) {
131      let newPixel = this.historyManager.doRedo();
132      this.editors[this.currentMode].entry(newPixel);
133      return true;
134    }
135
136    return false;
137  }
138
139  undo(): boolean {
140    if (this.isUndoValid() && this.editors[this.currentMode] != undefined) {
141      let newPixel = this.historyManager.doUndo();
142      this.editors[this.currentMode].entry(newPixel);
143      return true;
144    }
145
146    return false;
147  }
148
149  save(isReplace: boolean, callback: Function): void {
150    if (this.editors[this.currentMode] != undefined) {
151      Log.info(TAG, `save enter isReplace = ${isReplace}`);
152      const filter = this.editors[this.currentMode].exit();
153      if (filter != undefined) {
154        this.historyManager.push(filter);
155      }
156      Save.save(this.item, this.historyManager, isReplace, callback);
157    } else {
158      Log.warn(TAG, `editor is undefined, currentMode = ${this.currentMode}`);
159    }
160  }
161}