aboutsummaryrefslogtreecommitdiff
path: root/_posts/posts/2020-03-27-create-placeholder-images-with-sharp.md
diff options
context:
space:
mode:
authorMitja Felicijan <mitja.felicijan@gmail.com>2024-02-23 10:35:22 +0100
committerMitja Felicijan <mitja.felicijan@gmail.com>2024-02-23 10:35:22 +0100
commit4abcce013c9ee3053badf2abda77190233066676 (patch)
tree450de7e8fed3c3c7501a9d2e2eb60a676bdfa09e /_posts/posts/2020-03-27-create-placeholder-images-with-sharp.md
parentcdf50cb2e3051200c6ea0628c318d66220b7d1a1 (diff)
downloadmitjafelicijan.com-4abcce013c9ee3053badf2abda77190233066676.tar.gz
Testing thoughts page
Diffstat (limited to '_posts/posts/2020-03-27-create-placeholder-images-with-sharp.md')
-rw-r--r--_posts/posts/2020-03-27-create-placeholder-images-with-sharp.md103
1 files changed, 103 insertions, 0 deletions
diff --git a/_posts/posts/2020-03-27-create-placeholder-images-with-sharp.md b/_posts/posts/2020-03-27-create-placeholder-images-with-sharp.md
new file mode 100644
index 0000000..c129396
--- /dev/null
+++ b/_posts/posts/2020-03-27-create-placeholder-images-with-sharp.md
@@ -0,0 +1,103 @@
1---
2title: Create placeholder images with sharp Node.js image processing library
3permalink: /create-placeholder-images-with-sharp.html
4date: 2020-03-27T12:00:00+02:00
5layout: post
6type: post
7draft: false
8---
9
10I have been searching for a solution to pre-generate some placeholder images for
11image server I needed to develop that resizes images on S3. I though this would
12be a 15min job and quickly found out how very mistaken I was.
13
14Even though Node.js is not really the best way to do this kind of things (surely
15something written in C or Rust or even Golang would be the correct way to do
16this but we didn't need the speed in our case) I found an excellent library
17[sharp - High performance Node.js image
18processing](https://github.com/lovell/sharp).
19
20Getting things running was a breeze.
21
22## Fetch image from S3 and save resized
23
24```js
25const sharp = require('sharp');
26const aws = require('aws-sdk');
27
28const x,y = 100;
29const s3 = new aws.S3({});
30
31aws.config.update({
32 secretAccessKey: 'secretAccessKey',
33 accessKeyId: 'accessKeyId',
34 region: 'region'
35});
36
37const originalImage = await s3.getObject({
38 Bucket: 'some-bucket-name',
39 Key: 'image.jpg',
40}).promise();
41
42const resizedImage = await sharp(originalImage.Body)
43 .resize(x, y)
44 .jpeg({ progressive: true })
45 .toBuffer();
46
47s3.putObject({
48 Bucket: 'some-bucket-name',
49 Key: `optimized/${x}x${y}/image.jpg`,
50 Body: resizedImage,
51 ContentType: 'image/jpeg',
52 ACL: 'public-read'
53}).promise();
54```
55
56All this code was wrapped inside a web service with some additional security
57checks and defensive coding to detect if key is missing on S3.
58
59And at that point I needed to return placeholder images as a response in case
60key is missing or x,y are not allowed by the server etc. I could have created
61PNG in Gimp and just serve them but I wanted to respect aspect ratio and I
62didn't want to return some mangled images.
63
64> Main problem with finding a clean solution I could copy and paste and change a
65> bit was a task. API is changing constantly and there weren't clear examples or
66> I was unable to find them.
67
68## Generating placeholder images using SVG
69
70What I ended up was using SVG to generate text and created image with sharp and
71used composition to combine both layers. Response returned by this function is a
72buffer you can use to either upload to S3 or save to local file.
73
74```js
75const generatePlaceholderImageWithText = async (width, height, message) => {
76 const overlay = `<svg width="${width - 20}" height="${height - 20}">
77 <text x="50%" y="50%" font-family="sans-serif" font-size="16" text-anchor="middle">${message}</text>
78 </svg>`;
79
80 return await sharp({
81 create: {
82 width: width,
83 height: height,
84 channels: 4,
85 background: { r: 230, g: 230, b: 230, alpha: 1 }
86 }
87 })
88 .composite([{
89 input: Buffer.from(overlay),
90 gravity: 'center',
91 }])
92 .jpeg()
93 .toBuffer();
94}
95```
96
97That is about it. Nothing more to it. You can change the color of the image by
98changing `background` and if you want to change text styling you can adapt SVG
99to your needs.
100
101> Also be careful about the length of the text. This function positions text at
102> the center and adds `20px` padding on all sides. If text is longer than the
103> image it will get cut.