responsive-loader
responsive-loader copied to clipboard
Resize and/or crop images?
Is it possible to use this loader to also resize/crop images? For instance, it could be great to use it to create thumbnails with different ratio, ... Thank you
@Melzmr Can't figure out how to achieve that, can you share a snippet perhaps?
@Melzmr I think @gbouteiller was looking for ways to specify crop parameters at the URI-level. eg if I have a responsive background image in a hero section, I want to the height to be fixed as I generate crops of different widths.
So sharp has params for height
and crop
strategy, but responsive-loader
only takes width
at the moment.
I guess it's possible to supply our own adapter, copying this one: https://github.com/herrstucki/responsive-loader/blob/master/src/adapters/sharp.js
and then including all the args to sharp.resize
there (width, height, crop)
One strategy would be to use the width param as an integer key:
require("./images/image.jpg?resize?width=1")
that specifies one of a variety of settings used in our own site:
options = [
{width: 1200, height: 800, fit: "crop"},
{width: 300, height: 400, fit: "cover"},
]
which then calls:
image.clone.resize(options[width])
a la http://sharp.dimens.io/en/stable/api-resize/#parameters
See https://github.com/herrstucki/responsive-loader/issues/70#issuecomment-444900842
Here is my "works today" solution. It's somewhat of a hack (using the width parameter as an index into some presets), but it will work until there is a better way to do this.
I'm using this with
- https://github.com/cyrilwanner/next-optimized-images
- herrsucki/responsive-loader
- https://github.com/lovell/sharp so there are many pancakes stacked high and they will probably all fallover soon enough.
// ./lib/sharp-adapter.js
const sharp = require("sharp");
/**
* Factory to make a sharp adapter function for use in response-loader.
* Width is interpreted as an integer index into the presets list supplied to the factory function.
*
* Usage:
*
* next.config.js
*
* const resizeOptions = {
* 1: {
* width: 1024,
* height: 682,
* fit: "cover"
* },
* 2: {
* width: 496,
* height: 593,
* fit: "cover"
* }
* };
*
* // make the adapter
* adapter: require("./lib/sharp-adapter")(resizeOptions)
*
* // usage
* const main = require(`./images/some-image.jpg?resize&sizes[]=1`);
* const thumb = require(`./images/some-image.jpg?resize&sizes[]=2`);
*/
function adapterFactory(resizeOptions) {
return imagePath => {
const image = sharp(imagePath);
return {
metadata: () => image.metadata(),
resize: ({ width, mime, options }) =>
new Promise((resolve, reject) => {
const resizeOpts = resizeOptions[width] || { width: width };
// console.log(width, mime, options, resizeOpts);
let resized = image.clone().resize(resizeOpts);
if (options.background) {
resized = resized.background(options.background).flatten();
}
if (mime === "image/jpeg") {
resized = resized.jpeg({
quality: options.quality
});
}
resized.toBuffer((err, data, { height }) => {
if (err) {
reject(err);
} else {
resolve({
data,
width: resizeOpts.width,
height: height
});
}
});
})
};
};
}
module.exports = adapterFactory;
+1, I also need this! I want to pass the height / crop width/height via URL, like
background: url('../images/background.jpg?height=1000
.