mirror of
https://github.com/lovell/sharp.git
synced 2025-07-09 18:40:16 +02:00
Expose libjpeg optimize_coding flag (#1265)
This commit is contained in:
parent
873aa6700f
commit
76c41eaf05
@ -192,6 +192,7 @@ const Sharp = function (input, options) {
|
|||||||
jpegTrellisQuantisation: false,
|
jpegTrellisQuantisation: false,
|
||||||
jpegOvershootDeringing: false,
|
jpegOvershootDeringing: false,
|
||||||
jpegOptimiseScans: false,
|
jpegOptimiseScans: false,
|
||||||
|
jpegOptimiseCoding: true,
|
||||||
pngProgressive: false,
|
pngProgressive: false,
|
||||||
pngCompressionLevel: 9,
|
pngCompressionLevel: 9,
|
||||||
pngAdaptiveFiltering: false,
|
pngAdaptiveFiltering: false,
|
||||||
|
@ -148,6 +148,8 @@ function withMetadata (withMetadata) {
|
|||||||
* @param {Boolean} [options.overshootDeringing=false] - apply overshoot deringing, requires mozjpeg
|
* @param {Boolean} [options.overshootDeringing=false] - apply overshoot deringing, requires mozjpeg
|
||||||
* @param {Boolean} [options.optimiseScans=false] - optimise progressive scans, forces progressive, requires mozjpeg
|
* @param {Boolean} [options.optimiseScans=false] - optimise progressive scans, forces progressive, requires mozjpeg
|
||||||
* @param {Boolean} [options.optimizeScans=false] - alternative spelling of optimiseScans
|
* @param {Boolean} [options.optimizeScans=false] - alternative spelling of optimiseScans
|
||||||
|
* @param {Boolean} [options.optimiseCoding=true] - optimise Huffman coding tables
|
||||||
|
* @param {Boolean} [options.optimizeCoding=true] - alternative spelling of optimiseCoding
|
||||||
* @param {Boolean} [options.force=true] - force JPEG output, otherwise attempt to use input format
|
* @param {Boolean} [options.force=true] - force JPEG output, otherwise attempt to use input format
|
||||||
* @returns {Sharp}
|
* @returns {Sharp}
|
||||||
* @throws {Error} Invalid options
|
* @throws {Error} Invalid options
|
||||||
@ -185,6 +187,10 @@ function jpeg (options) {
|
|||||||
this.options.jpegProgressive = true;
|
this.options.jpegProgressive = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
options.optimiseCoding = is.bool(options.optimizeCoding) ? options.optimizeCoding : options.optimiseCoding;
|
||||||
|
if (is.defined(options.optimiseCoding)) {
|
||||||
|
this._setBooleanOption('jpegOptimiseCoding', options.optimiseCoding);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return this._updateFormatOut('jpeg', options);
|
return this._updateFormatOut('jpeg', options);
|
||||||
}
|
}
|
||||||
|
@ -735,7 +735,7 @@ class PipelineWorker : public Nan::AsyncWorker {
|
|||||||
->set("trellis_quant", baton->jpegTrellisQuantisation)
|
->set("trellis_quant", baton->jpegTrellisQuantisation)
|
||||||
->set("overshoot_deringing", baton->jpegOvershootDeringing)
|
->set("overshoot_deringing", baton->jpegOvershootDeringing)
|
||||||
->set("optimize_scans", baton->jpegOptimiseScans)
|
->set("optimize_scans", baton->jpegOptimiseScans)
|
||||||
->set("optimize_coding", TRUE)));
|
->set("optimize_coding", baton->jpegOptimiseCoding)));
|
||||||
baton->bufferOut = static_cast<char*>(area->data);
|
baton->bufferOut = static_cast<char*>(area->data);
|
||||||
baton->bufferOutLength = area->length;
|
baton->bufferOutLength = area->length;
|
||||||
area->free_fn = nullptr;
|
area->free_fn = nullptr;
|
||||||
@ -850,7 +850,7 @@ class PipelineWorker : public Nan::AsyncWorker {
|
|||||||
->set("trellis_quant", baton->jpegTrellisQuantisation)
|
->set("trellis_quant", baton->jpegTrellisQuantisation)
|
||||||
->set("overshoot_deringing", baton->jpegOvershootDeringing)
|
->set("overshoot_deringing", baton->jpegOvershootDeringing)
|
||||||
->set("optimize_scans", baton->jpegOptimiseScans)
|
->set("optimize_scans", baton->jpegOptimiseScans)
|
||||||
->set("optimize_coding", TRUE));
|
->set("optimize_coding", baton->jpegOptimiseCoding));
|
||||||
baton->formatOut = "jpeg";
|
baton->formatOut = "jpeg";
|
||||||
baton->channels = std::min(baton->channels, 3);
|
baton->channels = std::min(baton->channels, 3);
|
||||||
} else if (baton->formatOut == "png" || (mightMatchInput && isPng) || (willMatchInput &&
|
} else if (baton->formatOut == "png" || (mightMatchInput && isPng) || (willMatchInput &&
|
||||||
@ -929,7 +929,7 @@ class PipelineWorker : public Nan::AsyncWorker {
|
|||||||
{"trellis_quant", baton->jpegTrellisQuantisation ? "TRUE" : "FALSE"},
|
{"trellis_quant", baton->jpegTrellisQuantisation ? "TRUE" : "FALSE"},
|
||||||
{"overshoot_deringing", baton->jpegOvershootDeringing ? "TRUE": "FALSE"},
|
{"overshoot_deringing", baton->jpegOvershootDeringing ? "TRUE": "FALSE"},
|
||||||
{"optimize_scans", baton->jpegOptimiseScans ? "TRUE": "FALSE"},
|
{"optimize_scans", baton->jpegOptimiseScans ? "TRUE": "FALSE"},
|
||||||
{"optimize_coding", "TRUE"}
|
{"optimize_coding", baton->jpegOptimiseCoding ? "TRUE": "FALSE"}
|
||||||
};
|
};
|
||||||
suffix = AssembleSuffixString(extname, options);
|
suffix = AssembleSuffixString(extname, options);
|
||||||
}
|
}
|
||||||
@ -1268,6 +1268,7 @@ NAN_METHOD(pipeline) {
|
|||||||
baton->jpegTrellisQuantisation = AttrTo<bool>(options, "jpegTrellisQuantisation");
|
baton->jpegTrellisQuantisation = AttrTo<bool>(options, "jpegTrellisQuantisation");
|
||||||
baton->jpegOvershootDeringing = AttrTo<bool>(options, "jpegOvershootDeringing");
|
baton->jpegOvershootDeringing = AttrTo<bool>(options, "jpegOvershootDeringing");
|
||||||
baton->jpegOptimiseScans = AttrTo<bool>(options, "jpegOptimiseScans");
|
baton->jpegOptimiseScans = AttrTo<bool>(options, "jpegOptimiseScans");
|
||||||
|
baton->jpegOptimiseCoding = AttrTo<bool>(options, "jpegOptimiseCoding");
|
||||||
baton->pngProgressive = AttrTo<bool>(options, "pngProgressive");
|
baton->pngProgressive = AttrTo<bool>(options, "pngProgressive");
|
||||||
baton->pngCompressionLevel = AttrTo<uint32_t>(options, "pngCompressionLevel");
|
baton->pngCompressionLevel = AttrTo<uint32_t>(options, "pngCompressionLevel");
|
||||||
baton->pngAdaptiveFiltering = AttrTo<bool>(options, "pngAdaptiveFiltering");
|
baton->pngAdaptiveFiltering = AttrTo<bool>(options, "pngAdaptiveFiltering");
|
||||||
|
@ -104,6 +104,7 @@ struct PipelineBaton {
|
|||||||
bool jpegTrellisQuantisation;
|
bool jpegTrellisQuantisation;
|
||||||
bool jpegOvershootDeringing;
|
bool jpegOvershootDeringing;
|
||||||
bool jpegOptimiseScans;
|
bool jpegOptimiseScans;
|
||||||
|
bool jpegOptimiseCoding;
|
||||||
bool pngProgressive;
|
bool pngProgressive;
|
||||||
int pngCompressionLevel;
|
int pngCompressionLevel;
|
||||||
bool pngAdaptiveFiltering;
|
bool pngAdaptiveFiltering;
|
||||||
@ -189,6 +190,7 @@ struct PipelineBaton {
|
|||||||
jpegTrellisQuantisation(false),
|
jpegTrellisQuantisation(false),
|
||||||
jpegOvershootDeringing(false),
|
jpegOvershootDeringing(false),
|
||||||
jpegOptimiseScans(false),
|
jpegOptimiseScans(false),
|
||||||
|
jpegOptimiseCoding(true),
|
||||||
pngProgressive(false),
|
pngProgressive(false),
|
||||||
pngCompressionLevel(9),
|
pngCompressionLevel(9),
|
||||||
pngAdaptiveFiltering(false),
|
pngAdaptiveFiltering(false),
|
||||||
|
@ -826,6 +826,36 @@ describe('Input/output', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Optimise coding generates smaller output length', function (done) {
|
||||||
|
// First generate with optimize coding enabled (default)
|
||||||
|
sharp(fixtures.inputJpg)
|
||||||
|
.resize(320, 240)
|
||||||
|
.jpeg()
|
||||||
|
.toBuffer(function (err, withOptimiseCoding, withInfo) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual(true, withOptimiseCoding.length > 0);
|
||||||
|
assert.strictEqual(withOptimiseCoding.length, withInfo.size);
|
||||||
|
assert.strictEqual('jpeg', withInfo.format);
|
||||||
|
assert.strictEqual(320, withInfo.width);
|
||||||
|
assert.strictEqual(240, withInfo.height);
|
||||||
|
// Then generate with coding disabled
|
||||||
|
sharp(fixtures.inputJpg)
|
||||||
|
.resize(320, 240)
|
||||||
|
.jpeg({ optimizeCoding: false })
|
||||||
|
.toBuffer(function (err, withoutOptimiseCoding, withoutInfo) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual(true, withoutOptimiseCoding.length > 0);
|
||||||
|
assert.strictEqual(withoutOptimiseCoding.length, withoutInfo.size);
|
||||||
|
assert.strictEqual('jpeg', withoutInfo.format);
|
||||||
|
assert.strictEqual(320, withoutInfo.width);
|
||||||
|
assert.strictEqual(240, withoutInfo.height);
|
||||||
|
// Verify optimised image is of a smaller size
|
||||||
|
assert.strictEqual(true, withOptimiseCoding.length < withoutOptimiseCoding.length);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('Convert SVG to PNG at default 72DPI', function (done) {
|
it('Convert SVG to PNG at default 72DPI', function (done) {
|
||||||
sharp(fixtures.inputSvg)
|
sharp(fixtures.inputSvg)
|
||||||
.resize(1024)
|
.resize(1024)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user