1/* 2 * Copyright (c) 2022 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 type { MediaItem, Size } from '@ohos/common'; 17import { BrowserDataFactory, ImageUtil, Log, ScreenManager } from '@ohos/common'; 18import { PixelMapWrapper } from './base/PixelMapWrapper'; 19import { CropAngle } from './crop/CropType'; 20import userFileManager from '@ohos.filemanagement.userFileManager'; 21import image from '@ohos.multimedia.image'; 22 23const TAG: string = 'editor_Loader'; 24 25export class Loader { 26 private static readonly MIN_PIXEL_MAP_SIZE: number = 1024; 27 28 static async loadPixelMapWrapper(mediaItem: MediaItem, isPreview: boolean = false): Promise<PixelMapWrapper> { 29 Log.debug(TAG, `Photo: loadPixelMap uri = ${mediaItem.uri}`); 30 let dataImpl = BrowserDataFactory.getFeature(BrowserDataFactory.TYPE_PHOTO); 31 32 let result = await dataImpl.getDataByUri(mediaItem.uri); 33 if (!result) { 34 Log.error(TAG, 'get file asset failed.'); 35 return null; 36 } 37 38 let size = { 39 width: result.get(userFileManager.ImageVideoKey.WIDTH.toString()) as number, 40 height: result.get(userFileManager.ImageVideoKey.HEIGHT.toString()) as number 41 }; 42 43 let thumbnail = undefined; 44 if (isPreview) { 45 Loader.getPixelMapPreviewSize(size); 46 thumbnail = await result.getThumbnail(size); 47 } else { 48 let fd = undefined; 49 let imageSourceApi: image.ImageSource = undefined; 50 try { 51 fd = await result.open('rw'); 52 imageSourceApi = image.createImageSource(fd); 53 thumbnail = await imageSourceApi.createPixelMap(); 54 } catch (e) { 55 Log.error(TAG, "loadPixelMapWrapper: sth wrong, " + e); 56 } finally { 57 await result.close(fd); 58 } 59 } 60 61 let wrapper = new PixelMapWrapper(thumbnail, px2vp(size.width), px2vp(size.height)); 62 Log.info(TAG, `Photo: loadPixelMap: size[${JSON.stringify(size)}] wrapper[${JSON.stringify(wrapper)}]`); 63 64 let orientation = mediaItem.orientation || 0; 65 Loader.translatePixelMap(wrapper, orientation); 66 Log.info(TAG, `Photo: loadPixelMap: final wrapper[${JSON.stringify(wrapper)}]`); 67 return wrapper; 68 } 69 70 private static getPixelMapPreviewSize(size: Size) { 71 let width = ScreenManager.getInstance().getWinWidth(); 72 let height = ScreenManager.getInstance().getWinHeight(); 73 Log.debug(TAG, `picture real size: ${size.width} ${size.height}`); 74 let scale = ImageUtil.computeSampleSize(size.width, size.height, Loader.MIN_PIXEL_MAP_SIZE, width * height * 2); 75 size.width = Math.ceil(size.width / scale); 76 size.height = Math.ceil(size.height / scale); 77 Log.debug(TAG, `picture scale: ${scale} size: ${JSON.stringify(size)}`); 78 } 79 80 private static translatePixelMap(image: PixelMapWrapper, orientation: number) { 81 if (0 == orientation % CropAngle.CIRCLE_ANGLE) { 82 return image; 83 } 84 85 let size = Loader.swapSize(image, orientation); 86 let offWidth = size.width; 87 let offHeight = size.height; 88 let setting = new RenderingContextSettings(true) 89 let context = new OffscreenCanvasRenderingContext2D(offWidth, offHeight, setting); 90 91 context.save(); 92 context.drawImage(image.pixelMap, 0, 0, offWidth, offHeight); 93 context.restore(); 94 95 image.pixelMap && image.pixelMap.release(); 96 image.pixelMap = context.getPixelMap(0, 0, offWidth, offHeight); 97 image.width = size.width; 98 image.height = size.height; 99 } 100 101 private static swapSize(image: PixelMapWrapper, orientation: number): Size { 102 let angle = orientation % CropAngle.HALF_CIRCLE_ANGLE; 103 let size = { 104 width: image.width, 105 height: image.height 106 }; 107 if (0 != angle) { 108 size.width = image.height; 109 size.height = image.width; 110 } 111 return size; 112 } 113 114 static async getCompressedBitsPerPixel(mediaItem: MediaItem): Promise<number> { 115 return new Promise(async (resolve, reject)=> { 116 let dataImpl = BrowserDataFactory.getFeature(BrowserDataFactory.TYPE_PHOTO); 117 let result = await dataImpl.getDataByUri(mediaItem.uri); 118 if (!result) { 119 Log.error(TAG, 'getCompressedBitsPerPixel: get file asset failed.'); 120 reject(); 121 } 122 123 let fd = await result.open('rw'); 124 let imageSourceApi: image.ImageSource = image.createImageSource(fd); 125 imageSourceApi = image.createImageSource(fd); 126 imageSourceApi.getImageProperty("CompressedBitsPerPixel", (error, data) => { 127 if (error) { 128 Log.error(TAG, 'Failed to get the value of the specified attribute key of the image.'); 129 result.close(fd); 130 reject(); 131 } else { 132 Log.error(TAG, 'Succeeded in getting the value of the specified attribute key of the image. data is ' + data); 133 result.close(fd); 134 resolve(Number(data)); 135 } 136 }); 137 }); 138 } 139}