Skip to content

Commit

Permalink
Expose mozjpeg quant_table flag
Browse files Browse the repository at this point in the history
  • Loading branch information
rexxars committed Jul 9, 2018
1 parent 5cb3548 commit 66989b8
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 0 deletions.
4 changes: 4 additions & 0 deletions docs/api-output.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ Use these JPEG options for output image.
- `options.progressive` **[Boolean][6]** use progressive (interlace) scan (optional, default `false`)
- `options.chromaSubsampling` **[String][1]** set to '4:4:4' to prevent chroma subsampling when quality <= 90 (optional, default `'4:2:0'`)
- `options.trellisQuantisation` **[Boolean][6]** apply trellis quantisation, requires mozjpeg (optional, default `false`)
- `options.quantisationTable` **[Number][8]** [quantisation table][9] to use, integer 0-8 (optional, default `0`)
- `options.quantizationTable` **[Number][8]** alternative spelling of quantisationTable (optional, default `0`)
- `options.overshootDeringing` **[Boolean][6]** apply overshoot deringing, requires mozjpeg (optional, default `false`)
- `options.optimiseScans` **[Boolean][6]** optimise progressive scans, forces progressive, requires mozjpeg (optional, default `false`)
- `options.optimizeScans` **[Boolean][6]** alternative spelling of optimiseScans (optional, default `false`)
Expand Down Expand Up @@ -312,3 +314,5 @@ Returns **Sharp**
[7]: https://nodejs.org/api/buffer.html

[8]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number

