Improve perf/accuracy of nearest neighbour integral upsample

This commit is contained in:
Lovell Fuller 2017-04-30 20:54:48 +01:00
parent 52bea15ad7
commit 4d1a1694cd
3 changed files with 67 additions and 18 deletions

View File

@ -14,6 +14,10 @@ Requires libvips v8.5.2.
[#607](https://github.com/lovell/sharp/issues/607)
[@puzrin](https://github.com/puzrin)
* Improve performance and accuracy of nearest neighbour integral upsampling.
[#752](https://github.com/lovell/sharp/issues/752)
[@MrIbby](https://github.com/MrIbby)
* Ensure ARM64 pre-built binaries use correct C++11 ABI version.
[#772](https://github.com/lovell/sharp/issues/772)
[@ajiratech2](https://github.com/ajiratech2)

View File

@ -417,16 +417,24 @@ class PipelineWorker : public Nan::AsyncWorker {
->set("centre", baton->centreSampling));
}
}
// Perform affine enlargement
// Perform enlargement
if (yresidual > 1.0 || xresidual > 1.0) {
vips::VInterpolate interpolator = vips::VInterpolate::new_from_name(baton->interpolator.data());
if (yresidual > 1.0) {
image = image.affine({1.0, 0.0, 0.0, yresidual}, VImage::option()
->set("interpolate", interpolator));
}
if (xresidual > 1.0) {
image = image.affine({xresidual, 0.0, 0.0, 1.0}, VImage::option()
->set("interpolate", interpolator));
if (trunc(xresidual) == xresidual && trunc(yresidual) == yresidual && baton->interpolator == "nearest") {
// Fast, integral nearest neighbour enlargement
image = image.zoom(xresidual, yresidual);
} else {
// Floating point affine transformation
vips::VInterpolate interpolator = vips::VInterpolate::new_from_name(baton->interpolator.data());
if (yresidual > 1.0 && xresidual > 1.0) {
image = image.affine({xresidual, 0.0, 0.0, yresidual}, VImage::option()
->set("interpolate", interpolator));
} else if (yresidual > 1.0) {
image = image.affine({1.0, 0.0, 0.0, yresidual}, VImage::option()
->set("interpolate", interpolator));
} else if (xresidual > 1.0) {
image = image.affine({xresidual, 0.0, 0.0, 1.0}, VImage::option()
->set("interpolate", interpolator));
}
}
}
}

View File

@ -35,17 +35,54 @@ describe('Interpolators and kernels', function () {
sharp.interpolator.locallyBoundedBicubic,
sharp.interpolator.vertexSplitQuadraticBasisSpline
].forEach(function (interpolator) {
it(interpolator, function (done) {
sharp(fixtures.inputJpg)
.resize(320, null, { interpolator: interpolator })
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual('jpeg', info.format);
assert.strictEqual(320, info.width);
fixtures.assertSimilar(fixtures.inputJpg, data, done);
});
describe(interpolator, function () {
it('x and y', function (done) {
sharp(fixtures.inputTiff8BitDepth)
.resize(200, 200, { interpolator: interpolator })
.png()
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual(200, info.width);
assert.strictEqual(200, info.height);
done();
});
});
it('x only', function (done) {
sharp(fixtures.inputTiff8BitDepth)
.resize(200, 21, { interpolator: interpolator })
.png()
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual(200, info.width);
assert.strictEqual(21, info.height);
done();
});
});
it('y only', function (done) {
sharp(fixtures.inputTiff8BitDepth)
.resize(21, 200, { interpolator: interpolator })
.png()
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual(21, info.width);
assert.strictEqual(200, info.height);
done();
});
});
});
});
it('nearest with integral factor', function (done) {
sharp(fixtures.inputTiff8BitDepth)
.resize(210, 210, { interpolator: 'nearest' })
.png()
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual(210, info.width);
assert.strictEqual(210, info.height);
done();
});
});
});
it('unknown kernel throws', function () {