mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-19 08:31:43 +03:00
7099dd45a5
refs #10181 * Added initial handleImageSizes middleware * Implemented saveRaw method on local file storage * Wired up handleImageSizes middleware * Implemented delete for LocalFileStorage * Removed delete method from theme Storage class * Deleted sizes directory when theme is activated * Ensured that smaller images are not enlarged * Renamed sizes -> size * Exited middleware as early as possible * Called getStorage as late as possible * Updated image sizes middleware to handle dimension paths * Revert "Deleted sizes directory when theme is activated" This reverts commit 9204dfcc73a6a79d597dbf23651817bcbfc59991. * Revert "Removed delete method from theme Storage class" This reverts commit b45fdb405a05faeaf4bd87e977c4ac64ff96b057. * Revert "Implemented delete for LocalFileStorage" This reverts commit a587cd6bae45b68a293b2d5cfd9b7705a29e7bfa. * Fixed typo Co-Authored-By: allouis <fabien@allou.is> * Redirected to original image if no image_sizes config * Refactored redirection because rule of three * Updated comments * Added rubbish tests * Added @TODO comment for handleImageSizes tests * Added safeResizeImage method to image manipulator * Used image manipulator lib in image_size middleware
88 lines
2.8 KiB
JavaScript
88 lines
2.8 KiB
JavaScript
const Promise = require('bluebird');
|
|
const common = require('../common');
|
|
const fs = require('fs-extra');
|
|
|
|
/**
|
|
* @NOTE: Sharp cannot operate on the same image path, that's why we have to use in & out paths.
|
|
*
|
|
* We currently can't enable compression or having more config options, because of
|
|
* https://github.com/lovell/sharp/issues/1360.
|
|
*/
|
|
const process = (options = {}) => {
|
|
let sharp, img, originalData, originalSize;
|
|
|
|
try {
|
|
sharp = require('sharp');
|
|
} catch (err) {
|
|
return Promise.reject(new common.errors.InternalServerError({
|
|
message: 'Sharp wasn\'t installed',
|
|
code: 'SHARP_INSTALLATION',
|
|
err: err
|
|
}));
|
|
}
|
|
|
|
// @NOTE: workaround for Windows as libvips keeps a reference to the input file
|
|
// which makes it impossible to fs.unlink() it on cleanup stage
|
|
sharp.cache(false);
|
|
|
|
return fs.readFile(options.in)
|
|
.then((data) => {
|
|
originalData = data;
|
|
|
|
// @NOTE: have to use constructor with Buffer for sharp to be able to expose size property
|
|
img = sharp(data);
|
|
})
|
|
.then(() => img.metadata())
|
|
.then((metadata) => {
|
|
originalSize = metadata.size;
|
|
|
|
if (metadata.width > options.width) {
|
|
img.resize(options.width);
|
|
}
|
|
|
|
// CASE: if you call `rotate` it will automatically remove the orientation (and all other meta data) and rotates
|
|
// based on the orientation. It does not rotate if no orientation is set.
|
|
img.rotate();
|
|
return img.toBuffer({resolveWithObject: true});
|
|
})
|
|
.then(({data, info}) => {
|
|
if (info.size > originalSize) {
|
|
return fs.writeFile(options.out, originalData);
|
|
} else {
|
|
return fs.writeFile(options.out, data);
|
|
}
|
|
})
|
|
.catch((err) => {
|
|
throw new common.errors.InternalServerError({
|
|
message: 'Unable to manipulate image.',
|
|
err: err,
|
|
code: 'IMAGE_PROCESSING'
|
|
});
|
|
});
|
|
};
|
|
|
|
const resizeImage = (originalBuffer, {width, height} = {}) => {
|
|
const sharp = require('sharp');
|
|
return sharp(originalBuffer)
|
|
.resize(width, height, {
|
|
// CASE: dont make the image bigger than it was
|
|
withoutEnlargement: true
|
|
})
|
|
// CASE: Automatically remove metadata and rotate based on the orientation.
|
|
.rotate()
|
|
.toBuffer()
|
|
.then((resizedBuffer) => {
|
|
return resizedBuffer.length < originalBuffer.length ? resizedBuffer : originalBuffer;
|
|
});
|
|
};
|
|
|
|
module.exports.process = process;
|
|
module.exports.safeResizeImage = (buffer, options) => {
|
|
try {
|
|
require('sharp');
|
|
return resizeImage(buffer, options);
|
|
} catch (e) {
|
|
return Promise.resolve(buffer);
|
|
}
|
|
};
|