Skip to content

Commit

Permalink
Added mozjpeg defaults for jpeg compression (#484)
Browse files Browse the repository at this point in the history
refs TryGhost/Product#4140
- added `mozjpeg: true` for all jpeg formats to reduce file sizes
- added some basic integration tests as the existing unit tests don't actually verify any file creation/compression
  • Loading branch information
9larsons authored Nov 15, 2023
1 parent e746792 commit ce379d7
Show file tree
Hide file tree
Showing 12 changed files with 155 additions and 4 deletions.
10 changes: 9 additions & 1 deletion packages/image-transform/lib/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,16 @@ const unsafeResizeFromBuffer = async (originalBuffer, options = {}) => {
// CASE: Automatically remove metadata and rotate based on the orientation.
.rotate();

const metadata = await s.metadata();

if (options.format) {
s = s.toFormat(options.format);
if (options.format === 'jpeg') {
s.jpeg({mozjpeg: true}); // .jpeg sets format
} else {
s = s.toFormat(options.format);
}
} else if (metadata.format === 'jpeg') {
s.jpeg({mozjpeg: true}); // .jpeg sets format
}

const resizedBuffer = await s.toBuffer();
Expand Down
12 changes: 12 additions & 0 deletions packages/image-transform/test/integration/fixtures/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const path = require('path');

// Helpers
const getPath = function (filename) {
return path.join(__dirname, filename);
};

module.exports = {
inputJpeg: getPath('saw.jpg'),
inputPng: getPath('saw.png'),
inputWebp: getPath('tree.webp')
};
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
129 changes: 129 additions & 0 deletions packages/image-transform/test/integration/transform.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
'use strict';

const sharp = require('sharp');
// eslint-disable-next-line ghost/ghost-custom/node-assert-strict
const assert = require('assert');
const imageTransform = require('../../');
const path = require('path');
const fixtures = require('./fixtures');

const makeOutpath = (inPath, mod, ext) => {
if (!ext) {
ext = path.extname(inPath);
}
const fileName = path.basename(inPath, ext);
return path.join(__dirname, `fixtures/output/${fileName}_${mod}${ext}`);
};

describe('Image compression', function () {
describe('JPEG', function () {
let fixtureBuffer;

before(async function () {
fixtureBuffer = await sharp(fixtures.inputJpeg).toBuffer();
});

it('should always compress JPEG images', async function () {
const inPath = fixtures.inputJpeg;
const outPath = makeOutpath(inPath, 'base', '.jpg');

await imageTransform.resizeFromPath({in: inPath, out: outPath});

await sharp(outPath)
.toBuffer(function (err, result) {
if (err) {
throw err;
}
assert(result instanceof Buffer);
assert(result.length < fixtureBuffer.length);
});
});

it('should compress JPEG images with width attribute', async function () {
const inPath = fixtures.inputJpeg;
const outPath = makeOutpath(inPath, '1000w', '.jpg');

await imageTransform.resizeFromPath({in: inPath, out: outPath, width: 1000});

await sharp(outPath)
.toBuffer(function (err, result, info) {
if (err) {
throw err;
}
assert(result instanceof Buffer);
assert(result.length < fixtureBuffer.length);
assert(info.width === 1000);
});
});

it('can create a JPEG from another format by passing the format option', async function () {
const inputPngBuffer = await sharp(fixtures.inputPng).toBuffer();

const outputBuffer = await imageTransform.resizeFromBuffer(inputPngBuffer, {format: 'jpeg'});

sharp(outputBuffer).metadata().then(function (metadata) {
assert.equal(metadata.format, 'jpeg');
});
});
});

describe('PNG', function () {
let fixtureBuffer;

before(async function () {
fixtureBuffer = await sharp(fixtures.inputPng).toBuffer();
});

it('should compress PNG images with width attribute', async function () {
const inPath = fixtures.inputPng;
const outPath = makeOutpath(inPath, '1000w', '.png');

await imageTransform.resizeFromPath({in: inPath, out: outPath, width: 1000});

await sharp(outPath)
.toBuffer(function (err, result, info) {
if (err) {
throw err;
}
assert(result instanceof Buffer);
assert(result.length < fixtureBuffer.length);
assert(info.width === 1000);
});
});

it('can create PNG from another format by passing the format option', async function () {
const inputJpegBuffer = await sharp(fixtures.inputJpeg).toBuffer();

const outputBuffer = await imageTransform.resizeFromBuffer(inputJpegBuffer, {format: 'png'});

sharp(outputBuffer).metadata().then(function (metadata) {
assert.equal(metadata.format, 'png');
});
});
});

describe('WEBP', function () {
let fixtureBuffer;

before(async function () {
fixtureBuffer = await sharp(fixtures.inputWebp).toBuffer();
});

it('should compress WEBP images with width attribute', async function () {
const inPath = fixtures.inputWebp;
const outPath = makeOutpath(inPath, '1000w', '.webp');

await imageTransform.resizeFromPath({in: inPath, out: outPath, width: 1000});

await sharp(outPath)
.toBuffer(function (err, result, info) {
if (err) {
throw err;
}
assert(result instanceof Buffer);
assert(result.length < fixtureBuffer.length);
assert(info.width === 1000);
});
});
});
});
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Switch these lines once there are useful utils
const testUtils = require('./utils');
const testUtils = require('../utils');
const fs = require('fs-extra');
const errors = require('@tryghost/errors');

const transform = require('../');
const transform = require('../..');

describe('Transform', function () {
afterEach(function () {
Expand Down Expand Up @@ -86,7 +86,9 @@ describe('Transform', function () {
sharpInstance = {
resize: sinon.stub().returnsThis(),
rotate: sinon.stub().returnsThis(),
toBuffer: sinon.stub()
toBuffer: sinon.stub(),
jpeg: sinon.stub().returnsThis(),
metadata: sinon.stub().returns({format: 'test'})
};

sharp = sinon.stub().callsFake(() => {
Expand Down
Binary file added packages/outputJpeg.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit ce379d7

Please sign in to comment.