Compare commits
11 Commits
dd85bc466c
...
6c94566042
Author | SHA1 | Date |
---|---|---|
|
6c94566042 | |
|
c9957c458f | |
|
618df4c3bb | |
|
b9365b49f4 | |
|
f351c71541 | |
|
56bd1287e4 | |
|
2cd3465906 | |
|
ec27cb91fc | |
|
d2cead637b | |
|
1b812f8431 | |
|
6e708e1c17 |
|
@ -12,6 +12,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
import { DownsampleStrategy } from '@ohos/imageknife';
|
||||||
import { IEngineKey, ImageKnifeOption, PixelMapTransformation,SparkMD5 ,ImageKnifeRequestSource} from '@ohos/libraryimageknife';
|
import { IEngineKey, ImageKnifeOption, PixelMapTransformation,SparkMD5 ,ImageKnifeRequestSource} from '@ohos/libraryimageknife';
|
||||||
|
|
||||||
//全局自定义key demo
|
//全局自定义key demo
|
||||||
|
@ -35,6 +36,9 @@ export class CustomEngineKeyImpl implements IEngineKey {
|
||||||
if (imageKnifeOption.transformation) {
|
if (imageKnifeOption.transformation) {
|
||||||
key += "transformation=" + this.getTransformation(imageKnifeOption.transformation) + ";"
|
key += "transformation=" + this.getTransformation(imageKnifeOption.transformation) + ";"
|
||||||
}
|
}
|
||||||
|
if ((imageKnifeOption.downsampleOf !== DownsampleStrategy.NONE && imageKnifeOption.downsampleOf !== undefined)) {
|
||||||
|
key += "downsampleOf" + imageKnifeOption.downsampleOf +"width="+width+"height="+ height
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return key
|
return key
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,8 +132,8 @@ struct DownSamplePage {
|
||||||
decodingOptions = {
|
decodingOptions = {
|
||||||
editable: true,
|
editable: true,
|
||||||
desiredSize: {
|
desiredSize: {
|
||||||
width: reqSize.targetWidth,
|
width: reqSize.width,
|
||||||
height: reqSize.targetHeight
|
height: reqSize.height
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 创建pixelMap
|
// 创建pixelMap
|
||||||
|
|
|
@ -85,7 +85,7 @@ export class ImageKnifeLoader {
|
||||||
decodingOptions = ImageKnifeLoader.downsamplerReqSize(typeValue, request, size, ImageKnifeRequestSource.SRC)
|
decodingOptions = ImageKnifeLoader.downsamplerReqSize(typeValue, request, size, ImageKnifeRequestSource.SRC)
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return ImageKnifeLoader.makeEmptyResult("image.createImageSource failed")
|
return ImageKnifeLoader.makeEmptyResult(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
await imageSource.createPixelMap(decodingOptions)
|
await imageSource.createPixelMap(decodingOptions)
|
||||||
|
@ -132,7 +132,7 @@ export class ImageKnifeLoader {
|
||||||
opts = ImageKnifeLoader.downsamplerReqSize(typeValue, request, size)
|
opts = ImageKnifeLoader.downsamplerReqSize(typeValue, request, size)
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return ImageKnifeLoader.makeEmptyResult("image.createImageSource failed")
|
return ImageKnifeLoader.makeEmptyResult(err)
|
||||||
}
|
}
|
||||||
await imageSource.createPixelMap(opts)
|
await imageSource.createPixelMap(opts)
|
||||||
.then((pixelmap: PixelMap) => {
|
.then((pixelmap: PixelMap) => {
|
||||||
|
@ -397,8 +397,8 @@ export class ImageKnifeLoader {
|
||||||
return ({
|
return ({
|
||||||
editable: true,
|
editable: true,
|
||||||
desiredSize: ({
|
desiredSize: ({
|
||||||
height: vp2px(reqSize.targetHeight),
|
height: vp2px(reqSize.height),
|
||||||
width: vp2px(reqSize.targetWidth)
|
width: vp2px(reqSize.width)
|
||||||
} as Size)
|
} as Size)
|
||||||
|
|
||||||
} as image.DecodingOptions)
|
} as image.DecodingOptions)
|
||||||
|
@ -406,8 +406,8 @@ export class ImageKnifeLoader {
|
||||||
return ({
|
return ({
|
||||||
editable: request.requestSource === SRC && request.transformation !== undefined ? true : false,
|
editable: request.requestSource === SRC && request.transformation !== undefined ? true : false,
|
||||||
desiredSize: ({
|
desiredSize: ({
|
||||||
width: reqSize.targetWidth,
|
width: reqSize.width,
|
||||||
height: reqSize.targetHeight
|
height: reqSize.height
|
||||||
} as Size)
|
} as Size)
|
||||||
} as image.DecodingOptions)
|
} as image.DecodingOptions)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ export interface BaseDownsampling {
|
||||||
getName(): string
|
getName(): string
|
||||||
|
|
||||||
getScaleFactor(sourceWidth: number, sourceHeight: number, requestWidth: number, requestHeight: number,downsampType?:DownsampleStrategy): number
|
getScaleFactor(sourceWidth: number, sourceHeight: number, requestWidth: number, requestHeight: number,downsampType?:DownsampleStrategy): number
|
||||||
|
//
|
||||||
getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestWidth: number,
|
getSampleSizeType(sourceWidth: number, sourceHeight: number, requestWidth: number,
|
||||||
requestHeight: number,downsampType?:DownsampleStrategy): SampleSizeRounding
|
requestHeight: number,downsampType?:DownsampleStrategy): SampleSizeRounding
|
||||||
}
|
}
|
|
@ -13,30 +13,36 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { BaseDownsampling } from './BaseDownsampling';
|
import { BaseDownsampling } from './BaseDownsampling';
|
||||||
import { highestOneBit, SampleSizeRounding } from './DownsampleUtils';
|
import { getScale, highestOneBit, round, SampleSizeRounding } from './DownsampleUtils';
|
||||||
|
|
||||||
export class FitCenter implements BaseDownsampling {
|
export class FitCenter implements BaseDownsampling {
|
||||||
getName() {
|
getName() {
|
||||||
return "FitCenter"
|
return "FitCenter"
|
||||||
}
|
}
|
||||||
|
|
||||||
getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy |undefined
|
getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,
|
||||||
): number {
|
downsampType: DownsampleStrategy
|
||||||
if (downsampType===DownsampleStrategy.FIT_CENTER_MEMORY) {
|
): number {
|
||||||
const widthPercentage = requestedWidth / sourceWidth
|
//重新计算宽高比;
|
||||||
const heightPercentage = requestedHeight / sourceHeight
|
let outSize: Size = {
|
||||||
return Math.min(widthPercentage, heightPercentage)
|
width: round(getScale(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType) * sourceWidth),
|
||||||
} else {
|
height:round(getScale(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType) * sourceHeight)
|
||||||
const maxIntegerFactor = Math.max(sourceHeight / requestedHeight, sourceWidth / requestedWidth);
|
|
||||||
const a = maxIntegerFactor === 0 ? 1 : 1 / highestOneBit(maxIntegerFactor)
|
|
||||||
return a;
|
|
||||||
}
|
}
|
||||||
|
let scaleFactor = this.getSampleSizeType(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType)===
|
||||||
|
SampleSizeRounding.QUALITY? Math.max(1, highestOneBit(Math.max(sourceWidth / outSize.width, sourceHeight / outSize.height))) :
|
||||||
|
Math.max(1, highestOneBit(Math.min(sourceWidth / outSize.width, sourceHeight / outSize.height)))//将整型的缩放因子转换为2的次幂采样大小
|
||||||
|
|
||||||
|
if (this.getSampleSizeType(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType)===
|
||||||
|
SampleSizeRounding.MEMORY && (scaleFactor < (1 / getScale(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType)))) {
|
||||||
|
scaleFactor = scaleFactor << 1;
|
||||||
|
}
|
||||||
|
return scaleFactor
|
||||||
}
|
}
|
||||||
|
|
||||||
//实现 getSampleSizeRounding 方法
|
getSampleSizeType(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,
|
||||||
getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy|undefined
|
downsampType: DownsampleStrategy
|
||||||
): number {
|
): number {
|
||||||
if (downsampType===DownsampleStrategy.FIT_CENTER_QUALITY) {
|
if (downsampType === DownsampleStrategy.FIT_CENTER_QUALITY) {
|
||||||
return SampleSizeRounding.QUALITY;
|
return SampleSizeRounding.QUALITY;
|
||||||
} else {
|
} else {
|
||||||
return SampleSizeRounding.MEMORY;
|
return SampleSizeRounding.MEMORY;
|
||||||
|
@ -52,15 +58,19 @@ export class None implements BaseDownsampling {
|
||||||
|
|
||||||
public getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number,
|
public getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number,
|
||||||
requestedHeight: number): number {
|
requestedHeight: number): number {
|
||||||
//不进行任何下采样,缩放因子为 1
|
let outSize: Size = {
|
||||||
return 1;
|
width: round(sourceWidth),
|
||||||
|
height:round(sourceHeight)
|
||||||
|
}
|
||||||
|
let scaleFactor =
|
||||||
|
Math.max(1, highestOneBit(Math.max(sourceWidth / outSize.width, sourceHeight / outSize.height)))
|
||||||
|
return scaleFactor
|
||||||
}
|
}
|
||||||
|
|
||||||
//实现 getSampleSizeRounding 方法
|
//实现 getSampleSizeType 方法
|
||||||
public getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestedWidth: number,
|
public getSampleSizeType(sourceWidth: number, sourceHeight: number, requestedWidth: number,
|
||||||
requestedHeight: number): SampleSizeRounding {
|
requestedHeight: number): SampleSizeRounding {
|
||||||
return SampleSizeRounding.QUALITY
|
return SampleSizeRounding.QUALITY
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,10 +87,16 @@ export class CenterOutside implements BaseDownsampling {
|
||||||
const widthPercentage = requestedWidth / sourceWidth;
|
const widthPercentage = requestedWidth / sourceWidth;
|
||||||
const heightPercentage = requestedHeight / sourceHeight;
|
const heightPercentage = requestedHeight / sourceHeight;
|
||||||
//返回宽度和高度比例中最大的值
|
//返回宽度和高度比例中最大的值
|
||||||
return Math.max(widthPercentage, heightPercentage);
|
let outSize: Size = {
|
||||||
|
width: round(Math.max(widthPercentage, heightPercentage) * sourceWidth),
|
||||||
|
height:round(Math.max(widthPercentage, heightPercentage) * sourceHeight)
|
||||||
|
}
|
||||||
|
let scaleFactor = Math.max(1, highestOneBit(Math.max(sourceWidth / outSize.width, sourceHeight / outSize.height)))
|
||||||
|
|
||||||
|
return scaleFactor
|
||||||
}
|
}
|
||||||
|
|
||||||
getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestedWidth: number,
|
getSampleSizeType(sourceWidth: number, sourceHeight: number, requestedWidth: number,
|
||||||
requestedHeight: number): SampleSizeRounding {
|
requestedHeight: number): SampleSizeRounding {
|
||||||
return SampleSizeRounding.QUALITY;
|
return SampleSizeRounding.QUALITY;
|
||||||
}
|
}
|
||||||
|
@ -93,7 +109,7 @@ export class AtMost implements BaseDownsampling {
|
||||||
return "AtMost"
|
return "AtMost"
|
||||||
}
|
}
|
||||||
|
|
||||||
//实现 getScaleFactor 方法
|
|
||||||
getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number): number {
|
getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number): number {
|
||||||
const maxIntegerFactor = Math.ceil(Math.max(sourceHeight / requestedHeight, sourceWidth / requestedWidth));
|
const maxIntegerFactor = Math.ceil(Math.max(sourceHeight / requestedHeight, sourceWidth / requestedWidth));
|
||||||
let lesserOrEqualSampleSize = Math.max(1, highestOneBit(maxIntegerFactor));
|
let lesserOrEqualSampleSize = Math.max(1, highestOneBit(maxIntegerFactor));
|
||||||
|
@ -103,11 +119,19 @@ export class AtMost implements BaseDownsampling {
|
||||||
}
|
}
|
||||||
greaterOrEqualSampleSize = lesserOrEqualSampleSize << (lesserOrEqualSampleSize < maxIntegerFactor ? 1 : 0)
|
greaterOrEqualSampleSize = lesserOrEqualSampleSize << (lesserOrEqualSampleSize < maxIntegerFactor ? 1 : 0)
|
||||||
//返回缩放因子
|
//返回缩放因子
|
||||||
return 1 / greaterOrEqualSampleSize
|
let outSize: Size = {
|
||||||
|
width: round((1 / greaterOrEqualSampleSize) * sourceWidth),
|
||||||
|
height:round((1 / greaterOrEqualSampleSize) * sourceHeight)
|
||||||
|
}
|
||||||
|
let scaleFactor = Math.max(1, highestOneBit(Math.min(sourceWidth / outSize.width, sourceHeight / outSize.height)))
|
||||||
|
if ((scaleFactor < greaterOrEqualSampleSize)) {
|
||||||
|
scaleFactor = scaleFactor << 1;
|
||||||
|
}
|
||||||
|
return scaleFactor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestedWidth: number,
|
getSampleSizeType(sourceWidth: number, sourceHeight: number, requestedWidth: number,
|
||||||
requestHeight: number): SampleSizeRounding {
|
requestHeight: number): SampleSizeRounding {
|
||||||
//根据 AtMost 的逻辑,总是返回 MEMORY
|
//根据 AtMost 的逻辑,总是返回 MEMORY
|
||||||
return SampleSizeRounding.MEMORY
|
return SampleSizeRounding.MEMORY
|
||||||
|
@ -120,43 +144,42 @@ export class CenterInside implements BaseDownsampling {
|
||||||
getName() {
|
getName() {
|
||||||
return "CenterInside"
|
return "CenterInside"
|
||||||
}
|
}
|
||||||
|
getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,
|
||||||
getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy|undefined
|
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|undefined
|
|
||||||
): number {
|
): number {
|
||||||
if (downsampType===DownsampleStrategy.FIT_CENTER_MEMORY) {
|
|
||||||
const widthPercentage = requestedWidth / sourceWidth
|
let outSize: Size = {
|
||||||
const heightPercentage = requestedHeight / sourceHeight
|
width: round(Math.min(1, getScale(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType)) * sourceWidth),
|
||||||
return Math.min(widthPercentage, heightPercentage)
|
height:round(Math.min(1, getScale(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType)) * sourceHeight)
|
||||||
} else {
|
|
||||||
const maxIntegerFactor = Math.max(sourceHeight / requestedHeight, sourceWidth / requestedWidth);
|
|
||||||
const a = maxIntegerFactor === 0 ? 1 : 1 / highestOneBit(maxIntegerFactor)
|
|
||||||
return a;
|
|
||||||
}
|
}
|
||||||
|
//将整型的缩放因子转换为2的次幂采样大小
|
||||||
|
let scaleFactor = this.getSampleSizeType(sourceWidth, sourceHeight, requestedWidth, requestedHeight,
|
||||||
|
downsampType) == SampleSizeRounding.QUALITY ?
|
||||||
|
Math.max(1, highestOneBit(Math.max(sourceWidth / outSize.width, sourceHeight / outSize.height))) :
|
||||||
|
Math.max(1, highestOneBit(Math.min(sourceWidth / outSize.width, sourceHeight / outSize.height)))
|
||||||
|
if (this.getSampleSizeType(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType)
|
||||||
|
== SampleSizeRounding.MEMORY && (scaleFactor < (1 / Math.min(1, getScale(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType))))) {
|
||||||
|
scaleFactor = scaleFactor << 1;
|
||||||
|
}
|
||||||
|
return scaleFactor
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy|undefined
|
getSampleSizeType(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,
|
||||||
): SampleSizeRounding {
|
downsampType: DownsampleStrategy
|
||||||
|
): SampleSizeRounding {
|
||||||
//如果缩放因子为 1,表示没有缩放,优先选择质量
|
//如果缩放因子为 1,表示没有缩放,优先选择质量
|
||||||
if (this.getScaleFactor(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType) === 1) {
|
if (Math.min(1, getScale(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType)) === 1) {
|
||||||
return SampleSizeRounding.QUALITY
|
return SampleSizeRounding.QUALITY
|
||||||
}
|
}
|
||||||
//否则,使用 FIL_CENTER 的 SampleSizeRounding 值
|
//否则,使用 FIL_CENTER 的 SampleSizeRounding 值
|
||||||
return this.getSampleSize(sourceWidth, sourceHeight, requestedWidth, requestedHeight,downsampType);
|
return this.getSampleSize(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType);
|
||||||
}
|
}
|
||||||
|
|
||||||
getSampleSize(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy|undefined
|
getSampleSize(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,
|
||||||
): SampleSizeRounding {
|
downsampType: DownsampleStrategy
|
||||||
if (downsampType===DownsampleStrategy.CENTER_INSIDE_MEMORY) {
|
): SampleSizeRounding {
|
||||||
|
if (downsampType === DownsampleStrategy.CENTER_INSIDE_MEMORY) {
|
||||||
return SampleSizeRounding.MEMORY;
|
return SampleSizeRounding.MEMORY;
|
||||||
} else {
|
} else {
|
||||||
return SampleSizeRounding.QUALITY;
|
return SampleSizeRounding.QUALITY;
|
||||||
|
@ -168,11 +191,11 @@ export enum DownsampleStrategy {
|
||||||
//请求尺寸大于实际尺寸不进行放大
|
//请求尺寸大于实际尺寸不进行放大
|
||||||
AT_MOST,
|
AT_MOST,
|
||||||
//两边自适应内存优先
|
//两边自适应内存优先
|
||||||
FIT_CENTER_MEMORY ,
|
FIT_CENTER_MEMORY,
|
||||||
//两边自适应质量优先
|
//两边自适应质量优先
|
||||||
FIT_CENTER_QUALITY,
|
FIT_CENTER_QUALITY,
|
||||||
//按照宽高比的最大比进行适配内存优先
|
//按照宽高比的最大比进行适配内存优先
|
||||||
CENTER_INSIDE_MEMORY ,
|
CENTER_INSIDE_MEMORY,
|
||||||
//按照宽高比的最大比进行适配质量优先
|
//按照宽高比的最大比进行适配质量优先
|
||||||
CENTER_INSIDE_QUALITY,
|
CENTER_INSIDE_QUALITY,
|
||||||
//宽高进行等比缩放宽高里面最小的比例先放进去,然后再根据原图的缩放比去适配
|
//宽高进行等比缩放宽高里面最小的比例先放进去,然后再根据原图的缩放比去适配
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
import { DownsampleStrategy } from './DownsampleStartegy';
|
||||||
|
|
||||||
export enum SampleSizeRounding {
|
export enum SampleSizeRounding {
|
||||||
/**
|
/**
|
||||||
* Prefer to round the sample size up so that the image is downsampled to smaller than the
|
* Prefer to round the sample size up so that the image is downsampled to smaller than the
|
||||||
|
@ -26,6 +28,7 @@ export enum SampleSizeRounding {
|
||||||
//(质量优先)
|
//(质量优先)
|
||||||
QUALITY
|
QUALITY
|
||||||
}
|
}
|
||||||
|
|
||||||
export function highestOneBit(i: number): number {
|
export function highestOneBit(i: number): number {
|
||||||
i |= (i >> 1);
|
i |= (i >> 1);
|
||||||
i |= (i >> 2);
|
i |= (i >> 2);
|
||||||
|
@ -33,4 +36,22 @@ export function highestOneBit(i: number): number {
|
||||||
i |= (i >> 8);
|
i |= (i >> 8);
|
||||||
i |= (i >> 16);
|
i |= (i >> 16);
|
||||||
return i - (i >>> 1);
|
return i - (i >>> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function getScale(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,
|
||||||
|
downsampType: DownsampleStrategy
|
||||||
|
): number {
|
||||||
|
if (downsampType === DownsampleStrategy.FIT_CENTER_MEMORY) {
|
||||||
|
const widthPercentage = requestedWidth / sourceWidth
|
||||||
|
const heightPercentage = requestedHeight / sourceHeight
|
||||||
|
return Math.min(widthPercentage, heightPercentage)
|
||||||
|
} else {
|
||||||
|
const maxIntegerFactor = Math.max(sourceHeight / requestedHeight, sourceWidth / requestedWidth);
|
||||||
|
return maxIntegerFactor === 0 ? 1 : 1 / highestOneBit(maxIntegerFactor);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function round(value: number): number {
|
||||||
|
return Math.floor(value + 0.5);
|
||||||
}
|
}
|
|
@ -20,12 +20,7 @@ import {
|
||||||
FitCenter,
|
FitCenter,
|
||||||
None,
|
None,
|
||||||
} from './DownsampleStartegy';
|
} from './DownsampleStartegy';
|
||||||
import { highestOneBit, SampleSizeRounding } from './DownsampleUtils';
|
import { highestOneBit, round, SampleSizeRounding } from './DownsampleUtils';
|
||||||
|
|
||||||
export interface calculateScaleType {
|
|
||||||
targetWidth: number,
|
|
||||||
targetHeight: number
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export class Downsampler {
|
export class Downsampler {
|
||||||
|
@ -36,43 +31,45 @@ export class Downsampler {
|
||||||
requestWidth: number, //请求宽高
|
requestWidth: number, //请求宽高
|
||||||
requestHeight: number, //请求宽高
|
requestHeight: number, //请求宽高
|
||||||
downsampType: DownsampleStrategy,
|
downsampType: DownsampleStrategy,
|
||||||
): calculateScaleType {
|
): Size {
|
||||||
|
|
||||||
if (sourceHeight <= 0 || sourceWidth <= 0) {
|
if (sourceHeight <= 0 || sourceWidth <= 0) {
|
||||||
throw new Error(`Invalid width and height, sourceHeight:${sourceHeight}+ sourceWidth:${sourceWidth}`)
|
throw new Error(`Invalid width and height, sourceHeight:${sourceHeight}+ sourceWidth:${sourceWidth}`)
|
||||||
}
|
}
|
||||||
let downsampler = this.getDownsampler(downsampType);
|
let downsampler = this.getDownsampler(downsampType);
|
||||||
let exactScaleFactor: number =
|
let scaleFactor: number =
|
||||||
downsampler.getScaleFactor(sourceWidth, sourceHeight, requestWidth, requestHeight, downsampType);
|
downsampler.getScaleFactor(sourceWidth, sourceHeight, requestWidth, requestHeight, downsampType);//缩放比
|
||||||
let rounding: SampleSizeRounding =
|
// let rounding: SampleSizeRounding =
|
||||||
downsampler.getSampleSizeRounding(sourceWidth, sourceHeight, requestWidth, requestHeight, downsampType); //采样类型
|
// downsampler.getSampleSizeType(sourceWidth, sourceHeight, requestWidth, requestHeight, downsampType); //采样类型
|
||||||
//原始宽高和缩放系数的乘积
|
//根据缩放比重新计算宽高
|
||||||
let outSize:Size = {
|
// let outSize: Size = {
|
||||||
width: this.round(exactScaleFactor * sourceWidth),
|
// width: round(exactScaleFactor * sourceWidth),
|
||||||
height: this.round(exactScaleFactor * sourceHeight)
|
// height:round(exactScaleFactor * sourceHeight)
|
||||||
}
|
// }
|
||||||
let scaleFactor =
|
// let scaleFactor =
|
||||||
rounding == SampleSizeRounding.QUALITY ? Math.max(sourceWidth / outSize.width, sourceHeight / outSize.height) :
|
// rounding == SampleSizeRounding.QUALITY ? Math.max(sourceWidth / exactScaleFactor.width, sourceHeight / exactScaleFactor.height) :
|
||||||
Math.min(sourceWidth / outSize.width, sourceHeight / outSize.height) //将整型的缩放因子转换为2的次幂采样大小
|
// Math.min(sourceWidth / exactScaleFactor.width, sourceHeight / exactScaleFactor.height) //重新计算宽高比
|
||||||
scaleFactor = Math.max(1, highestOneBit(scaleFactor))
|
|
||||||
if (rounding == 0 && (scaleFactor < (1 / exactScaleFactor))) {
|
// scaleFactor = Math.max(1, highestOneBit(scaleFactor))//将整型的缩放因子转换为2的次幂采样大小
|
||||||
scaleFactor = scaleFactor << 1;
|
//
|
||||||
}
|
// if (rounding == 0 && (scaleFactor < (1 / exactScaleFactor))) {
|
||||||
|
// scaleFactor = scaleFactor << 1;
|
||||||
|
// }
|
||||||
//基于上一步得出的采样大小,根据不同的图片类型,计算采样后的图片尺寸
|
//基于上一步得出的采样大小,根据不同的图片类型,计算采样后的图片尺寸
|
||||||
if (typeValue === "png") {
|
if (typeValue === "png") {
|
||||||
return {
|
return {
|
||||||
targetWidth: Math.floor(sourceWidth / scaleFactor),
|
width: Math.floor(sourceWidth / scaleFactor),
|
||||||
targetHeight: Math.floor(sourceHeight / scaleFactor)
|
height: Math.floor(sourceHeight / scaleFactor)
|
||||||
}
|
}
|
||||||
} else if (typeValue === "webp") {
|
} else if (typeValue === "webp") {
|
||||||
return {
|
return {
|
||||||
targetWidth: Math.round(sourceWidth / scaleFactor),
|
width: Math.round(sourceWidth / scaleFactor),
|
||||||
targetHeight: Math.round(sourceHeight / scaleFactor)
|
height: Math.round(sourceHeight / scaleFactor)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
targetWidth: sourceWidth / scaleFactor,
|
width: sourceWidth / scaleFactor,
|
||||||
targetHeight: sourceHeight / scaleFactor
|
height: sourceHeight / scaleFactor
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,8 +93,4 @@ export class Downsampler {
|
||||||
throw new Error('Unsupported downsampling strategy');
|
throw new Error('Unsupported downsampling strategy');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
round(value: number): number {
|
|
||||||
return Math.floor(value + 0.5);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue