forked from floraachy/ImageKnife
184 lines
7.0 KiB
Plaintext
184 lines
7.0 KiB
Plaintext
/*
|
||
* Copyright (C) 2024 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 { BaseDownsampling } from './BaseDownsampling';
|
||
import { highestOneBit, SampleSizeRounding } from './DownsampleUtils';
|
||
|
||
export class FitCenter implements BaseDownsampling {
|
||
getName() {
|
||
return "FitCenter"
|
||
}
|
||
|
||
getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy
|
||
): number {
|
||
if (downsampType===DownsampleStrategy.FIT_CENTER_QUALITY) {
|
||
const widthPercentage = requestedWidth / sourceWidth
|
||
const heightPercentage = requestedHeight / sourceHeight
|
||
return Math.min(widthPercentage, heightPercentage)
|
||
} else {
|
||
const maxIntegerFactor = Math.max(sourceHeight / requestedHeight, sourceWidth / requestedWidth);
|
||
const a = maxIntegerFactor === 0 ? 1 : 1 / highestOneBit(maxIntegerFactor)
|
||
return a;
|
||
}
|
||
}
|
||
|
||
//实现 getSampleSizeRounding 方法
|
||
getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy
|
||
): number {
|
||
if (downsampType===DownsampleStrategy.FIT_CENTER_QUALITY) {
|
||
return SampleSizeRounding.QUALITY;
|
||
} else {
|
||
return SampleSizeRounding.MEMORY;
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
export class None implements BaseDownsampling {
|
||
getName(): string {
|
||
return "DownsampleNone"
|
||
}
|
||
|
||
public getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number,
|
||
requestedHeight: number): number {
|
||
//不进行任何下采样,缩放因子为 1
|
||
return 1;
|
||
}
|
||
|
||
//实现 getSampleSizeRounding 方法
|
||
public getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestedWidth: number,
|
||
requestedHeight: number): SampleSizeRounding {
|
||
return SampleSizeRounding.QUALITY
|
||
|
||
}
|
||
}
|
||
|
||
|
||
/*宽高进行等比缩放宽高里面最小的比例先放进去
|
||
然后再更据原图的缩放比去适配另一边*/
|
||
|
||
export class CenterOutside implements BaseDownsampling {
|
||
getName() {
|
||
return "CenterOutside"
|
||
}
|
||
|
||
getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number): number {
|
||
const widthPercentage = requestedWidth / sourceWidth;
|
||
const heightPercentage = requestedHeight / sourceHeight;
|
||
//返回宽度和高度比例中最大的值
|
||
return Math.max(widthPercentage, heightPercentage);
|
||
}
|
||
|
||
getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestedWidth: number,
|
||
requestedHeight: number): SampleSizeRounding {
|
||
//根据 CenterOutside 的逻辑,总是返回 QUALITY
|
||
return SampleSizeRounding.QUALITY;
|
||
}
|
||
}
|
||
|
||
/*请求尺寸大于实际尺寸不进行放大,按照原图展示*/
|
||
|
||
export class AtMost implements BaseDownsampling {
|
||
getName() {
|
||
return "AtMost"
|
||
}
|
||
|
||
//实现 getScaleFactor 方法
|
||
getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number): number {
|
||
const maxIntegerFactor = Math.ceil(Math.max(sourceHeight / requestedHeight, sourceWidth / requestedWidth));
|
||
let lesserOrEqualSampleSize = Math.max(1, highestOneBit(maxIntegerFactor));
|
||
let greaterOrEqualSampleSize = lesserOrEqualSampleSize
|
||
if (lesserOrEqualSampleSize < maxIntegerFactor) {
|
||
greaterOrEqualSampleSize = lesserOrEqualSampleSize <<= 1;
|
||
}
|
||
greaterOrEqualSampleSize = lesserOrEqualSampleSize << (lesserOrEqualSampleSize < maxIntegerFactor ? 1 : 0)
|
||
//返回缩放因子
|
||
return 1 / greaterOrEqualSampleSize
|
||
}
|
||
|
||
|
||
getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestedWidth: number,
|
||
requestHeight: number): SampleSizeRounding {
|
||
//根据 AtMost 的逻辑,总是返回 MEMORY
|
||
return SampleSizeRounding.MEMORY
|
||
}
|
||
}
|
||
|
||
/*宽高进行等比缩放宽高里面最大的比例先放进去
|
||
然后再更据原图的缩放比去适配另一边*/
|
||
export class CenterInside implements BaseDownsampling {
|
||
getName() {
|
||
return "CenterInside"
|
||
}
|
||
|
||
getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy
|
||
): number {
|
||
//获取 FIT_CENTER 的缩放因子
|
||
const fitCenterScaleFactor: ESObject =
|
||
this.getScale(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType);
|
||
//返回不超过 1 的缩放因子,即尽量缩小图像以适应目标尺寸,但不会放大
|
||
return Math.min(1, fitCenterScaleFactor);
|
||
|
||
}
|
||
|
||
getScale(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy
|
||
): number {
|
||
if (downsampType===DownsampleStrategy.FIT_CENTER_QUALITY) {
|
||
const widthPercentage = requestedWidth / sourceWidth
|
||
const heightPercentage = requestedHeight / sourceHeight
|
||
return Math.min(widthPercentage, heightPercentage)
|
||
} else {
|
||
//类似 AT_LEAST,但只要求一个维度或另一个维度大于等于请求的尺寸
|
||
const maxIntegerFactor = Math.max(sourceHeight / requestedHeight, sourceWidth / requestedWidth);
|
||
return maxIntegerFactor === 0 ? 1 : 1 / highestOneBit(maxIntegerFactor);
|
||
|
||
}
|
||
}
|
||
|
||
getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy
|
||
): SampleSizeRounding {
|
||
//如果缩放因子为 1,表示没有缩放,优先选择质量
|
||
if (this.getScaleFactor(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType) === 1) {
|
||
return SampleSizeRounding.QUALITY
|
||
}
|
||
//否则,使用 FIL_CENTER 的 SampleSizeRounding 值
|
||
return this.getSampleSize(sourceWidth, sourceHeight, requestedWidth, requestedHeight,downsampType);
|
||
}
|
||
|
||
getSampleSize(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy
|
||
): SampleSizeRounding {
|
||
if (downsampType===DownsampleStrategy.CENTER_INSIDE_QUALITY) {
|
||
return SampleSizeRounding.QUALITY;
|
||
} else {
|
||
return SampleSizeRounding.MEMORY;
|
||
}
|
||
}
|
||
}
|
||
|
||
export enum DownsampleStrategy {
|
||
//请求尺寸大于实际尺寸不进行放大
|
||
AT_MOST,
|
||
//两边自适应内存优先
|
||
FIT_CENTER_MEMORY ,
|
||
//两边自适应质量优先
|
||
FIT_CENTER_QUALITY,
|
||
//按照宽高比的最大比进行适配内存优先
|
||
CENTER_INSIDE_MEMORY ,
|
||
//按照宽高比的最大比进行适配质量优先
|
||
CENTER_INSIDE_QUALITY,
|
||
//宽高进行等比缩放宽高里面最小的比例先放进去,然后再根据原图的缩放比去适配
|
||
CENTER_OUTSIDE,
|
||
//不进行降采样
|
||
NONE,
|
||
} |