parent
60df15c3ea
commit
9b44746094
|
@ -656,11 +656,11 @@ async function requestJob(request: RequestJobRequest, requestList?: List<ImageKn
|
||||||
editable: true,
|
editable: true,
|
||||||
desiredSize: defaultSize
|
desiredSize: defaultSize
|
||||||
};
|
};
|
||||||
let imageInfo = await imageSource.getImageInfo()
|
// let imageInfo = await imageSource.getImageInfo()
|
||||||
if ((request.downsampType !== DownsampleStrategy.NONE && request.downsampType !== undefined) &&
|
if ((request.downsampType !== DownsampleStrategy.NONE && request.downsampType !== undefined) &&
|
||||||
request.requestSource == ImageKnifeRequestSource.SRC) {
|
request.requestSource == ImageKnifeRequestSource.SRC) {
|
||||||
let reqSize =
|
let reqSize =
|
||||||
new Downsampler().calculateScaling(typeValue, imageInfo.size.width, imageInfo.size.height, request.targetWidth,
|
new Downsampler().calculateScaling(typeValue, size.width, size.height, request.targetWidth,
|
||||||
request.targetHeight, request.downsampType)
|
request.targetHeight, request.downsampType)
|
||||||
opts = {
|
opts = {
|
||||||
editable: true,
|
editable: true,
|
||||||
|
@ -682,12 +682,12 @@ async function requestJob(request: RequestJobRequest, requestList?: List<ImageKn
|
||||||
type:typeValue
|
type:typeValue
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
let size = (await imageSource.getImageInfo()).size
|
||||||
let imageInfo = await imageSource.getImageInfo()
|
// let imageInfo = await imageSource.getImageInfo()
|
||||||
if ((request.downsampType !== undefined && request.downsampType !== DownsampleStrategy.NONE) &&
|
if ((request.downsampType !== undefined && request.downsampType !== DownsampleStrategy.NONE) &&
|
||||||
request.requestSource == ImageKnifeRequestSource.SRC) {
|
request.requestSource == ImageKnifeRequestSource.SRC) {
|
||||||
let reqSize =
|
let reqSize =
|
||||||
new Downsampler().calculateScaling(typeValue, imageInfo.size.width, imageInfo.size.height, request.targetWidth,
|
new Downsampler().calculateScaling(typeValue, size.width, size.height, request.targetWidth,
|
||||||
request.targetHeight, request.downsampType)
|
request.targetHeight, request.downsampType)
|
||||||
|
|
||||||
decodingOptions = {
|
decodingOptions = {
|
||||||
|
@ -698,7 +698,7 @@ async function requestJob(request: RequestJobRequest, requestList?: List<ImageKn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let size = (await imageSource.getImageInfo()).size
|
|
||||||
await imageSource.createPixelMap(decodingOptions)
|
await imageSource.createPixelMap(decodingOptions)
|
||||||
.then((pixelmap: PixelMap) => {
|
.then((pixelmap: PixelMap) => {
|
||||||
resPixelmap = pixelmap
|
resPixelmap = pixelmap
|
||||||
|
|
|
@ -20,7 +20,7 @@ export class FitCenter implements BaseDownsampling {
|
||||||
return "FitCenter"
|
return "FitCenter"
|
||||||
}
|
}
|
||||||
|
|
||||||
getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy
|
getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy |undefined
|
||||||
): number {
|
): number {
|
||||||
if (downsampType===DownsampleStrategy.FIT_CENTER_MEMORY) {
|
if (downsampType===DownsampleStrategy.FIT_CENTER_MEMORY) {
|
||||||
const widthPercentage = requestedWidth / sourceWidth
|
const widthPercentage = requestedWidth / sourceWidth
|
||||||
|
@ -34,7 +34,7 @@ export class FitCenter implements BaseDownsampling {
|
||||||
}
|
}
|
||||||
|
|
||||||
//实现 getSampleSizeRounding 方法
|
//实现 getSampleSizeRounding 方法
|
||||||
getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy
|
getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy|undefined
|
||||||
): number {
|
): number {
|
||||||
if (downsampType===DownsampleStrategy.FIT_CENTER_QUALITY) {
|
if (downsampType===DownsampleStrategy.FIT_CENTER_QUALITY) {
|
||||||
return SampleSizeRounding.QUALITY;
|
return SampleSizeRounding.QUALITY;
|
||||||
|
@ -121,7 +121,7 @@ export class CenterInside implements BaseDownsampling {
|
||||||
return "CenterInside"
|
return "CenterInside"
|
||||||
}
|
}
|
||||||
|
|
||||||
getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy
|
getScaleFactor(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy|undefined
|
||||||
): number {
|
): number {
|
||||||
//获取 FIT_CENTER 的缩放因子
|
//获取 FIT_CENTER 的缩放因子
|
||||||
const fitCenterScaleFactor: ESObject =
|
const fitCenterScaleFactor: ESObject =
|
||||||
|
@ -131,21 +131,20 @@ export class CenterInside implements BaseDownsampling {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getScale(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy
|
getScale(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy|undefined
|
||||||
): number {
|
): number {
|
||||||
if (downsampType===DownsampleStrategy.FIT_CENTER_QUALITY) {
|
if (downsampType===DownsampleStrategy.FIT_CENTER_MEMORY) {
|
||||||
const widthPercentage = requestedWidth / sourceWidth
|
const widthPercentage = requestedWidth / sourceWidth
|
||||||
const heightPercentage = requestedHeight / sourceHeight
|
const heightPercentage = requestedHeight / sourceHeight
|
||||||
return Math.min(widthPercentage, heightPercentage)
|
return Math.min(widthPercentage, heightPercentage)
|
||||||
} else {
|
} else {
|
||||||
//类似 AT_LEAST,但只要求一个维度或另一个维度大于等于请求的尺寸
|
|
||||||
const maxIntegerFactor = Math.max(sourceHeight / requestedHeight, sourceWidth / requestedWidth);
|
const maxIntegerFactor = Math.max(sourceHeight / requestedHeight, sourceWidth / requestedWidth);
|
||||||
return maxIntegerFactor === 0 ? 1 : 1 / highestOneBit(maxIntegerFactor);
|
const a = maxIntegerFactor === 0 ? 1 : 1 / highestOneBit(maxIntegerFactor)
|
||||||
|
return a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy
|
getSampleSizeRounding(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy|undefined
|
||||||
): SampleSizeRounding {
|
): SampleSizeRounding {
|
||||||
//如果缩放因子为 1,表示没有缩放,优先选择质量
|
//如果缩放因子为 1,表示没有缩放,优先选择质量
|
||||||
if (this.getScaleFactor(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType) === 1) {
|
if (this.getScaleFactor(sourceWidth, sourceHeight, requestedWidth, requestedHeight, downsampType) === 1) {
|
||||||
|
@ -155,7 +154,7 @@ export class CenterInside implements BaseDownsampling {
|
||||||
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
|
getSampleSize(sourceWidth: number, sourceHeight: number, requestedWidth: number, requestedHeight: number,downsampType:DownsampleStrategy|undefined
|
||||||
): SampleSizeRounding {
|
): SampleSizeRounding {
|
||||||
if (downsampType===DownsampleStrategy.CENTER_INSIDE_MEMORY) {
|
if (downsampType===DownsampleStrategy.CENTER_INSIDE_MEMORY) {
|
||||||
return SampleSizeRounding.MEMORY;
|
return SampleSizeRounding.MEMORY;
|
||||||
|
|
|
@ -30,82 +30,33 @@ export interface calculateScaleType {
|
||||||
export class Downsampler {
|
export class Downsampler {
|
||||||
calculateScaling(
|
calculateScaling(
|
||||||
typeValue: string | null,
|
typeValue: string | null,
|
||||||
sourceHeight: number, //原始宽高
|
// TODO 宽高调整
|
||||||
sourceWidth: number | undefined, //原始宽高
|
sourceWidth: number | undefined, //原始宽高
|
||||||
requestHeight: number, //请求宽高
|
sourceHeight: number, //原始宽高
|
||||||
requestWidth: number, //请求宽高
|
requestWidth: number, //请求宽高
|
||||||
|
requestHeight: number, //请求宽高
|
||||||
downsampType: DownsampleStrategy | undefined,
|
downsampType: DownsampleStrategy | undefined,
|
||||||
|
|
||||||
): calculateScaleType {
|
): calculateScaleType {
|
||||||
let degreesToRotate: ESObject = 90;
|
|
||||||
const fileType = typeValue //获取图片类型
|
const fileType = typeValue //获取图片类型
|
||||||
let powerOfTwoWidth: number | null = null;
|
// TODO 命名修改 powerOfTwoWidth改为targetWidth
|
||||||
let powerOfTwoHeight: number | null = null;
|
let targetWidth: number | null = null;
|
||||||
let targetWidth: number = 0
|
let targetHeight: number | null = null;
|
||||||
let targetHeight: number = 0
|
|
||||||
|
|
||||||
if (sourceHeight <= 0 || sourceWidth == undefined || sourceWidth == null || sourceWidth <= 0) {
|
if (sourceHeight <= 0 || sourceWidth == undefined || sourceWidth == null || sourceWidth <= 0) {
|
||||||
throw new Error("Cannot found width or height");
|
throw new Error("Cannot found width or height"); // TODO catch
|
||||||
}
|
}
|
||||||
let orientedSourceWidth = sourceWidth;
|
if(downsampType===undefined){
|
||||||
let orientedSourceHeight = sourceHeight;
|
throw new Error("Cannot found downsampType");
|
||||||
if (this.isRotationRequired(degreesToRotate)) {
|
|
||||||
orientedSourceWidth = sourceHeight;
|
|
||||||
orientedSourceHeight = sourceWidth;
|
|
||||||
}
|
|
||||||
if (requestWidth && !requestHeight) {
|
|
||||||
targetWidth = this.round((requestHeight) * orientedSourceWidth / orientedSourceHeight)
|
|
||||||
} else if (requestHeight && !requestWidth) {
|
|
||||||
targetHeight = this.round((requestWidth) * orientedSourceHeight / orientedSourceWidth)
|
|
||||||
} else if (requestHeight && requestWidth) {
|
|
||||||
targetWidth =
|
|
||||||
requestHeight == sourceWidth ? (this.isRotationRequired(degreesToRotate) ? sourceHeight : sourceWidth) :
|
|
||||||
requestWidth;
|
|
||||||
targetHeight =
|
|
||||||
requestHeight == sourceHeight ? (this.isRotationRequired(degreesToRotate) ? sourceWidth : sourceHeight) :
|
|
||||||
requestWidth;
|
|
||||||
} else {
|
|
||||||
throw new Error("Cannot found width or height");
|
|
||||||
}
|
|
||||||
let exactScaleFactor: number | undefined
|
|
||||||
let rounding: SampleSizeRounding | undefined
|
|
||||||
if(downsampType===DownsampleStrategy.FIT_CENTER_MEMORY || downsampType===DownsampleStrategy.FIT_CENTER_QUALITY){
|
|
||||||
exactScaleFactor = new FitCenter()
|
|
||||||
.getScaleFactor(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight,downsampType)
|
|
||||||
rounding = new FitCenter()
|
|
||||||
.getSampleSizeRounding(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight,downsampType)
|
|
||||||
|
|
||||||
}else if(downsampType===DownsampleStrategy.NONE){
|
|
||||||
exactScaleFactor = new None()
|
|
||||||
.getScaleFactor(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight)
|
|
||||||
rounding = new None()
|
|
||||||
.getSampleSizeRounding(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight)
|
|
||||||
}else if( downsampType===DownsampleStrategy.AT_MOST){
|
|
||||||
exactScaleFactor = new AtMost()
|
|
||||||
.getScaleFactor(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight)
|
|
||||||
rounding = new AtMost()
|
|
||||||
.getSampleSizeRounding(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight)
|
|
||||||
}else if(downsampType===DownsampleStrategy.CENTER_INSIDE_MEMORY || downsampType===DownsampleStrategy.CENTER_INSIDE_QUALITY){
|
|
||||||
exactScaleFactor = new CenterInside()
|
|
||||||
.getScaleFactor(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight,downsampType)
|
|
||||||
rounding = new CenterInside()
|
|
||||||
.getSampleSizeRounding(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight,downsampType)
|
|
||||||
}else if(downsampType===DownsampleStrategy.CENTER_OUTSIDE){
|
|
||||||
exactScaleFactor = new CenterOutside()
|
|
||||||
.getScaleFactor(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight)
|
|
||||||
rounding = new CenterOutside()
|
|
||||||
.getSampleSizeRounding(orientedSourceWidth, orientedSourceHeight, targetWidth, targetHeight)
|
|
||||||
}
|
}
|
||||||
|
let downsampler = this.getDownsampler(downsampType);
|
||||||
|
let exactScaleFactor : number = downsampler.getScaleFactor(sourceWidth, sourceHeight, requestWidth, requestHeight, downsampType);
|
||||||
|
let rounding: SampleSizeRounding= downsampler.getSampleSizeRounding(sourceWidth, sourceHeight, requestWidth, requestHeight, downsampType);
|
||||||
if (exactScaleFactor==undefined|| exactScaleFactor <= 0 ) {
|
if (exactScaleFactor==undefined|| exactScaleFactor <= 0 ) {
|
||||||
throw new Error("Cannot round with exactScaleFactor");
|
throw new Error("Cannot round with exactScaleFactor");
|
||||||
}
|
}
|
||||||
if (rounding == undefined) {
|
let outWidth: number = this.round(exactScaleFactor * sourceWidth);
|
||||||
throw new Error("Cannot round with null rounding");
|
let outHeight: number = this.round(exactScaleFactor * sourceHeight);
|
||||||
}
|
let widthScaleFactor = sourceWidth / outWidth;
|
||||||
let outWidth: number = this.round(exactScaleFactor * orientedSourceWidth);
|
let heightScaleFactor = sourceHeight / outHeight;
|
||||||
let outHeight: number = this.round(exactScaleFactor * orientedSourceHeight);
|
|
||||||
let widthScaleFactor = orientedSourceWidth / outWidth;
|
|
||||||
let heightScaleFactor = orientedSourceHeight / outHeight;
|
|
||||||
let scaleFactor = rounding ==SampleSizeRounding.QUALITY ? Math.max(widthScaleFactor, heightScaleFactor) :
|
let scaleFactor = rounding ==SampleSizeRounding.QUALITY ? Math.max(widthScaleFactor, heightScaleFactor) :
|
||||||
Math.min(widthScaleFactor, heightScaleFactor) //将整型的缩放因子转换为2的次幂采样大小
|
Math.min(widthScaleFactor, heightScaleFactor) //将整型的缩放因子转换为2的次幂采样大小
|
||||||
let powerOfTwoSampleSize: number = scaleFactor;
|
let powerOfTwoSampleSize: number = scaleFactor;
|
||||||
|
@ -115,27 +66,36 @@ export class Downsampler {
|
||||||
}
|
}
|
||||||
//基于上一步得出的采样大小,根据不同的图片类型,计算采样后的图片尺寸
|
//基于上一步得出的采样大小,根据不同的图片类型,计算采样后的图片尺寸
|
||||||
if (fileType === "png") {
|
if (fileType === "png") {
|
||||||
powerOfTwoWidth = Math.floor(orientedSourceWidth / powerOfTwoSampleSize);
|
targetWidth = Math.floor(sourceWidth / powerOfTwoSampleSize);
|
||||||
powerOfTwoHeight = Math.floor(orientedSourceHeight / powerOfTwoSampleSize);
|
targetHeight = Math.floor(sourceHeight / powerOfTwoSampleSize);
|
||||||
} else if (fileType === "webp") {
|
} else if (fileType === "webp") {
|
||||||
powerOfTwoWidth = Math.round(orientedSourceWidth / powerOfTwoSampleSize);
|
targetWidth = Math.round(sourceWidth / powerOfTwoSampleSize);
|
||||||
powerOfTwoHeight = Math.round(orientedSourceHeight / powerOfTwoSampleSize);
|
targetHeight = Math.round(sourceHeight / powerOfTwoSampleSize);
|
||||||
} else {
|
} else {
|
||||||
powerOfTwoWidth = orientedSourceWidth / powerOfTwoSampleSize;
|
targetWidth = sourceWidth / powerOfTwoSampleSize;
|
||||||
powerOfTwoHeight = orientedSourceHeight / powerOfTwoSampleSize;
|
targetHeight = sourceHeight / powerOfTwoSampleSize;
|
||||||
|
}
|
||||||
|
return { targetWidth, targetHeight }
|
||||||
|
}
|
||||||
|
getDownsampler(downsampType:DownsampleStrategy) {
|
||||||
|
switch (downsampType) {
|
||||||
|
case DownsampleStrategy.FIT_CENTER_MEMORY:
|
||||||
|
case DownsampleStrategy.FIT_CENTER_QUALITY:
|
||||||
|
return new FitCenter();
|
||||||
|
case DownsampleStrategy.NONE:
|
||||||
|
return new None();
|
||||||
|
case DownsampleStrategy.AT_MOST:
|
||||||
|
return new AtMost();
|
||||||
|
case DownsampleStrategy.CENTER_INSIDE_MEMORY:
|
||||||
|
case DownsampleStrategy.CENTER_INSIDE_QUALITY:
|
||||||
|
return new CenterInside();
|
||||||
|
case DownsampleStrategy.CENTER_OUTSIDE:
|
||||||
|
return new CenterOutside();
|
||||||
|
default:
|
||||||
|
throw new Error('Unsupported downsampling strategy');
|
||||||
}
|
}
|
||||||
let a: calculateScaleType = {
|
|
||||||
"targetWidth": powerOfTwoWidth,
|
|
||||||
"targetHeight": powerOfTwoHeight
|
|
||||||
}
|
|
||||||
return a
|
|
||||||
}
|
}
|
||||||
|
|
||||||
round(value: number): number {
|
round(value: number): number {
|
||||||
return Math.floor(value + 0.5);
|
return Math.floor(value + 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
isRotationRequired(degreesToRotate: number): boolean {
|
|
||||||
return degreesToRotate == 90 || degreesToRotate == 270;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue