Skip to content

Commit

Permalink
add flatten background color option (#86)
Browse files Browse the repository at this point in the history
* Update index.js

support flatten background color

* Update README.md

update README
  • Loading branch information
owlpro authored Aug 14, 2024
1 parent 4ef86d1 commit 0145ba7
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 33 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ try {
- __fit__ [string] - method by which the image should fit the width/height. Default = contain ([details](https://sharp.pixelplumbing.com/api-resize))
- __failOnError__ [boolean] - Set to false to avoid read problems for images from some phones (i.e Samsung) in the sharp lib. Default = true ([details](https://github.com/lovell/sharp/issues/1578))
- __withMetaData__ [boolean] - Keep metadata in the thumbnail (will increase file size)
- __flattenBackgroundColor__ [background colour] - parsed by the color module, defaults to #ffffff.

### Examples
```js
Expand Down
133 changes: 100 additions & 33 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ const { fail } = require('assert');
const PERCENTAGE = 10;
const RESPONSE_TYPE = 'buffer';

const fromBase64 = async (source, percentage, width, height, responseType, jpegOptions, fit, failOnError, withMetaData) => {
const fromBase64 = async (source, percentage, width, height, responseType, jpegOptions, fit, failOnError, withMetaData, flattenBackgroundColor) => {
const imageBuffer = Buffer.from(source, 'base64');
const dimensions = getDimensions(imageBuffer, percentage, { width, height });
const thumbnailBuffer = await sharpResize(imageBuffer, dimensions, jpegOptions, fit, failOnError, withMetaData);
const thumbnailBuffer = await sharpResize(imageBuffer, dimensions, jpegOptions, fit, failOnError, withMetaData, flattenBackgroundColor);

if (responseType === 'base64') {
return thumbnailBuffer.toString('base64');
Expand All @@ -24,13 +24,12 @@ const fromBase64 = async (source, percentage, width, height, responseType, jpegO
return thumbnailBuffer;
};

const fromUri = async (source, percentage, width, height, responseType, jpegOptions, fit, failOnError, withMetaData) => {
const fromUri = async (source, percentage, width, height, responseType, jpegOptions, fit, failOnError, withMetaData, flattenBackgroundColor) => {
const response = await axios.get(source.uri, { responseType: 'arraybuffer' });
const imageBuffer = Buffer.from(response.data, 'binary');

const dimensions = getDimensions(imageBuffer, percentage, { width, height });
const thumbnailBuffer = await sharpResize(imageBuffer, dimensions, jpegOptions, fit, failOnError, withMetaData);

const thumbnailBuffer = await sharpResize(imageBuffer, dimensions, jpegOptions, fit, failOnError, withMetaData, flattenBackgroundColor);

if (responseType === 'base64') {
return thumbnailBuffer.toString('base64');
Expand All @@ -39,11 +38,11 @@ const fromUri = async (source, percentage, width, height, responseType, jpegOpti
return thumbnailBuffer;
};

const fromPath = async (source, percentage, width, height, responseType, jpegOptions, fit, failOnError, withMetaData) => {
const fromPath = async (source, percentage, width, height, responseType, jpegOptions, fit, failOnError, withMetaData, flattenBackgroundColor) => {
const imageBuffer = fs.readFileSync(source);

const dimensions = getDimensions(imageBuffer, percentage, { width, height });
const thumbnailBuffer = await sharpResize(imageBuffer, dimensions, jpegOptions, fit, failOnError, withMetaData);
const thumbnailBuffer = await sharpResize(imageBuffer, dimensions, jpegOptions, fit, failOnError, withMetaData, flattenBackgroundColor);

if (responseType === 'base64') {
return thumbnailBuffer.toString('base64');
Expand All @@ -52,10 +51,21 @@ const fromPath = async (source, percentage, width, height, responseType, jpegOpt
return thumbnailBuffer;
};

const fromReadStream = async (source, percentage, width, height, responseType, jpegOptions, fit, failOnError, withMetaData) => {
const fromReadStream = async (
source,
percentage,
width,
height,
responseType,
jpegOptions,
fit,
failOnError,
withMetaData,
flattenBackgroundColor,
) => {
const imageBuffer = await util.streamToBuffer(source);
const dimensions = getDimensions(imageBuffer, percentage, { width, height });
const thumbnailBuffer = await sharpResize(imageBuffer, dimensions, jpegOptions, fit, failOnError, withMetaData);
const thumbnailBuffer = await sharpResize(imageBuffer, dimensions, jpegOptions, fit, failOnError, withMetaData, flattenBackgroundColor);

if (responseType === 'base64') {
return thumbnailBuffer.toString('base64');
Expand All @@ -64,11 +74,10 @@ const fromReadStream = async (source, percentage, width, height, responseType, j
return thumbnailBuffer;
};

const fromBuffer = async (source, percentage, width, height, responseType, jpegOptions, fit, failOnError, withMetaData) => {
const fromBuffer = async (source, percentage, width, height, responseType, jpegOptions, fit, failOnError, withMetaData, flattenBackgroundColor) => {
const imageBuffer = source;

const dimensions = getDimensions(imageBuffer, percentage, { width, height });
const thumbnailBuffer = await sharpResize(imageBuffer, dimensions, jpegOptions, fit, failOnError, withMetaData);
const thumbnailBuffer = await sharpResize(imageBuffer, dimensions, jpegOptions, fit, failOnError, withMetaData, flattenBackgroundColor);

if (responseType === 'base64') {
return thumbnailBuffer.toString('base64');
Expand All @@ -84,26 +93,82 @@ module.exports = async (source, options) => {
const responseType = options && options.responseType ? options.responseType : RESPONSE_TYPE;
const jpegOptions = options && options.jpegOptions ? options.jpegOptions : undefined;
const fit = options && options.fit ? options.fit : undefined;
const failOnError = options && typeof(options.failOnError) !== 'undefined' ? options.failOnError : true;
const withMetaData = options && typeof(options.withMetaData) !== 'undefined' ? options.withMetaData : false;
const failOnError = options && typeof options.failOnError !== 'undefined' ? options.failOnError : true;
const withMetaData = options && typeof options.withMetaData !== 'undefined' ? options.withMetaData : false;
const flattenBackgroundColor = options && typeof options.flattenBackgroundColor !== 'undefined' ? options.flattenBackgroundColor : '#ffffff';

try {
switch (typeof source) {
case 'object':
let response;
if (source instanceof fs.ReadStream || source instanceof stream.PassThrough) {
response = await fromReadStream(source, percentage, width, height, responseType, jpegOptions, fit, failOnError, withMetaData);
response = await fromReadStream(
source,
percentage,
width,
height,
responseType,
jpegOptions,
fit,
failOnError,
withMetaData,
flattenBackgroundColor,
);
} else if (source instanceof Buffer) {
response = await fromBuffer(source, percentage, width, height, responseType, jpegOptions, fit, failOnError, withMetaData);
response = await fromBuffer(
source,
percentage,
width,
height,
responseType,
jpegOptions,
fit,
failOnError,
withMetaData,
flattenBackgroundColor,
);
} else {
response = await fromUri(source, percentage, width, height, responseType, jpegOptions, fit, failOnError, withMetaData);
response = await fromUri(
source,
percentage,
width,
height,
responseType,
jpegOptions,
fit,
failOnError,
withMetaData,
flattenBackgroundColor,
);
}
return response;
case 'string':
if (validator.isBase64(source)) {
return await fromBase64(source, percentage, width, height, responseType, jpegOptions, fit, failOnError, withMetaData);
return await fromBase64(
source,
percentage,
width,
height,
responseType,
jpegOptions,
fit,
failOnError,
withMetaData,
flattenBackgroundColor,
);
} else {
return await fromPath(source, percentage, width, height, responseType, jpegOptions, fit, failOnError, withMetaData);
return await fromPath(
source,
percentage,
width,
height,
responseType,
jpegOptions,
fit,
failOnError,
withMetaData,
flattenBackgroundColor,
);
}
default:
throw new Error('unsupported source type');
Expand All @@ -124,26 +189,28 @@ const getDimensions = (imageBuffer, percentageOfImage, dimensions) => {
const height = parseInt((originalDimensions.height * (percentageOfImage / 100)).toFixed(0));

return { width, height };
}
};

const sharpResize = (imageBuffer, dimensions, jpegOptions, fit, failOnError, withMetadata) => {
const sharpResize = (imageBuffer, dimensions, jpegOptions, fit, failOnError, withMetadata, flattenBackgroundColor) => {
return new Promise((resolve, reject) => {
let result = sharp(imageBuffer, { failOnError })
.resize({
...dimensions, withoutEnlargement: true, fit: fit ? fit : 'contain',
...dimensions,
withoutEnlargement: true,
fit: fit ? fit : 'contain',
})
.flatten({ background: flattenBackgroundColor });

if(withMetadata){
result.withMetadata()
}
if (withMetadata) {
result.withMetadata();
}

result.jpeg(jpegOptions ? jpegOptions : { force: false })
.toBuffer((err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
result.jpeg(jpegOptions ? jpegOptions : { force: false }).toBuffer((err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
};

0 comments on commit 0145ba7

Please sign in to comment.