Development Tip

Node.js : ImageMagick없이 이미지 크기 조정

yourdevel 2020. 10. 25. 13:12
반응형

Node.js : ImageMagick없이 이미지 크기 조정


저는 Node.js (+ express 4)에서 사용자가 프로필 이미지를 서버에 업로드하여 설정할 수있는 웹 앱을 개발 중입니다. 우리는 이미 파일 MIME 유형과 최대 파일 크기를 제한하므로 사용자는 200KB 이상의 png 또는 jpeg 이미지를 업로드 할 수 없습니다.

문제는 업로드 된 이미지 해상도를 200x200으로 크기를 조정 (서버 측)하여 페이지로드를 개선하고 디스크 공간을 절약하려고한다는 것입니다. 몇 가지 조사 후 모든 답변은 ImageMagick 또는 GraphicsMagick을 기반으로 한 모듈을 사용하는 것으로 나타났습니다.

그러나 간단한 이미지 크기 조정을 수행하기 위해 ImageMagick / GraphicsMagick을 설치해야하는 것은 나에게 너무 지나친 것처럼 보이므로 Node.js에 대해 이것 이외의 다른 솔루션이 있습니까?

편집 : 이전 솔루션 (lwip)이 더 이상 유지되지 않으므로 수락 된 솔루션을 sharp변경했습니다 . 모든 피드백에 감사드립니다!


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

빠르고 일반적으로 가장 빠른 imagemagick 기반 노드 바인딩보다 6 배 빠르며 매우 적은 메모리에서 실행되며 아마도 10 배 더 적습니다 . libvips 이미지 라이브러리 에 대한 날카로운 링크 , 외부 프로그램에 대한 쉘링이 없으며 라이브러리 자체가이 작업에서 * magick보다 빠르고 효율적입니다. 스트림, 버퍼 및 파일 시스템 입력 및 출력, 색상 관리, 투명성, 약속, 오버레이, WebP, SVG 등과 같은 유용한 기능을 지원합니다.

Sharp 0.20부터 npm은 대부분의 플랫폼에서 사전 컴파일 된 완전한 바이너리를 자동으로 다운로드하므로 node-gyp이 필요하지 않습니다. 다음을 입력하십시오.

npm install sharp

또는:

yarn add sharp

그리고 가세요.


최근에 런타임 종속성없이 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 에서 더 많은 정보를 확인하세요 .


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

});

파일 업 로더 에서 성공적으로 구현 했으며 매력처럼 작동합니다.


Jimp라는 다른 라이브러리에 대한 종속성없이 완전히 JavaScript로 작성된 좋은 이미지 조작 라이브러리가 있습니다. 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
});

sharp 는 최근 인기를 얻었지만 * Magick 바인딩과 같은 아이디어입니다.

그러나 간단한 이미지 크기 조정을 수행하기 위해 ImageMagick / GraphicsMagick을 설치해야하는 것은 나에게 너무 과한 것 같습니다.

이미지 크기 조정은 간단하지 않습니다. JPEG 형식은 특히 복잡하며 다양한 품질의 결과로 그래픽 크기를 조정하는 여러 가지 방법이 있으며 그 중 일부는 쉽게 구현할 수 있습니다. 이 작업을 수행하기 위해 이미지 처리 라이브러리가 존재하므로 설치할 수없는 다른 이유가 없다면 사용하십시오.


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

큰 이미지가 필요하지 않은 경우 업로드하기 전에 클라이언트 측에서 크기를 조정할 수 있습니다.

File API를 사용하여 JavaScript에서 파일 읽기

서버에 업로드하기 전에 자바 스크립트로 클라이언트 측 이미지 크기 조정

많은 사용자가 스마트 폰에서 자신의 모습을 잘 볼 수 있으며 그중 많은 사용자가 200KB 이상입니다. 클라이언트가 제공 한 데이터는 신뢰할 수 없으므로 서버 측 검사가 계속 적용됩니다.


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 파일 만 수행합니다.


Sharp work very well and is easy to use with streams, work like a charm, but you need to compile it with the node version, this is a downside to it. I was using Sharp for image processing, with an image from an AWS S3 bucket and worked perfectly, but I had to use another module. GM didn't work for me, but Jimp worked very good!

You have to pay attention to the path of the written picture, it might give you some errors if you start the path with a "/".

This is how I used Jimp in 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() } }

            });

Also watch out for the order of execution, put a callback so other things don't happen when you don't want to. Tried using "await" for the Jimp.read() but it didn't do the job well.


You can do this using jimp (node_module)

Local Write:

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

To upload to s3 or where ever you like.

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

참고URL : https://stackoverflow.com/questions/24026320/node-js-image-resizing-without-imagemagick

반응형