Compare commits

...

4 Commits

Author SHA1 Message Date
田双明 e086bb8630
update library/src/main/ets/model/ImageKnifeOption.ets.
Signed-off-by: 田双明 <tianshuangming@h-partners.com>
2024-09-26 03:14:51 +00:00
田双明 14be70d5e6
update library/src/main/ets/ImageKnifeLoader.ets.
Signed-off-by: 田双明 <tianshuangming@h-partners.com>
2024-09-26 03:12:32 +00:00
田双明 48c92b5fe7
update library/src/main/ets/downsampling/Downsampler.ets.
Signed-off-by: 田双明 <tianshuangming@h-partners.com>
2024-09-26 03:11:39 +00:00
田双明 fe9235d8b1
update library/src/main/ets/downsampling/Downsampler.ets.
简化代码

Signed-off-by: 田双明 <tianshuangming@h-partners.com>
2024-09-26 01:53:22 +00:00
3 changed files with 86 additions and 60 deletions

View File

@ -39,6 +39,16 @@ class RequestData {
/** /**
* ImageKnifeDispatcher 抽取出来的方法,因@Concurrent只能import方法故抽取到另一个类 * ImageKnifeDispatcher 抽取出来的方法,因@Concurrent只能import方法故抽取到另一个类
*/ */
interface GeneratedObjectLiteralInterface_1 {
height: number;
width: number;
}
interface Generated {
editable: boolean;
desiredSize: Size;
}
export class ImageKnifeLoader { export class ImageKnifeLoader {
static async parseImage(resBuf: ArrayBuffer, typeValue: string, fileKey: string, static async parseImage(resBuf: ArrayBuffer, typeValue: string, fileKey: string,
request: RequestJobRequest): Promise<RequestJobResult> { request: RequestJobRequest): Promise<RequestJobResult> {
@ -75,19 +85,15 @@ export class ImageKnifeLoader {
} }
let size = (await imageSource.getImageInfo()).size let size = (await imageSource.getImageInfo()).size
if ((request.downsampType !== undefined && request.downsampType !== DownsampleStrategy.NONE) && try{
if ((request.downsampType !== DownsampleStrategy.NONE) &&
request.requestSource == ImageKnifeRequestSource.SRC ) { request.requestSource == ImageKnifeRequestSource.SRC ) {
let reqSize = decodingOptions =await ImageKnifeLoader.downsamplerReqSize(typeValue,request,size,ImageKnifeRequestSource.SRC)
new Downsampler().calculateScaling(typeValue, size.width, size.height, request.targetWidth,
request.targetHeight, request.downsampType)
decodingOptions = {
editable: request.requestSource === ImageKnifeRequestSource.SRC && request.transformation !== undefined ? true : false,
desiredSize: {
width: reqSize.targetWidth,
height: reqSize.targetHeight
}
} }
}catch(err){
return ImageKnifeLoader.makeEmptyResult("image.createImageSource failed")
} }
await imageSource.createPixelMap(decodingOptions) await imageSource.createPixelMap(decodingOptions)
.then((pixelmap: PixelMap) => { .then((pixelmap: PixelMap) => {
resPixelmap = pixelmap resPixelmap = pixelmap
@ -125,18 +131,13 @@ export class ImageKnifeLoader {
editable: true, editable: true,
desiredSize: defaultSize desiredSize: defaultSize
}; };
if ((request.downsampType !== DownsampleStrategy.NONE && request.downsampType !== undefined) && try{
if ((request.downsampType !== DownsampleStrategy.NONE) &&
request.requestSource == ImageKnifeRequestSource.SRC ) { request.requestSource == ImageKnifeRequestSource.SRC ) {
let reqSize = opts =await ImageKnifeLoader.downsamplerReqSize(typeValue,request,size)
new Downsampler().calculateScaling(typeValue, size.width, size.height, request.targetWidth,
request.targetHeight, request.downsampType)
opts = {
editable: true,
desiredSize: {
height: vp2px(reqSize.targetHeight),
width: vp2px(reqSize.targetWidth)
}
} }
}catch(err){
return ImageKnifeLoader.makeEmptyResult("image.createImageSource failed")
} }
await imageSource.createPixelMap(opts) await imageSource.createPixelMap(opts)
.then((pixelmap: PixelMap) => { .then((pixelmap: PixelMap) => {
@ -382,4 +383,25 @@ export class ImageKnifeLoader {
} }
return resBuf return resBuf
} }
static async downsamplerReqSize(typeValue:string,request:RequestJobRequest ,size:Size,SRC?:ImageKnifeRequestSource): Promise<image.DecodingOptions>{
let reqSize = new Downsampler().calculateScaling(typeValue, size.width, size.height, request.targetWidth, request.targetHeight, request.downsampType)
if(typeValue=="svg") {
return ({
editable: true,
desiredSize: ({
height: vp2px(reqSize.targetHeight),
width: vp2px(reqSize.targetWidth)
} as Size)
} as image.DecodingOptions )
}else {
return( {
editable: request.requestSource ===SRC && request.transformation !== undefined ? true : false,
desiredSize: ({
width: reqSize.targetWidth,
height: reqSize.targetHeight
}as Size)
}as image.DecodingOptions)
} }
}
}

View File

@ -27,54 +27,57 @@ export interface calculateScaleType {
targetHeight: number targetHeight: number
} }
export class Downsampler { export class Downsampler {
calculateScaling( calculateScaling(
typeValue: string |null, typeValue: string |null,
sourceWidth: number | undefined, //原始宽高 sourceWidth: number, //原始宽高
sourceHeight: number, //原始宽高 sourceHeight: number, //原始宽高
requestWidth: number, //请求宽高 requestWidth: number, //请求宽高
requestHeight: number, //请求宽高 requestHeight: number, //请求宽高
downsampType: DownsampleStrategy | undefined, downsampType: DownsampleStrategy,
): calculateScaleType { ): calculateScaleType {
const fileType = typeValue //获取图片类型
let targetWidth: number | null = null;//降采样之后的宽 if (sourceHeight <= 0 || sourceWidth <= 0) {
let targetHeight: number | null = null;//降采样之后的高 throw new Error(`Invalid width and height, sourceHeight:${sourceHeight}+ sourceWidth:${sourceWidth}`)
if (sourceHeight <= 0 || sourceWidth == undefined || sourceWidth == null || sourceWidth <= 0) {
throw new Error("Cannot found width or height")
}
if(downsampType===undefined){
throw new Error("Cannot found downsampType");
} }
let downsampler = this.getDownsampler(downsampType); let downsampler = this.getDownsampler(downsampType);
let exactScaleFactor : number = downsampler.getScaleFactor(sourceWidth, sourceHeight, requestWidth, requestHeight, downsampType); let exactScaleFactor: number =
let rounding: SampleSizeRounding= downsampler.getSampleSizeRounding(sourceWidth, sourceHeight, requestWidth, requestHeight, downsampType);//采样类型 downsampler.getScaleFactor(sourceWidth, sourceHeight, requestWidth, requestHeight, downsampType);
if (exactScaleFactor==undefined|| exactScaleFactor <= 0 ) { let rounding: SampleSizeRounding =
throw new Error("Cannot round with exactScaleFactor"); downsampler.getSampleSizeRounding(sourceWidth, sourceHeight, requestWidth, requestHeight, downsampType); //采样类型
//原始宽高和缩放系数的乘积
let outSize:Size = {
width: this.round(exactScaleFactor * sourceWidth),
height: this.round(exactScaleFactor * sourceHeight)
} }
let outWidth: number = this.round(exactScaleFactor * sourceWidth);//原始宽和缩放系数的乘积 let scaleFactor =
let outHeight: number = this.round(exactScaleFactor * sourceHeight);//原始高和缩放系数的乘积 rounding == SampleSizeRounding.QUALITY ? Math.max(sourceWidth / outSize.width, sourceHeight / outSize.height) :
let widthScaleFactor = sourceWidth / outWidth;//计算的缩放因子 Math.min(sourceWidth / outSize.width, sourceHeight / outSize.height) //将整型的缩放因子转换为2的次幂采样大小
let heightScaleFactor = sourceHeight / outHeight;//计算的缩放因子 scaleFactor = Math.max(1, highestOneBit(scaleFactor))
let scaleFactor = rounding ==SampleSizeRounding.QUALITY ? Math.max(widthScaleFactor, heightScaleFactor) : if (rounding == 0 && (scaleFactor < (1 / exactScaleFactor))) {
Math.min(widthScaleFactor, heightScaleFactor) //将整型的缩放因子转换为2的次幂采样大小 scaleFactor = scaleFactor << 1;
let powerOfTwoSampleSize: number = scaleFactor;
powerOfTwoSampleSize = Math.max(1, highestOneBit(scaleFactor))
if (rounding == 0 && (powerOfTwoSampleSize < (1 / exactScaleFactor))) {
powerOfTwoSampleSize = powerOfTwoSampleSize << 1;
} }
//基于上一步得出的采样大小,根据不同的图片类型,计算采样后的图片尺寸 //基于上一步得出的采样大小,根据不同的图片类型,计算采样后的图片尺寸
if (fileType === "png") { if (typeValue === "png") {
targetWidth = Math.floor(sourceWidth / powerOfTwoSampleSize); return {
targetHeight = Math.floor(sourceHeight / powerOfTwoSampleSize); targetWidth: Math.floor(sourceWidth / scaleFactor),
} else if (fileType === "webp") { targetHeight: Math.floor(sourceHeight / scaleFactor)
targetWidth = Math.round(sourceWidth / powerOfTwoSampleSize); }
targetHeight = Math.round(sourceHeight / powerOfTwoSampleSize); } else if (typeValue === "webp") {
return {
targetWidth: Math.round(sourceWidth / scaleFactor),
targetHeight: Math.round(sourceHeight / scaleFactor)
}
} else { } else {
targetWidth = sourceWidth / powerOfTwoSampleSize; return {
targetHeight = sourceHeight / powerOfTwoSampleSize; targetWidth: sourceWidth / scaleFactor,
targetHeight: sourceHeight / scaleFactor
} }
return { targetWidth, targetHeight }
} }
}
getDownsampler(downsampType: DownsampleStrategy) { getDownsampler(downsampType: DownsampleStrategy) {
switch (downsampType) { switch (downsampType) {
case DownsampleStrategy.FIT_CENTER_MEMORY: case DownsampleStrategy.FIT_CENTER_MEMORY:
@ -93,6 +96,7 @@ export class Downsampler {
throw new Error('Unsupported downsampling strategy'); throw new Error('Unsupported downsampling strategy');
} }
} }
round(value: number): number { round(value: number): number {
return Math.floor(value + 0.5); return Math.floor(value + 0.5);
} }

View File

@ -124,7 +124,7 @@ export class ImageKnifeOption {
onComplete?:(event:EventImage | undefined) => void onComplete?:(event:EventImage | undefined) => void
drawingColorFilter?: ColorFilter | drawing.ColorFilter drawingColorFilter?: ColorFilter | drawing.ColorFilter
// 下采样 // 下采样
@Trace downsampleOf?: DownsampleStrategy = DownsampleStrategy.NONE @Trace downsampleOf: DownsampleStrategy = DownsampleStrategy.NONE
constructor(option?:ImageOption) { constructor(option?:ImageOption) {
this.loadSrc = option?.loadSrc == undefined ? "" : option?.loadSrc this.loadSrc = option?.loadSrc == undefined ? "" : option?.loadSrc
this.placeholderSrc = option?.placeholderSrc this.placeholderSrc = option?.placeholderSrc
@ -145,7 +145,7 @@ export class ImageKnifeOption {
this.onLoadListener = option?.onLoadListener this.onLoadListener = option?.onLoadListener
this.onComplete = option?.onComplete this.onComplete = option?.onComplete
this.drawingColorFilter = option?.drawingColorFilter this.drawingColorFilter = option?.drawingColorFilter
this.downsampleOf = option?.downsampleOf this.downsampleOf = option?.downsampleOf==undefined?DownsampleStrategy.NONE:option?.downsampleOf
} }
} }