Node.js:不使用ImageMagick调整图像大小

时间:2014-06-03 22:55:49

标签: image node.js image-resizing

我正在Node.js(+ express 4)上开发一个Web应用程序,用户可以通过将其上传到服务器来设置他们的个人资料图像。我们已经限制了文件mimetype和max filesize,因此用户无法上传超过200KB的png或jpeg图像。

问题是我们希望将上传的图像分辨率调整为(服务器端)为200x200以改善页面加载并节省磁盘空间。经过一些研究,所有答案都指向使用基于ImageMagick或GraphicsMagick的任何模块。

但是,必须安装ImageMagick / GraphicsMagick进行简单的图像调整大小对我来说似乎太过分了,所以除了Node.js之外还有其他解决方案吗?

修改:我已将已接受的解决方案更改为sharp,因为之前的解决方案(lwip)已不再维护。感谢您的所有反馈!

11 个答案:

答案 0 :(得分:70)

我最近开始为NodeJS开发一个没有任何运行时依赖性的图像处理模块(read why)。它还处于早期阶段,但已经可以使用了。

您要求的内容如下:

image.resize(200, 200, function(err, image){
    // encode resized image to jpeg and get a Buffer object
    image.toBuffer('jpg', function(err, buffer){
        // save buffer to disk / send over network / etc.
    });
});

该模块Github repo的更多信息。

答案 1 :(得分:65)

我会投票给sharp

sharp('input.jpg')
  .resize(200, 200)
  .toFile('ouput.jpg', function(err) {
    // output.jpg is a 200 pixels wide and 200 pixels high image
    // containing a scaled and cropped version of input.jpg
  });

它很快,typically 6x faster than the fastest imagemagick-based node bindings,并且在很少的内存中运行perhaps 10x less。直接链接到libvips图像库,没有外部程序的外壳,并且库本身比* magick更快,更有效。它支持流,缓冲和文件系统输入和输出,颜色管理,透明度,承诺,叠加,WebP,SVG等有用的东西。

截至0.20,npm将在大多数平台上自动下载完整的预编译二进制文件,因此不需要node-gyp。只需输入:

npm install sharp

或:

yarn add sharp

然后离开。

答案 2 :(得分:16)

看看lwip:https://github.com/EyalAr/lwip

非常简单易用

npm install lwip

然后在您的节点代码中

// obtain an image object:
require('lwip').open('image.jpg', function(err, image){

  // check err...
  // define a batch of manipulations and save to disk as JPEG:
  image.batch()
    .scale(0.75)          // scale to 75%
    .rotate(45, 'white')  // rotate 45degs clockwise (white fill)
    .crop(200)            // crop a 200X200 square from center
    .blur(5)              // Gaussian blur with SD=5
    .writeFile('output.jpg', function(err){
      // check err...
      // done.
    });

});

我已经在我的file uploader中成功实现了它,它就像一个魅力。

答案 3 :(得分:10)

有一个很好的图像处理库,完全用JavaScript编写,不依赖于任何其他库,Jimp。 https://github.com/oliver-moran/jimp

使用示例:

var Jimp = require("jimp");

// open a file called "lenna.png"
Jimp.read("lenna.png", function (err, lenna) {
    if (err) throw err;
    lenna.resize(256, 256)            // resize
         .quality(60)                 // set JPEG quality
         .write("lena-small.jpg"); // save
});

答案 4 :(得分:8)

sharp最近很受欢迎,但它与* Magick绑定的想法相同。

  

但是,不得不安装ImageMagick / GraphicsMagick进行简单的图像调整大小对我来说太过分了

图像大小调整绝非易事。 JPEG格式特别复杂,有几种方法可以使用不同质量的结果来缩放图形,很少有这些方法可以轻松实现。存在图像处理库来完成这项工作,所以如果你没有其他原因无法安装它们,那就去吧。

答案 5 :(得分:5)

Canvas 比ImageMagic快 2.3倍。

您可以尝试比较Node.js模块以进行图像处理 - https://github.com/ivanoff/images-manipulation-performance

