Skip to content

Commit 3d1a191

Browse files
authored
perf: optimize bilinear (#296)
close: #313
1 parent d91cf57 commit 3d1a191

File tree

4 files changed

+42
-15
lines changed

4 files changed

+42
-15
lines changed

scripts/benchmark/large.jpg

175 KB
Loading

scripts/benchmark/resize.benchmark.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// run with `ts-node-transpile-only scripts/benchmark/resize.benchmark.ts`
2+
3+
import { read } from '../../src';
4+
import { join } from 'path';
5+
6+
async function doAll() {
7+
const image = await read(join(__dirname, 'large.jpg'));
8+
9+
console.time('resize');
10+
11+
image.resize({ width: 6000, height: 4000, interpolationType: 'bilinear' });
12+
console.timeEnd('resize');
13+
}
14+
15+
doAll();

src/utils/interpolatePixel.ts

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -90,21 +90,28 @@ function interpolateBilinear(
9090
const px0 = Math.floor(column);
9191
const py0 = Math.floor(row);
9292

93-
if (px0 === column && py0 === row) {
94-
return interpolateBorder(px0, py0, channel, image);
95-
}
96-
9793
const px1 = px0 + 1;
9894
const py1 = py0 + 1;
9995

100-
const vx0y0 = interpolateBorder(px0, py0, channel, image);
101-
const vx1y0 = interpolateBorder(px1, py0, channel, image);
102-
const vx0y1 = interpolateBorder(px0, py1, channel, image);
103-
const vx1y1 = interpolateBorder(px1, py1, channel, image);
104-
105-
const r1 = (px1 - column) * vx0y0 + (column - px0) * vx1y0;
106-
const r2 = (px1 - column) * vx0y1 + (column - px0) * vx1y1;
107-
return round((py1 - row) * r1 + (row - py0) * r2);
96+
if (px1 < image.width && py1 < image.height && px0 >= 0 && py0 >= 0) {
97+
const vx0y0 = image.getValue(px0, py0, channel);
98+
const vx1y0 = image.getValue(px1, py0, channel);
99+
const vx0y1 = image.getValue(px0, py1, channel);
100+
const vx1y1 = image.getValue(px1, py1, channel);
101+
102+
const r1 = (px1 - column) * vx0y0 + (column - px0) * vx1y0;
103+
const r2 = (px1 - column) * vx0y1 + (column - px0) * vx1y1;
104+
return round((py1 - row) * r1 + (row - py0) * r2);
105+
} else {
106+
const vx0y0 = interpolateBorder(px0, py0, channel, image);
107+
const vx1y0 = interpolateBorder(px1, py0, channel, image);
108+
const vx0y1 = interpolateBorder(px0, py1, channel, image);
109+
const vx1y1 = interpolateBorder(px1, py1, channel, image);
110+
111+
const r1 = (px1 - column) * vx0y0 + (column - px0) * vx1y0;
112+
const r2 = (px1 - column) * vx0y1 + (column - px0) * vx1y1;
113+
return round((py1 - row) * r1 + (row - py0) * r2);
114+
}
108115
}
109116

110117
/**

src/utils/round.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,13 @@
55
* @returns The rounded value.
66
*/
77
export function round(value: number): number {
8-
if (value % 0.5 !== 0) {
9-
return Math.round(value);
8+
const integer = Math.trunc(value);
9+
const decimal = value - integer;
10+
if (decimal < 0.5) {
11+
return integer;
12+
} else if (decimal > 0.5) {
13+
return integer + 1;
14+
} else {
15+
return integer % 2 === 0 ? integer : integer + 1;
1016
}
11-
return Math.floor(value) % 2 === 0 ? Math.floor(value) : Math.ceil(value);
1217
}

0 commit comments

Comments
 (0)