Node 6.10.x에서 이미지 처리용으로 사용하는 lwip가 문제가 있어서, jimp로 바꿨어요.


(InGrowth) #1

Node LTS 버전이 6.10.3이죠. 6.9.5를 상당히 오래 쓰다가 6.10.3으로 올렸더니,
엉뚱하게 lwip에서 문제가 발생하네요.


요런 다양한 이슈들이 있습니다.
아무래도 업데이트가 너무 오래 되지 않았군요…
그래서 활성 포크인 pajk-lwip로 바꿨더니 로컬에서는 되는데, docker 환경에서 안되더군요.

결국 jimp로 바꿨습니다.

코드를 약간 수정해야했지만 native 의존성이 적어서 잘 되는군요.
성능은 1~2mb 정도인 이미지에서는 차이를 잘 모르겠네요.

코드 차이는 이정도 입니다. 훨씬 간결하고 좋네요.

lwip 버전

import lwip from 'lwip';
import stream from 'stream';

export function imageResize(file, thumbWidth = 900) {
  return new Promise((resolve, reject) => {
    const type = file.mimetype.replace('image/', '') || 'jpg';
    // read info
    lwip.open(file.path, type, (_err, _image) => {
      if (_err) return reject(_err);

      const width = _image.width();
      const height = _image.height();
      console.log('getImageSize', width, height);

      const size = {};
      size.width = thumbWidth;
      size.height = (height / width) * thumbWidth;

      // resize
      _image.resize(size.width, size.height, (_err2, _image2) => {
        if (_err2) return reject(_err2);
        // to buffer
        _image2.toBuffer('jpg', { quality: 80 }, (_err3, _buffer) => {
          if (_err3) return reject(_err3);
          // Initiate the source
          const bufferStream = new stream.PassThrough();
          // Write your buffer
          bufferStream.end(_buffer);
          // return
          resolve(bufferStream, { width, height });
        });
      });
    });
  });
}

jimp 버전

import Jimp from 'jimp';
import stream from 'stream';

export function imageResize(file, thumbWidth = 900) {
  return new Promise((resolve, reject) => {
    // read info
    Jimp.read(file.path, (_err, _image) => {
      if (_err) return reject(_err);

      const width = _image.bitmap.width;
      const height = _image.bitmap.height;
      console.log('getImageSize', width, height);

      const size = {};
      size.width = thumbWidth;
      size.height = (height / width) * thumbWidth;

      // resize
      _image.resize(size.width, size.height)
      .quality(80)
      .getBuffer(Jimp.MIME_JPEG, (_err2, _buffer) => {
        if (_err2) return reject(_err2);
        // Initiate the source
        const bufferStream = new stream.PassThrough();
        // Write your buffer
        bufferStream.end(_buffer);
        // return
        resolve(bufferStream, { width, height });
      });
    });
  });
}

(InGrowth) #2

jimp는 메모리를 너무 많이 먹어서… GraphicsMagick로 바꿨습니다.

gm을 적용한 코드는요…

import gm from 'gm';

export default function image() {}

export function getImageSize(file) {
  return new Promise((resolve, reject) => {
    // read info
    gm(file.path).size((_err, _size) => {
      if (_err) return reject(_err);

      console.log('getImageSize', _size);
      resolve(_size);
    });
  });
}

export function imageResize(file, resizedWidth = 900) {
  return new Promise((resolve, reject) => {
    // read info
    gm(file.path).size(function (_err, _size) {
      if (_err) return reject(_err);

      const width = _size.width;
      const height = _size.height;
      console.log('getImageSize', width, height);

      const size = {};
      // crop position
      if (width > height) {
        // landsacpe : 3000 * 2000
        size.width = (width / height) * resizedWidth; // 1.5 * 300 = 450
        size.height = resizedWidth; // 300
      } else {
        // portrait : 2000 * 3000
        size.width = resizedWidth;  // 300
        size.height = (height / width) * resizedWidth;  // 1.5 * 300 = 450
      }

      // resize
      const stream = this.resize(size.width, size.height)
        .quality(80)
        .stream();

      resolve({ stream, ...size });
    });
  });
}

(이종은(Jong Lee)) #3

동우님은 parse-server 사용할 때 이를 이용해서 서버사이드에서 thumbnail 생성하고 계신건가요?


(InGrowth) #4

네. 서버에서 썸네일 생성하고 있습니다. Lamda도 써보고 했지만, 제일 깔끔한건 역시 서버코드로 만드는거더라구요.