author's results:
 sharp.js : 9.501 img/sec; minFreeMem: 929Mb
 canvas.js : 8.246 img/sec; minFreeMem: 578Mb
 gm.js : 4.433 img/sec; minFreeMem: 791Mb
 gm-imagemagic.js : 3.654 img/sec; minFreeMem: 804Mb
 lwip.js : 1.203 img/sec; minFreeMem: 54Mb
 jimp.js : 0.445 img/sec; minFreeMem: 82Mb

答案 6 :(得分:3)

如果您不需要大图片,可以在上传之前在客户端调整大小:

Reading files in JavaScript using the File APIs

Image resizing client-side with javascript before upload to the server

许多用户可能从智能手机上看到自己的好照片,其中许多用户超过200kB。请注意,客户端提供的数据不受信任,因此服务器端检查仍然适用。

答案 7 :(得分:0)

Sharp可以很好地工作,并且易于在流中使用,就像魅力一样工作,但是您需要使用节点版本进行编译,这是它的缺点。 我使用Sharp进行图像处理,并使用了AWS S3存储桶中的图像,并且运行良好,但是我不得不使用另一个模块。通用汽车没有为我工作,但吉普却表现出色!

您必须注意所写图片的路径,如果以“ /”开头的路径可能会给您带来一些错误。

这就是我在nodeJS中使用Jimp的方式:

const imageUrl = `SOME_URL`;
let imgExported = 'EXPORTED_PIC.png';

Jimp.read(imageUrl)
    .then(image => {
        image   
            .resize(X, Y) 
            .write(`tmp/`+ imgExported, err => { 
                if(err) 
                    console.error('Write error: ', err);
                else { ... // don't forget to put a callback() } }

            });

还要注意执行的顺序,放置一个回调,这样在您不想执行其他操作时就不会发生。尝试对Jimp.read()使用“等待”,但效果不佳。

答案 8 :(得分:0)

您可以使用jimp(node_module)

本地写入:

Jimp.read(path) // this can be url or local location
      .then(image=> {
          image
            .resize(size, Jimp.AUTO) // jimp.AUTO automatically sets the width so that the image doesnot looks odd
            .write('path-to-save');
      })
      .catch(err => {
        console.log(err);
      });

要上传到s3或您喜欢的任何地方。

Jimp.read(urls) // this can be url or local location
          .then(image=> {
              image
                .resize(size, Jimp.AUTO) // jimp.AUTO automatically sets the width so that the image doesnot looks odd
                .getBase64(Jimp.AUTO, (err, res) => {
                  const buf = new Buffer(
                    res.replace(/^data:image\/\w+;base64,/, ""),
                    "base64"
                  );
                  var data = {
                    Key: key,
                    Bucket: bucket,
                    Body: body,
                    ContentEncoding: "base64",
                    ContentType: "image/jpeg"
                  };
                  s3.putObject(data, function(err, data) {
                    if (err) {
                      throw err;
                    } else {
                      console.log("succesfully uploaded the image!");
                    }
                  });
                });
          })
          .catch(err => {
            console.log(err);
          });

答案 9 :(得分:0)

我喜欢resize-img库,因为它很简单。

const fs = require('fs');
const resizeImg = require('resize-img');

(async () => {
    const image = fs.readFileSync('unicorn.png');

    const newImage = await resizeImg(image, { width: 128, height: 128 });

    fs.writeFileSync('unicorn-128x128.png', newImage);
})();

答案 10 :(得分:0)

使用Google Drive API v3调整图像大小。建议Google Apps脚本使用此方法将图像插入Google表格中。

算法:

  1. Upload图片到Google云端硬盘文件夹。
  2. Get图片缩略图公开URL。
  3. 用必要的宽度和/或高度替换URL中的“调整大小”参数。 (默认缩略图大小为220像素)。
  4. 从Google云端硬盘下载调整大小的缩略图。

在此处查看示例: https://github.com/dobromyslov/google-drive-utils/blob/511c44c2c48862b47c60038423b7f71bf1d28f49/src/index.ts#L150

并注意GDrive配额:

  • 每天查询:1000000000
  • 每用户每100秒
  • 查询:1000
  • 每100秒查询次数:10000次