Skip to content

Commit 7828ddc

Browse files
authored
Merge pull request #164 from wchaws/dev
feat: add threshold
2 parents b653246 + c50edfe commit 7828ddc

File tree

5 files changed

+101
-0
lines changed

5 files changed

+101
-0
lines changed

source/new-image-handler/src/processor/image/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { RotateAction } from './rotate';
2020
import { RoundedCornersAction } from './rounded-corners';
2121
import { SharpenAction } from './sharpen';
2222
import { StripMetadataAction } from './strip-metadata';
23+
import { ThresholdAction } from './threshold';
2324
import { WatermarkAction } from './watermark';
2425

2526
export interface IImageInfo {
@@ -226,6 +227,7 @@ ImageProcessor.getInstance().register(
226227
new InfoAction(),
227228
new CgifAction(),
228229
new StripMetadataAction(),
230+
new ThresholdAction(),
229231
);
230232

231233

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { IImageContext } from '.';
2+
import { IActionOpts, ReadOnly, InvalidArgument } from '..';
3+
import { BaseImageAction } from './_base';
4+
5+
6+
export interface ThresholdOpts extends IActionOpts {
7+
threshold: number;
8+
}
9+
10+
11+
export class ThresholdAction extends BaseImageAction {
12+
public readonly name: string = 'threshold';
13+
14+
public beforeProcess(ctx: IImageContext, params: string[], _: number): void {
15+
const opts = this.validate(params);
16+
17+
if (ctx.metadata.size && (ctx.metadata.size < opts.threshold)) {
18+
ctx.mask.disableAll();
19+
}
20+
}
21+
22+
public validate(params: string[]): ReadOnly<ThresholdOpts> {
23+
if (params.length !== 2) {
24+
throw new InvalidArgument(`Invalid ${this.name} params, incomplete param`);
25+
}
26+
const t = Number.parseInt(params[1], 10);
27+
if (t <= 0) {
28+
throw new InvalidArgument(`Invalid ${this.name} params, threshold must be greater than zero`);
29+
}
30+
return {
31+
threshold: t,
32+
};
33+
}
34+
35+
public async process(_1: IImageContext, _2: string[]): Promise<void> {
36+
return Promise.resolve();
37+
}
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
*.gif
2+
*.png
3+
*.PNG
4+
*.jpeg
5+
*.jpg
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// import * as sharp from 'sharp';
2+
import { ThresholdAction } from '../../../src/processor/image/threshold';
3+
import { mkctx } from './utils';
4+
5+
test(`${ThresholdAction.name} action validate`, () => {
6+
const action = new ThresholdAction();
7+
const param = action.validate('threshold,100'.split(','));
8+
expect(param.threshold).toBe(100);
9+
10+
expect(() => {
11+
action.validate('threshold'.split(','));
12+
}).toThrow(/Invalid/);
13+
14+
expect(() => {
15+
action.validate('threshold,-1'.split(','));
16+
}).toThrow(/Invalid.*greater than zero/);
17+
18+
});
19+
20+
21+
test(`${ThresholdAction.name} beforeProcess mask disabled`, async () => {
22+
const ctx = await mkctx('example.jpg', ['threshold,23000']);
23+
const action = new ThresholdAction();
24+
25+
await action.beforeProcess(ctx, 'threshold,23000'.split(','), 0);
26+
expect(ctx.mask.isDisabled(0)).toBeTruthy();
27+
});
28+
29+
30+
test(`${ThresholdAction.name} beforeProcess mask enabled`, async () => {
31+
const ctx = await mkctx('example.jpg', ['threshold,100']);
32+
const action = new ThresholdAction();
33+
34+
await action.beforeProcess(ctx, 'threshold,100'.split(','), 0);
35+
expect(ctx.mask.isEnabled(0)).toBeTruthy();
36+
});

source/new-image-handler/test/processor/index.test.ts

+20
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,26 @@ test('image/resize,w_50/crop,w_100,h_100/rounded-corners,r_100/format,png', asyn
7474
expect(info.channels).toBe(4);
7575
});
7676

77+
test('example.jpg?x-oss-process=image/resize,w_50/threshold,10', async () => {
78+
const ctx = await ImageProcessor.getInstance().newContext('example.jpg', 'image/resize,w_50/threshold,10'.split('/'), fixtureStore);
79+
await ImageProcessor.getInstance().process(ctx);
80+
const { info } = await ctx.image.toBuffer({ resolveWithObject: true });
81+
82+
expect(info.width).toBe(50);
83+
expect(info.height).toBe(33);
84+
expect(info.channels).toBe(3);
85+
});
86+
87+
test('example.jpg?x-oss-process=image/resize,w_50/threshold,23000', async () => {
88+
const ctx = await ImageProcessor.getInstance().newContext('example.jpg', 'image/resize,w_50/threshold,23000'.split('/'), fixtureStore);
89+
await ImageProcessor.getInstance().process(ctx);
90+
const { info } = await ctx.image.toBuffer({ resolveWithObject: true });
91+
92+
expect(info.width).toBe(400);
93+
expect(info.height).toBe(267);
94+
expect(info.channels).toBe(3);
95+
});
96+
7797
test('image/resize,w_20/indexcrop,x_50,i_0/', async () => {
7898
const ctx = await ImageProcessor.getInstance().newContext('example.jpg', 'image/resize,w_20/indexcrop,x_50,i_0/'.split('/'), fixtureStore);
7999
await ImageProcessor.getInstance().process(ctx);

0 commit comments

Comments
 (0)