Allow floating point density input (#1362)

Metadata output will still remain integer
This commit is contained in:
Axel Eirola 2018-09-01 10:58:30 +03:00 committed by Lovell Fuller
parent bf3254cb16
commit 7d48a5ccf4
9 changed files with 28 additions and 18 deletions

View File

@ -18,7 +18,7 @@ If the overlay image contains an alpha channel then composition with premultipli
- `options.left` **[Number][4]?** the pixel offset from the left edge. - `options.left` **[Number][4]?** the pixel offset from the left edge.
- `options.tile` **[Boolean][5]** set to true to repeat the overlay image across the entire image with the given `gravity`. (optional, default `false`) - `options.tile` **[Boolean][5]** set to true to repeat the overlay image across the entire image with the given `gravity`. (optional, default `false`)
- `options.cutout` **[Boolean][5]** set to true to apply only the alpha channel of the overlay image to the input image, giving the appearance of one image being cut out of another. (optional, default `false`) - `options.cutout` **[Boolean][5]** set to true to apply only the alpha channel of the overlay image to the input image, giving the appearance of one image being cut out of another. (optional, default `false`)
- `options.density` **[Number][4]** integral number representing the DPI for vector overlay image. (optional, default `72`) - `options.density` **[Number][4]** number representing the DPI for vector overlay image. (optional, default `72`)
- `options.raw` **[Object][3]?** describes overlay when using raw pixel data. - `options.raw` **[Object][3]?** describes overlay when using raw pixel data.
- `options.raw.width` **[Number][4]?** - `options.raw.width` **[Number][4]?**
- `options.raw.height` **[Number][4]?** - `options.raw.height` **[Number][4]?**

View File

@ -12,7 +12,7 @@
- `options.failOnError` **[Boolean][4]** by default apply a "best effort" - `options.failOnError` **[Boolean][4]** by default apply a "best effort"
to decode images, even if the data is corrupt or invalid. Set this flag to true to decode images, even if the data is corrupt or invalid. Set this flag to true
if you'd rather halt processing and raise an error when loading invalid images. (optional, default `false`) if you'd rather halt processing and raise an error when loading invalid images. (optional, default `false`)
- `options.density` **[Number][5]** integral number representing the DPI for vector images. (optional, default `72`) - `options.density` **[Number][5]** number representing the DPI for vector images. (optional, default `72`)
- `options.page` **[Number][5]** page number to extract for multi-page input (GIF, TIFF) (optional, default `0`) - `options.page` **[Number][5]** page number to extract for multi-page input (GIF, TIFF) (optional, default `0`)
- `options.raw` **[Object][3]?** describes raw pixel input image data. See `raw()` for pixel ordering. - `options.raw` **[Object][3]?** describes raw pixel input image data. See `raw()` for pixel ordering.
- `options.raw.width` **[Number][5]?** - `options.raw.width` **[Number][5]?**

View File

@ -34,7 +34,7 @@ const is = require('./is');
* @param {Number} [options.left] - the pixel offset from the left edge. * @param {Number} [options.left] - the pixel offset from the left edge.
* @param {Boolean} [options.tile=false] - set to true to repeat the overlay image across the entire image with the given `gravity`. * @param {Boolean} [options.tile=false] - set to true to repeat the overlay image across the entire image with the given `gravity`.
* @param {Boolean} [options.cutout=false] - set to true to apply only the alpha channel of the overlay image to the input image, giving the appearance of one image being cut out of another. * @param {Boolean} [options.cutout=false] - set to true to apply only the alpha channel of the overlay image to the input image, giving the appearance of one image being cut out of another.
* @param {Number} [options.density=72] - integral number representing the DPI for vector overlay image. * @param {Number} [options.density=72] - number representing the DPI for vector overlay image.
* @param {Object} [options.raw] - describes overlay when using raw pixel data. * @param {Object} [options.raw] - describes overlay when using raw pixel data.
* @param {Number} [options.raw.width] * @param {Number} [options.raw.width]
* @param {Number} [options.raw.height] * @param {Number} [options.raw.height]

View File

@ -96,7 +96,7 @@ const debuglog = util.debuglog('sharp');
* @param {Boolean} [options.failOnError=false] - by default apply a "best effort" * @param {Boolean} [options.failOnError=false] - by default apply a "best effort"
* to decode images, even if the data is corrupt or invalid. Set this flag to true * to decode images, even if the data is corrupt or invalid. Set this flag to true
* if you'd rather halt processing and raise an error when loading invalid images. * if you'd rather halt processing and raise an error when loading invalid images.
* @param {Number} [options.density=72] - integral number representing the DPI for vector images. * @param {Number} [options.density=72] - number representing the DPI for vector images.
* @param {Number} [options.page=0] - page number to extract for multi-page input (GIF, TIFF) * @param {Number} [options.page=0] - page number to extract for multi-page input (GIF, TIFF)
* @param {Object} [options.raw] - describes raw pixel input image data. See `raw()` for pixel ordering. * @param {Object} [options.raw] - describes raw pixel input image data. See `raw()` for pixel ordering.
* @param {Number} [options.raw.width] * @param {Number} [options.raw.width]

View File

@ -36,7 +36,7 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
} }
// Density // Density
if (is.defined(inputOptions.density)) { if (is.defined(inputOptions.density)) {
if (is.integer(inputOptions.density) && is.inRange(inputOptions.density, 1, 2400)) { if (is.inRange(inputOptions.density, 1, 2400)) {
inputDescriptor.density = inputOptions.density; inputDescriptor.density = inputOptions.density;
} else { } else {
throw new Error('Invalid density (1 to 2400) ' + inputOptions.density); throw new Error('Invalid density (1 to 2400) ' + inputOptions.density);

View File

@ -55,7 +55,7 @@ namespace sharp {
descriptor->failOnError = AttrTo<bool>(input, "failOnError"); descriptor->failOnError = AttrTo<bool>(input, "failOnError");
// Density for vector-based input // Density for vector-based input
if (HasAttr(input, "density")) { if (HasAttr(input, "density")) {
descriptor->density = AttrTo<uint32_t>(input, "density"); descriptor->density = AttrTo<double>(input, "density");
} }
// Raw pixel input // Raw pixel input
if (HasAttr(input, "rawChannels")) { if (HasAttr(input, "rawChannels")) {
@ -228,7 +228,7 @@ namespace sharp {
->set("access", accessMethod) ->set("access", accessMethod)
->set("fail", descriptor->failOnError); ->set("fail", descriptor->failOnError);
if (imageType == ImageType::SVG || imageType == ImageType::PDF) { if (imageType == ImageType::SVG || imageType == ImageType::PDF) {
option->set("dpi", static_cast<double>(descriptor->density)); option->set("dpi", descriptor->density);
} }
if (imageType == ImageType::MAGICK) { if (imageType == ImageType::MAGICK) {
option->set("density", std::to_string(descriptor->density).data()); option->set("density", std::to_string(descriptor->density).data());
@ -270,7 +270,7 @@ namespace sharp {
->set("access", accessMethod) ->set("access", accessMethod)
->set("fail", descriptor->failOnError); ->set("fail", descriptor->failOnError);
if (imageType == ImageType::SVG || imageType == ImageType::PDF) { if (imageType == ImageType::SVG || imageType == ImageType::PDF) {
option->set("dpi", static_cast<double>(descriptor->density)); option->set("dpi", descriptor->density);
} }
if (imageType == ImageType::MAGICK) { if (imageType == ImageType::MAGICK) {
option->set("density", std::to_string(descriptor->density).data()); option->set("density", std::to_string(descriptor->density).data());
@ -355,8 +355,8 @@ namespace sharp {
/* /*
Set pixels/mm resolution based on a pixels/inch density. Set pixels/mm resolution based on a pixels/inch density.
*/ */
void SetDensity(VImage image, const int density) { void SetDensity(VImage image, const double density) {
const double pixelsPerMm = static_cast<double>(density) / 25.4; const double pixelsPerMm = density / 25.4;
image.set("Xres", pixelsPerMm); image.set("Xres", pixelsPerMm);
image.set("Yres", pixelsPerMm); image.set("Yres", pixelsPerMm);
image.set(VIPS_META_RESOLUTION_UNIT, "in"); image.set(VIPS_META_RESOLUTION_UNIT, "in");

View File

@ -49,7 +49,7 @@ namespace sharp {
char *buffer; char *buffer;
bool failOnError; bool failOnError;
size_t bufferLength; size_t bufferLength;
int density; double density;
int rawChannels; int rawChannels;
int rawWidth; int rawWidth;
int rawHeight; int rawHeight;
@ -63,7 +63,7 @@ namespace sharp {
buffer(nullptr), buffer(nullptr),
failOnError(FALSE), failOnError(FALSE),
bufferLength(0), bufferLength(0),
density(72), density(72.0),
rawChannels(0), rawChannels(0),
rawWidth(0), rawWidth(0),
rawHeight(0), rawHeight(0),
@ -186,7 +186,7 @@ namespace sharp {
/* /*
Set pixels/mm resolution based on a pixels/inch density. Set pixels/mm resolution based on a pixels/inch density.
*/ */
void SetDensity(VImage image, const int density); void SetDensity(VImage image, const double density);
/* /*
Check the proposed format supports the current dimensions. Check the proposed format supports the current dimensions.

BIN
test/fixtures/expected/svg14.4.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

View File

@ -939,6 +939,21 @@ describe('Input/output', function () {
}); });
}); });
it('Convert SVG to PNG at 14.4DPI', function (done) {
sharp(fixtures.inputSvg, { density: 14.4 })
.toFormat('png')
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual('png', info.format);
assert.strictEqual(20, info.width);
assert.strictEqual(20, info.height);
fixtures.assertSimilar(fixtures.expected('svg14.4.png'), data, function (err) {
if (err) throw err;
done();
});
});
});
it('Convert SVG with embedded images to PNG, respecting dimensions, autoconvert to PNG', function (done) { it('Convert SVG with embedded images to PNG, respecting dimensions, autoconvert to PNG', function (done) {
sharp(fixtures.inputSvgWithEmbeddedImages) sharp(fixtures.inputSvgWithEmbeddedImages)
.toBuffer(function (err, data, info) { .toBuffer(function (err, data, info) {
@ -1506,11 +1521,6 @@ describe('Input/output', function () {
sharp(null, { density: 'zoinks' }); sharp(null, { density: 'zoinks' });
}); });
}); });
it('Invalid density: float', function () {
assert.throws(function () {
sharp(null, { density: 0.5 });
});
});
it('Ignore unknown attribute', function () { it('Ignore unknown attribute', function () {
sharp(null, { unknown: true }); sharp(null, { unknown: true });
}); });