Подтвердить что ты не робот

Node.js: изменение размера изображения без ImageMagick

Я разрабатываю веб-приложение для Node.js(+ экспресс 4), где пользователи могут установить изображение своего профиля, загрузив его на сервер. Мы уже ограничиваем размер файла mimetype и максимальный размер файла, поэтому пользователь не может загружать изображения размером более 200 КБ в png или jpeg.

Проблема в том, что мы хотели бы изменить (загружаемое на сервер) разрешение загружаемого изображения до 200x200, чтобы улучшить загрузку страниц и сэкономить место на диске. После некоторых исследований все ответы указывали на использование любого модуля на основе ImageMagick или GraphicsMagick.

Однако необходимость установить ImageMagick/GraphicsMagick для простого изменения размера изображения кажется мне слишком излишней, поэтому есть ли какое-либо иное решение, кроме этого, для Node.js?

Изменить: Я изменил принятое решение на sharp, так как предыдущее решение (lwip) больше не поддерживается. Спасибо за все ваши отзывы!

4b9b3361

Ответ 1

Я бы проголосовал за резкое

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
  });

Это быстро, обычно в 6 раз быстрее, чем самые быстрые привязки узлов на основе imagemagick, и работает в очень небольшом объеме памяти, возможно, в 10 раз меньше. четкие ссылки на библиотеку изображений libvips напрямую, никакой внешней оболочки нет, а сама библиотека работает быстрее и эффективнее, чем * magick в этой задаче. Он поддерживает полезные функции, такие как ввод и вывод потока, буфера и файловой системы, управление цветом, прозрачность, обещания, наложения, WebP, SVG и многое другое.

Начиная с 0,20, npm будет автоматически загружать полные скомпилированные двоичные файлы на большинстве платформ, поэтому нет необходимости в node-gyp. Просто введите:

npm install sharp

или же:

yarn add sharp

И пошли.

Ответ 2

Недавно я начал разрабатывать модуль обработки изображений для NodeJS без каких-либо зависимостей во времени выполнения (прочитать, почему). Он все еще находится на ранних стадиях, но уже можно использовать.

То, о чем вы просите, будет сделано следующим образом:

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.

Ответ 3

Взгляните на lwip: https://github.com/EyalAr/lwip

Очень простой и простой в использовании

npm install lwip

а затем в вашем node коде,

// 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.
    });

});

Я успешно реализовал это в своем загрузчике файлов и работает как шарм.

Ответ 4

Существует хорошая библиотека обработки изображений, полностью написанная на 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
});

Ответ 5

sharp в последнее время пользуется некоторой популярностью, но его та же идея, что и * привязки Magick.

Однако, для установки ImageMagick/GraphicsMagick для простого изменения размера изображения кажется слишком излишним для меня

Изменение размера изображения ничего, кроме простого. Формат JPEG особенно сложный, и есть несколько способов масштабирования графики с результатами различного качества, некоторые из которых легко реализованы. Библиотеки обработки изображений существуют для выполнения этой задачи, поэтому, если у вас нет другой причины, по которой вы не можете их установить, перейдите к ней.

Ответ 6

Холст в 2,3 раза быстрее, чем ImageMagic.

Вы можете попробовать сравнить модули Node.js для обработки изображений - https://github.com/ivanoff/images-manipulation-performance

author 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

Ответ 7

Если вам не требуется большое изображение, вы можете изменить его размер на стороне клиента перед его загрузкой:

Чтение файлов в JavaScript с использованием API-интерфейсов файлов

Изменение размера изображения на стороне клиента с помощью javascript перед загрузкой на сервер

Многие пользователи могут иметь хорошее представление о себе со смартфона, и многие из них более 200 КБ. Обратите внимание, что данные, предоставленные клиентом, не должны быть доверенными, поэтому проверки на стороне сервера по-прежнему применяются.

Ответ 8

Я использовал lwip (как ранее предлагал arvind), но переключился на png-crop. Кажется, это работает немного быстрее для меня (Win 8.1 x64, Node v0.12.7). Код в репо выглядит невероятно легким и оперативно простым в использовании.

var pngcrop = require('png-crop');
var config = {left: 10, top: 100, height: 150, width: 150};
pngcrop.crop('cats.png','cats-cropped.png',config);

Конечно, это будут только файлы png...

Ответ 9

Sharp работает очень хорошо и прост в использовании с потоками, работает как шарм, но вам нужно скомпилировать его с версией узла, это его недостаток. Я использовал Sharp для обработки изображений с изображением из корзины AWS S3 и работал отлично, но мне пришлось использовать другой модуль. GM не работал для меня, но Jimp работал очень хорошо!

Вы должны обратить внимание на путь написанного рисунка, это может привести к ошибкам, если вы начнете путь с "/".

Вот как я использовал Jimp в nodeJS:

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() } }

            });

Также следите за порядком выполнения, установите обратный вызов, чтобы другие вещи не происходили, когда вы этого не хотите. Пробовал использовать "await" для Jimp.read(), но это не помогло.

Ответ 10

Вы можете сделать это, используя 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);
          });