question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

can I use image url as sharp input?

See original GitHub issue

I’m just started with Sharp, and trying to overlay two images in the nodejs server and output a png, both are web images. So I’m trying with (picked random img urls here)

const server = http.createServer(async (req, res) => {
function processImg(){
  let buffer = sharp('https://pbs.twimg.com/profile_images/3572978953/8c522d3ea384cd42e46a4a2498300c35_400x400.jpeg')
    .composite({input: 'https://abs.twimg.com/a/1569889127/img/delight/delight_prompt_3.png'})
    .png()
    .toBuffer()
    .catch(err=>{console.log(err)})
  return buffer
}

let newBuffer = await processImg();
res.setHeader("Content-Type", "image/png");
res.end(newBuffer);
}

Then I get error [Error: Input file is missing]. Does it mean the image src was not working?

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:1
  • Comments:7 (1 by maintainers)

github_iconTop GitHub Comments

29reactions
mooyoulcommented, Oct 5, 2019

As @lovell mentioned, Sharp does not support remote URL as Input.

Anyway, There’s another way to achieve your goal - Download Image manually & Use Buffer as Input:

using Axios

import axios from "axios";

const input = (await axios({ url: "https://somewhere.com/some-image.png", responseType: "arraybuffer" })).data as Buffer;
const composite = (await axios({ url: "https://somewhere.com/another-image.png", responseType: "arraybuffer" })).data as Buffer;

const output = await sharp(input).composite({ input: composite }).png().toBuffer();

using Request

Unfortunately. request does not support Promise interface. You’ll have to wrap request calls to your own Promise instance:

import * as request from "request";

const getBody = (url: string): Promise<Buffer> => new Promise<Buffer>)((resolve, reject) => {
  // `encoding: null` is important - otherwise you'll get non-buffer response body
  request({ url, encoding: null }, (e, res, body) => {
    if (e) { return reject(e); }
    else if (200 <= res.statusCode && res.statusCode < 300) {
       return resolve(body);
    } else {
      return reject(new Error(`Unexpected response status ${res.statusCode}`));
    }
  });
});

const input = await getBody("https://some-where.com/some-image.png");
const composite = await getBody("https://another-server.com/another-image.png");

const output = await sharp(input).composite({ input: composite }).png().toBuffer();

Anyway, Based on your code example, It’s not good to production usage because someone calls your server, every time server should do expensive tasks (download image from remote server and transform image - imagine If someone calls your server 100 times concurrently - your server will be unavailable.)

To optimize performance issue, You should consider caching.

If composite image is always same, you can store composite image to memory and re-use them:

import axios from "axios";
import * as sharp from "sharp";

let cachedCompositeInput = null;
async function compositeImage(inputUrl: string): Promise<Buffer> {
   if (!cachedCompositeInput) { 
     cachedCompositeInput = await getCompositeImageSomehow();
   }

  const input = (await axios({ url: remoteUrl, responseType: "arraybuffer" })).data;
  return await sharp(input).composite({ input: cachedCompositeInput }).png().toBuffer();
}

Anyway, Upper example can reduce number of downloading composite image. but image composition is still required.

To reduce image composition tasks. You can setup your own CDN in front of your server. See https://github.com/donnemartin/system-design-primer#content-delivery-network for details.

3reactions
jiehan1029commented, Oct 5, 2019

Thank you @lovell , the example helped a lot! Able to resolve the problem.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How can you resize an image in NodeJS using Sharp having ...
To get a buffer from a axios response, you'll have to set responseType to 'arraybuffer' . const imageResponse = await axios({url: url, ...
Read more >
How To Process Images in Node.js With Sharp - DigitalOcean
Node.js has an ecosystem of libraries you can use to process images, such as sharp, jimp, and gm module. This article will focus...
Read more >
Processing images with sharp in Node.js - LogRocket Blog
sharp is a high-performance image processing module for Node.js. Learn how to use sharp for UGC management.
Read more >
Process Images the right way | SharpJS - Programmer Couple
A complete guide on Sharp.js, a light and easy Javascript Library used for Image Processing.
Read more >
Output options - High performance Node.js image processing
If an explicit output format is not selected, it will be inferred from the extension, with JPEG, PNG, WebP, AVIF, TIFF, GIF, DZI,...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found