[9]: https://jcupitt.github.io/libvips/API/current/VipsForeignSave.html#vips-jpegsave
1 change: 1 addition & 0 deletions lib/constructor.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ const Sharp = function (input, options) {
jpegOvershootDeringing: false,
jpegOptimiseScans: false,
jpegOptimiseCoding: true,
jpegQuantisationTable: 0,
pngProgressive: false,
pngCompressionLevel: 9,
pngAdaptiveFiltering: false,
Expand Down
10 changes: 10 additions & 0 deletions lib/output.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ function withMetadata (withMetadata) {
* @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 {Number} [options.quantisationTable=0] - quantization table to use, integer 0-8, requires mozjpeg
* @param {Number} [options.quantizationTable=0] - alternative spelling of quantisationTable
* @param {Boolean} [options.force=true] - force JPEG output, otherwise attempt to use input format
* @returns {Sharp}
* @throws {Error} Invalid options
Expand Down Expand Up @@ -191,6 +193,14 @@ function jpeg (options) {
if (is.defined(options.optimiseCoding)) {
this._setBooleanOption('jpegOptimiseCoding', options.optimiseCoding);
}
options.quantisationTable = is.number(options.quantizationTable) ? options.quantizationTable : options.quantisationTable;
if (is.defined(options.quantisationTable)) {
if (is.integer(options.quantisationTable) && is.inRange(options.quantisationTable, 0, 8)) {
this.options.jpegQuantisationTable = options.quantisationTable;
} else {
throw new Error('Invalid quantisation table (integer, 0-8) ' + options.quantisationTable);
}
}
}
return this._updateFormatOut('jpeg', options);
}
Expand Down
4 changes: 4 additions & 0 deletions src/pipeline.cc
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,7 @@ class PipelineWorker : public Nan::AsyncWorker {
->set("interlace", baton->jpegProgressive)
->set("no_subsample", baton->jpegChromaSubsampling == "4:4:4")
->set("trellis_quant", baton->jpegTrellisQuantisation)
->set("quant_table", baton->jpegQuantisationTable)
->set("overshoot_deringing", baton->jpegOvershootDeringing)
->set("optimize_scans", baton->jpegOptimiseScans)
->set("optimize_coding", baton->jpegOptimiseCoding)));
Expand Down Expand Up @@ -848,6 +849,7 @@ class PipelineWorker : public Nan::AsyncWorker {
->set("interlace", baton->jpegProgressive)
->set("no_subsample", baton->jpegChromaSubsampling == "4:4:4")
->set("trellis_quant", baton->jpegTrellisQuantisation)
->set("quant_table", baton->jpegQuantisationTable)
->set("overshoot_deringing", baton->jpegOvershootDeringing)
->set("optimize_scans", baton->jpegOptimiseScans)
->set("optimize_coding", baton->jpegOptimiseCoding));
Expand Down Expand Up @@ -927,6 +929,7 @@ class PipelineWorker : public Nan::AsyncWorker {
{"interlace", baton->jpegProgressive ? "TRUE" : "FALSE"},
{"no_subsample", baton->jpegChromaSubsampling == "4:4:4" ? "TRUE": "FALSE"},
{"trellis_quant", baton->jpegTrellisQuantisation ? "TRUE" : "FALSE"},
{"quant_table", std::to_string(baton->jpegQuantisationTable)},
{"overshoot_deringing", baton->jpegOvershootDeringing ? "TRUE": "FALSE"},
{"optimize_scans", baton->jpegOptimiseScans ? "TRUE": "FALSE"},
{"optimize_coding", baton->jpegOptimiseCoding ? "TRUE": "FALSE"}
Expand Down Expand Up @@ -1266,6 +1269,7 @@ NAN_METHOD(pipeline) {
baton->jpegProgressive = AttrTo<bool>(options, "jpegProgressive");
baton->jpegChromaSubsampling = AttrAsStr(options, "jpegChromaSubsampling");
baton->jpegTrellisQuantisation = AttrTo<bool>(options, "jpegTrellisQuantisation");
baton->jpegQuantisationTable = AttrTo<uint32_t>(options, "jpegQuantisationTable");
baton->jpegOvershootDeringing = AttrTo<bool>(options, "jpegOvershootDeringing");
baton->jpegOptimiseScans = AttrTo<bool>(options, "jpegOptimiseScans");
baton->jpegOptimiseCoding = AttrTo<bool>(options, "jpegOptimiseCoding");
Expand Down
2 changes: 2 additions & 0 deletions src/pipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ struct PipelineBaton {
bool jpegProgressive;
std::string jpegChromaSubsampling;
bool jpegTrellisQuantisation;
int jpegQuantisationTable;
bool jpegOvershootDeringing;
bool jpegOptimiseScans;
bool jpegOptimiseCoding;
Expand Down Expand Up @@ -188,6 +189,7 @@ struct PipelineBaton {
jpegProgressive(false),
jpegChromaSubsampling("4:2:0"),
jpegTrellisQuantisation(false),
jpegQuantisationTable(0),
jpegOvershootDeringing(false),
jpegOptimiseScans(false),
jpegOptimiseCoding(true),
Expand Down
41 changes: 41 additions & 0 deletions test/unit/io.js
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,16 @@ describe('Input/output', function () {
});
});

describe('Invalid JPEG quantisation table', function () {
[-1, 88.2, 'test'].forEach(function (table) {
it(table.toString(), function () {
assert.throws(function () {
sharp().jpeg({ quantisationTable: table });
});
});
});
});

it('Progressive JPEG image', function (done) {
sharp(fixtures.inputJpg)
.resize(320, 240)
Expand Down Expand Up @@ -856,6 +866,37 @@ describe('Input/output', function () {
});
});

it('Specifying quantisation table provides different JPEG', function (done) {
// First generate with default quantisation table
sharp(fixtures.inputJpg)
.resize(320, 240)
.jpeg({ optimiseCoding: false })
.toBuffer(function (err, withDefaultQuantisationTable, withInfo) {
if (err) throw err;
assert.strictEqual(true, withDefaultQuantisationTable.length > 0);
assert.strictEqual(withDefaultQuantisationTable.length, withInfo.size);
assert.strictEqual('jpeg', withInfo.format);
assert.strictEqual(320, withInfo.width);
assert.strictEqual(240, withInfo.height);
// Then generate with different quantisation table
sharp(fixtures.inputJpg)
.resize(320, 240)
.jpeg({ optimiseCoding: false, quantisationTable: 3 })
.toBuffer(function (err, withQuantTable3, withoutInfo) {
if (err) throw err;
assert.strictEqual(true, withQuantTable3.length > 0);
assert.strictEqual(withQuantTable3.length, withoutInfo.size);
assert.strictEqual('jpeg', withoutInfo.format);
assert.strictEqual(320, withoutInfo.width);
assert.strictEqual(240, withoutInfo.height);

// Verify image is same (as mozjpeg may not be present) size or less
assert.strictEqual(true, withQuantTable3.length <= withDefaultQuantisationTable.length);
done();
});
});
});

it('Convert SVG to PNG at default 72DPI', function (done) {
sharp(fixtures.inputSvg)
.resize(1024)
Expand Down

0 comments on commit 66989b8

Please sign in to comment.