The javascript sharp library is used for image manipulation. https://sharp.pixelplumbing.com/
These are various experiments and exercises to better understand the possibilities of this library and how it can be used to automate various image manipulation tasks such as:
Most of these are pretty straightforward but there are some more advanced scenarios that seem possible but don't have many samples such as:
The goals of these experiments are:
const sharp = require("sharp")
const loadJpg = async () => {
const image = await sharp('./cat1.jpg')
const metadata = await image.metadata()
console.log(metadata)
}
loadJpg()
{
format: 'jpeg',
width: 1680,
height: 1050,
space: 'srgb',
channels: 3,
depth: 'uchar',
density: 72,
chromaSubsampling: '4:2:0',
isProgressive: false,
hasProfile: false,
hasAlpha: false
}
const loadAnimatedGif = async () => {
// loads default frame (page 1) and save to jpg
const image = await sharp('./cat-animated.gif')
const metadata = await image.metadata()
image.toFile('./cat-animated-frame1.jpg')
console.log(metadata)
}
loadAnimatedGif()
Note that it contains 102 frames (pages)
{
format: 'gif',
width: 548,
height: 610,
space: 'srgb',
channels: 4,
depth: 'uchar',
isProgressive: true,
paletteBitDepth: 5,
pages: 102,
loop: 0,
delay: [
30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30,
... 2 more items
],
background: { r: 255, g: 255, b: 255 },
hasProfile: false,
hasAlpha: true
}
const loadAnimatedGifFrame42 = async () => {
// load only frame 42 and save to a jpg
const image = await sharp('./cat-animated.gif', {pages: 1, page: 42})
image.toFile('./cat-animated-frame42.jpg')
}
loadAnimatedGifFrame42()
const loadAnimatedGif10Frames = async () => {
// load only 10 frames and save to animated webp
const image = await sharp('./cat-animated.gif', {pages: 10, page: 42})
.toFile('./cat-animated.webp')
}
loadAnimatedGif10Frames()
Confirmed that it only has 10 frames (pages)
const loadAnimatedWebp = async () => {
// open up the webp file and confirm we only have 10 frames
const image = await sharp('./cat-animated.webp')
const metadata = await image.metadata()
console.log(metadata)
}
loadAnimatedWebp()
{
format: 'webp',
width: 548,
height: 610,
space: 'srgb',
channels: 4,
depth: 'uchar',
isProgressive: false,
pages: 10,
loop: 0,
delay: [
30, 30, 30, 30, 30,
30, 30, 30, 30, 30
],
hasProfile: false,
hasAlpha: true
}
This adjust the delay value between each frame thus slowing it down
const loadAnimatedGif10FramesSlowDown = async () => {
// load only 10 frames and save to animated webp
const image = await sharp("./cat-animated.gif", {
pages: 10,
page: 42,
})
.webp({delay: 90}).toFile("./cat-animated-slow.webp");
}
loadAnimatedGif10FramesSlowDown()
const makeNoise = async () => {
// Generate RGB Gaussian noise
await sharp({
create: {
width: 300,
height: 200,
channels: 3,
noise: {
type: "gaussian",
mean: 128,
sigma: 30,
},
},
}).toFile("noise.png");
}
makeNoise()
const makeImageFromText = async () => {
// Generate an image from text
await sharp({
text: {
text: 'Hello, world!',
width: 400, // max width
height: 300 // max height
}
}).toFile('text_bw.png');
}
makeImageFromText()
const makeImageFromTextHtml = async () => {
// Generate an rgba image from text using pango markup and font
await sharp({
text: {
text: '<span foreground="red">Red!</span><span background="cyan">blue</span>',
font: "sans",
rgba: true,
dpi: 300,
},
}).toFile("text_rgba.png");
}
makeImageFromTextHtml()
Pango is a library for laying out and rendering of text, with an emphasis on internationalization Pango Documentation