mirror of
https://github.com/lovell/sharp.git
synced 2025-07-09 10:30:15 +02:00
Add ability to read and write native vips .v files (#500)
This commit is contained in:
parent
b69627891d
commit
f672f86b53
@ -507,7 +507,7 @@ In the above example if `input.png` is a 3 channel RGB image, `output.png` will
|
||||
|
||||
`path` is a String containing the path to write the image data to.
|
||||
|
||||
If an explicit output format is not selected, it will be inferred from the extension, with JPEG, PNG, WebP, TIFF and DZI supported. Note that RAW format is only supported for buffer output.
|
||||
If an explicit output format is not selected, it will be inferred from the extension, with JPEG, PNG, WebP, TIFF, DZI, and VIPS V format supported. Note that RAW format is only supported for buffer output.
|
||||
|
||||
`callback`, if present, is called with two arguments `(err, info)` where:
|
||||
|
||||
|
2
index.js
2
index.js
@ -975,7 +975,7 @@ Sharp.prototype.toFormat = function(formatOut) {
|
||||
}
|
||||
if (
|
||||
isDefined(formatOut) &&
|
||||
['jpeg', 'png', 'webp', 'raw', 'tiff', 'dz', 'input'].indexOf(formatOut) !== -1
|
||||
['jpeg', 'png', 'webp', 'raw', 'tiff', 'dz', 'input'].indexOf(formatOut) !== -1
|
||||
) {
|
||||
this.options.formatOut = formatOut;
|
||||
} else {
|
||||
|
@ -55,6 +55,9 @@ namespace sharp {
|
||||
bool IsDzZip(std::string const &str) {
|
||||
return EndsWith(str, ".zip") || EndsWith(str, ".ZIP") || EndsWith(str, ".szi") || EndsWith(str, ".SZI");
|
||||
}
|
||||
bool IsV(std::string const &str) {
|
||||
return EndsWith(str, ".v") || EndsWith(str, ".V") || EndsWith(str, ".vips") || EndsWith(str, ".VIPS");
|
||||
}
|
||||
|
||||
/*
|
||||
Provide a string identifier for the given image type.
|
||||
@ -73,6 +76,7 @@ namespace sharp {
|
||||
case ImageType::OPENSLIDE: id = "openslide"; break;
|
||||
case ImageType::PPM: id = "ppm"; break;
|
||||
case ImageType::FITS: id = "fits"; break;
|
||||
case ImageType::VIPS: id = "v"; break;
|
||||
case ImageType::RAW: id = "raw"; break;
|
||||
case ImageType::UNKNOWN: id = "unknown"; break;
|
||||
}
|
||||
@ -136,6 +140,8 @@ namespace sharp {
|
||||
imageType = ImageType::PPM;
|
||||
} else if (EndsWith(loader, "Fits")) {
|
||||
imageType = ImageType::FITS;
|
||||
} else if (EndsWith(loader, "Vips")) {
|
||||
imageType = ImageType::VIPS;
|
||||
} else if (EndsWith(loader, "Magick") || EndsWith(loader, "MagickFile")) {
|
||||
imageType = ImageType::MAGICK;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ namespace sharp {
|
||||
OPENSLIDE,
|
||||
PPM,
|
||||
FITS,
|
||||
VIPS,
|
||||
RAW,
|
||||
UNKNOWN
|
||||
};
|
||||
@ -39,6 +40,7 @@ namespace sharp {
|
||||
bool IsTiff(std::string const &str);
|
||||
bool IsDz(std::string const &str);
|
||||
bool IsDzZip(std::string const &str);
|
||||
bool IsV(std::string const &str);
|
||||
|
||||
/*
|
||||
Provide a string identifier for the given image type.
|
||||
|
@ -73,6 +73,7 @@ using sharp::IsWebp;
|
||||
using sharp::IsTiff;
|
||||
using sharp::IsDz;
|
||||
using sharp::IsDzZip;
|
||||
using sharp::IsV;
|
||||
using sharp::FreeCallback;
|
||||
using sharp::CalculateCrop;
|
||||
using sharp::counterProcess;
|
||||
@ -878,7 +879,9 @@ class PipelineWorker : public AsyncWorker {
|
||||
bool isTiff = IsTiff(baton->fileOut);
|
||||
bool isDz = IsDz(baton->fileOut);
|
||||
bool isDzZip = IsDzZip(baton->fileOut);
|
||||
bool matchInput = baton->formatOut == "input" && !(isJpeg || isPng || isWebp || isTiff || isDz || isDzZip);
|
||||
bool isV = IsV(baton->fileOut);
|
||||
bool matchInput = baton->formatOut == "input" &&
|
||||
!(isJpeg || isPng || isWebp || isTiff || isDz || isDzZip || isV);
|
||||
if (baton->formatOut == "jpeg" || isJpeg || (matchInput && inputImageType == ImageType::JPEG)) {
|
||||
// Write JPEG to file
|
||||
image.jpegsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
|
||||
@ -932,6 +935,12 @@ class PipelineWorker : public AsyncWorker {
|
||||
->set("layout", baton->tileLayout)
|
||||
);
|
||||
baton->formatOut = "dz";
|
||||
} else if (baton->formatOut == "v" || isV || (matchInput && inputImageType == ImageType::VIPS)) {
|
||||
// Write V to file
|
||||
image.vipssave(const_cast<char*>(baton->fileOut.data()), VImage::option()
|
||||
->set("strip", !baton->withMetadata)
|
||||
);
|
||||
baton->formatOut = "v";
|
||||
} else {
|
||||
// Unsupported output format
|
||||
(baton->err).append("Unsupported output format " + baton->fileOut);
|
||||
|
@ -139,7 +139,7 @@ NAN_METHOD(format) {
|
||||
// Which load/save operations are available for each compressed format?
|
||||
Local<Object> format = New<Object>();
|
||||
for (std::string f : {
|
||||
"jpeg", "png", "webp", "tiff", "magick", "openslide", "dz", "ppm", "fits", "gif", "svg", "pdf"
|
||||
"jpeg", "png", "webp", "tiff", "magick", "openslide", "dz", "ppm", "fits", "gif", "svg", "pdf", "v"
|
||||
}) {
|
||||
// Input
|
||||
Local<Boolean> hasInputFile =
|
||||
|
BIN
test/fixtures/expected/vfile.jpg
vendored
Normal file
BIN
test/fixtures/expected/vfile.jpg
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
3
test/fixtures/index.js
vendored
3
test/fixtures/index.js
vendored
@ -95,9 +95,12 @@ module.exports = {
|
||||
inputPngStripesV: getPath('stripesV.png'),
|
||||
inputPngStripesH: getPath('stripesH.png'),
|
||||
|
||||
inputV: getPath('vfile.v'),
|
||||
|
||||
outputJpg: getPath('output.jpg'),
|
||||
outputPng: getPath('output.png'),
|
||||
outputWebP: getPath('output.webp'),
|
||||
outputV: getPath('output.v'),
|
||||
outputZoinks: getPath('output.zoinks'), // an 'unknown' file extension
|
||||
|
||||
// Path for tests requiring human inspection
|
||||
|
BIN
test/fixtures/vfile.v
vendored
Normal file
BIN
test/fixtures/vfile.v
vendored
Normal file
Binary file not shown.
@ -781,6 +781,37 @@ describe('Input/output', function() {
|
||||
});
|
||||
}
|
||||
|
||||
if (sharp.format.v.input.file) {
|
||||
it("Load Vips V file", function(done) {
|
||||
sharp(fixtures.inputV)
|
||||
.jpeg()
|
||||
.toBuffer(function(err, data, info) {
|
||||
if (err) throw err;
|
||||
assert.strictEqual(true, data.length > 0);
|
||||
assert.strictEqual('jpeg', info.format);
|
||||
assert.strictEqual(70, info.width);
|
||||
assert.strictEqual(60, info.height);
|
||||
fixtures.assertSimilar(fixtures.expected('vfile.jpg'), data, done);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (sharp.format.v.output.file) {
|
||||
it("Save Vips V file", function(done) {
|
||||
sharp(fixtures.inputJpg)
|
||||
.extract({left: 910, top: 1105, width: 70, height: 60})
|
||||
.toFile(fixtures.outputV, function(err, info) {
|
||||
if(err) throw err;
|
||||
assert.strictEqual(true, info.size > 0);
|
||||
assert.strictEqual('v', info.format);
|
||||
assert.strictEqual(70, info.width);
|
||||
assert.strictEqual(60, info.height);
|
||||
fs.unlinkSync(fixtures.outputV);
|
||||
done();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (sharp.format.raw.output.buffer) {
|
||||
describe('Ouput raw, uncompressed image data', function() {
|
||||
it('1 channel greyscale image', function(done) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user