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 { Log } from './Log'; 17import { Constants } from '../model/common/Constants'; 18import display from '@ohos.display'; 19import image from '@ohos.multimedia.image'; 20 21const TAG: string = 'common_ImageUtil'; 22 23type ImageSize = { 24 width: number; 25 height: number; 26}; 27 28export class ImageUtil { 29 // 默认缩略图大小,用于大图跳转 30 static readonly DEFAULT_THUMBNAIL_SIZE: number = 640; 31 32 static computeSampleSize(width: number, height: number, minSideLength: number, maxNumOfPixels: number): number { 33 if (width == 0 || height == 0 || minSideLength == 0 || maxNumOfPixels == 0) { 34 return 2; 35 } 36 let initialSize = ImageUtil.computeInitialSampleSize(width, height, minSideLength, maxNumOfPixels); 37 Log.debug(TAG, `initialSize: ${initialSize}`); 38 return initialSize <= 8 ? ImageUtil.nextPowerOf2(initialSize) : Math.floor((initialSize + 8 - 1) / 8) * 8; 39 } 40 41 static getScreenNailSize(size: image.Size): void { 42 let displayClass: display.Display = display.getDefaultDisplaySync(); 43 // 屏幕最长边px值 44 let screenWidth: number = displayClass.width; 45 let screenHeight: number = displayClass.height; 46 let maxScreenSideLength = Math.max(screenWidth, screenHeight); 47 Log.info(TAG, `getScreenNailSize maxSideLength: ${maxScreenSideLength}`); 48 let targetSize = maxScreenSideLength * Constants.NUMBER_1 / Constants.NUMBER_4; 49 let sizeWidth: number = size.width; 50 let sizeHeight: number = size.height; 51 let maxImageSideLength: number = Math.max(sizeWidth, sizeHeight); 52 if (maxImageSideLength === 0) { 53 Log.error(TAG, 'screen max length is zero'); 54 return; 55 } 56 let scale = targetSize / maxImageSideLength; 57 size.width = Math.ceil(size.width * scale); 58 size.height = Math.ceil(size.height * scale); 59 Log.info(TAG, `getScreenNailSize scale: ${scale}, target height ${size.height}`); 60 } 61 62 static nextPowerOf2(value: number): number { 63 let useValue = value; 64 if (useValue <= 0 || useValue > (1 << 30)) { 65 Log.warn(TAG, `invalid sample value ${useValue}!`); 66 return 1; 67 } 68 useValue -= 1; 69 useValue |= useValue >> 16; 70 useValue |= useValue >> 8; 71 useValue |= useValue >> 4; 72 useValue |= useValue >> 2; 73 useValue |= useValue >> 1; 74 Log.debug(TAG, `nextPowerOf2:${useValue}`); 75 return useValue + 1; 76 } 77 78 /** 79 * Calculate the aspect ratio, considering the direction of rotation 80 * 81 * @param info include orientation width height 82 * @return the aspect ratio 83 */ 84 static calcRatio(info: ImageSize): number { 85 if (info == null || info == undefined) { 86 return 1; 87 } 88 if (info.width == 0 || info.height == 0) { 89 return 1; 90 } 91 return info.width / info.height; 92 } 93 94 /** 95 * 计算缩略图大小生成对应路径 96 * 计算缩略图大小规格:短边等于不小于给定大小;如果原图短边小于给定大小则返回原图大小 97 * 98 * @param uri 图片媒体路径 99 * @param imageHeight 图片原高 100 * @param imageWidth 图片原宽 101 */ 102 static calcThumbnail(uri: string, imageHeight: number, imageWidth: number, orientation?: number): string { 103 if (uri == null) { 104 return ''; 105 } 106 if (!imageWidth || !imageHeight) { 107 // 长宽无效返回缩略图默认值256 * 256 108 return `${uri}/thumbnail/256/256` 109 } 110 if (imageHeight < this.DEFAULT_THUMBNAIL_SIZE || imageWidth < this.DEFAULT_THUMBNAIL_SIZE) { 111 return `${uri}/thumbnail/${imageWidth}/${imageHeight}` 112 } 113 114 let width = 0; 115 let height = 0; 116 if (orientation != null && (orientation == Constants.ANGLE_90 || orientation == Constants.ANGLE_270)) { 117 let temp = imageWidth; 118 imageWidth = imageHeight; 119 imageHeight = temp; 120 } 121 if (imageHeight < imageWidth) { 122 height = this.DEFAULT_THUMBNAIL_SIZE; 123 width = Math.round(height * imageWidth / imageHeight) 124 } else { 125 width = this.DEFAULT_THUMBNAIL_SIZE; 126 height = Math.round(width * imageHeight / imageWidth); 127 } 128 return `${uri}/thumbnail/${width}/${height}` 129 } 130 131 private static computeInitialSampleSize(width: number, height: number, 132 minSideLength: number, maxNumOfPixels: number): number { 133 if ((maxNumOfPixels == -1) && (minSideLength == -1)) { 134 return 1; 135 } 136 137 let lowerBound: number = (maxNumOfPixels == -1) ? 1 : Math.ceil(Math.sqrt((width * height) / maxNumOfPixels)); 138 Log.debug(TAG, `lowerBound: ${lowerBound}`); 139 if (minSideLength == -1) { 140 return lowerBound; 141 } else { 142 let sampleSize = Math.min(width / minSideLength, height / minSideLength); 143 return Math.max(sampleSize, lowerBound); 144 } 145 } 146}