Node.js: ImageMagick olmadan görüntüyü yeniden boyutlandırma


86

Node.js (+ express 4) üzerinde kullanıcıların profil resimlerini sunucuya yükleyerek ayarlayabilecekleri bir web uygulaması geliştiriyorum. Dosya mimetipini ve maksimum dosya boyutunu zaten sınırladık, böylece kullanıcı 200 KB'tan fazla png veya jpeg resim yükleyemez.

Sorun, sayfa yüklemesini iyileştirmek ve diskte yer tasarrufu sağlamak için yüklenen görüntünün çözünürlüğünü 200x200 olarak yeniden boyutlandırmak (sunucu tarafında) istiyoruz. Biraz araştırmadan sonra, tüm cevaplar ImageMagick veya GraphicsMagick'e dayalı herhangi bir modülü kullanmaya işaret etti.

Bununla birlikte, basit bir görüntü yeniden boyutlandırma yapmak için ImageMagick / GraphicsMagick'i kurmak zorunda kalmak benim için çok fazla gözüküyor, bu yüzden Node.js için bundan başka bir çözüm var mı?

Düzenleme: Önceki çözüm (lwip) artık korunmadığından kabul edilen çözümü keskin olarak değiştirdim . Bütün geri bildirimleriniz için teşekkürler!


Selam. Bir sorum var Görüntü boyutunu 200 KB'nin altına nasıl düşürürüm? Lütfen yolu açıklayın. Teşekkürler.
C.Petrescu

Merhaba, daha önce gönderilmiş herhangi bir ilgili soru bulamazsanız, bu soru yeni bir soru olarak gönderilmeye değer. Size biraz ışık tutmak için, bu soruda bulabileceğiniz araçlar için sağlanan API'de sıkıştırma ve yeniden boyutlandırma yöntemlerini aramayı deneyin.
zacr0

Yanıtlar:


92

Keskinliğe oy verirdim :

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

Hızlıdır , tipik olarak en hızlı imge-sihirli tabanlı düğüm bağlamalarından 6 kat daha hızlıdır ve çok az bellekte, belki de 10 kat daha azdır . libvip'lere keskin bağlantılardoğrudan görüntü kitaplığına , harici bir programa yoktur ve kitaplığın kendisi bu görevde * magick'ten daha hızlı ve daha etkilidir. Akış, arabellek ve dosya sistemi girişi ve çıkışı, renk yönetimi, şeffaflık, vaatler, kaplamalar, WebP, SVG ve daha fazlası gibi yararlı şeyleri destekler.

Keskin 0.20'den itibaren npm, çoğu platformda önceden derlenmiş tam ikili dosyaları otomatik olarak indirecektir, bu nedenle düğüm-gyp'ye gerek yoktur. Sadece şunu girin:

npm install sharp

veya:

yarn add sharp

Ve sen git.


7
V0.12.0'dan itibaren, libvips'in sharpönceden derlenmiş bir sürümünü paketlediği için Linux ve Windows kullanıcıları için artık herhangi bir harici çalışma zamanı bağımlılığı yoktur. Yeniden boyutlandırma işlemlerinin LWIP'den ~ 10 kat daha hızlı olduğunu ve bellek kullanımının bir kısmını göreceksiniz.
Lovell Fuller


1
Yüzlerce dosyadır, ancak hepsi sizin için otomatik olarak npm tarafından yönetilir, bunun hakkında düşünmenize gerek yoktur.
jcupitt

4
@CoDEmanX Belki npm install --global --production windows-build-toolsönce koşmayı deneyin . Ayrıca bkz. Github.com/Microsoft/nodejs-guidelines/blob/master/…
Lovell Fuller

1
Biraz senaryo kolay yapar inşa bakın ne şeyler yapıyoruz ve boostrap kartları ve arka gibi içeriğinde nasıl görüneceğini: belki onun intrest en iyi optimize etmek kapak parametreler, github.com/lcherone/sharp-test
Lawrence Cherone

71

Yakın zamanda herhangi bir çalışma zamanı bağımlılığı olmadan NodeJS için bir görüntü işleme modülü geliştirmeye başladım ( nedenini okuyun ). Hala erken aşamalarda, ancak zaten kullanılabilir durumda.

İstediğiniz şey şu şekilde yapılacaktır:

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

Modülün Github deposunda daha fazla bilgi .


7
Modülünüz harika. Ancak çok fazla hafıza gerektirir. writeFile Bir 1.8Mbgörüntüyü denedim ve 130 Mb bellek gerektiriyor. Bundan sonra, bir 4MB, 11000x6000resmi birkaç küçük resme (640,560,480, ..., 160) yeniden boyutlandırarak bir test yapıyorum ve yaklaşık 1,7 GB bellek alıyor. Bu bir hata mı?
Lewis

2
Merhaba @Orion, geri bildirim için teşekkürler. Lütfen Github deposuna gidin ve daha fazla ayrıntı içeren bir sorunu açın (OS, sürümler, bunu yeniden üretmek için kod). Bunu birlikte çözmeye çalışacağız :)
EyalAr

@EyalAr Hey Eyal, görünüm nasıl yeniden boyutlandırılır ve korunur? (mümkün olan maksimum genişlik ve yükseklik boyutuna yeniden boyutlandırın)
Daniel Krom

10
2017'de lwip'i kullanmamanızı öneririm. Paket artık desteklenmiyor gibi görünüyor ve Windows'ta ve hatta Unix platformlarında bile büyük yükleme sorunları var.
zerefel

9
lwip maalesef ölü bir proje. keskin ancak yine de aktif olarak korunuyor gibi görünüyor.
laurent

16

Lwip'e bir göz atın: https://github.com/EyalAr/lwip

Çok basit ve kullanımı kolay

npm install lwip

ve sonra düğüm kodunuzda,

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

});

Bunu dosya yükleyicimde başarıyla uyguladım ve bir cazibe gibi çalışıyor.


1
Aradığım şey buydu, görüntü yeniden boyutlandırmayla ilgili birkaç işlev için aşırı, ağır harici bağımlılıklar yüklemek zorunda kalmadım.
zacr0

3
Btw @EyalAr, bu düğüm modülünün yazarıdır. Onun yorumu da aşağıda listelenmiştir.
Arvind

Kurulumu ve çalışması çok sezgisel. ImageMagick gibi herhangi bir ikili kitaplık uygulamanız gerekmemesini gerçekten çok seviyorum.
ChrisRich

Bu, tam olarak bu yanıtla aynı (lwip sahibi), ancak daha sonra: stackoverflow.com/a/24543924/1525495
Jorge Fuentes González

12

Jimp, diğer kitaplıklara bağımlılığı olmayan, tamamen JavaScript ile yazılmış iyi bir görüntü işleme kitaplığı var. https://github.com/oliver-moran/jimp

Örnek kullanım:

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

ImageMagik'e kıyasla bu ne kadar hızlı?
Christopher Grigg

2
Sharp'ın bir dizi kıyaslaması vardır: sharp.dimens.io/en/stable/performance --- Bu testte, jimp, IM'den 5 kat ve keskinten 30 kat daha yavaştır. Elbette yeterince hızlı yeterince hızlıdır ve dikkate alınması gereken tek faktör hız değildir.
jcupitt

Gerçek zamanlı olmayabilir, ancak Jimp yalnızca çok boyutlu küçük resim dosyaları yazmak için harikadır (ve daha sonra bunları önbelleğe alınmış dosyalar olarak geri alır).
coderofsalvation

jimp webp'yi desteklemez ve yakın gelecekte desteklemeyecektir. Bakınız: github.com/oliver-moran/jimp/issues/144
Viacheslav Dobromyslov

8

Sharp , son zamanlarda biraz popülerlik kazandı, ancak bu, * Magick bağlamaları ile aynı fikir.

Ancak, basit bir görüntü yeniden boyutlandırma yapmak için ImageMagick / GraphicsMagick'i kurmak zorunda kalmak benim için fazla abartılı görünüyor

Görüntüyü yeniden boyutlandırma basit olmaktan başka her şeydir. JPEG formatı özellikle karmaşıktır ve grafikleri farklı kalitede sonuçlarla ölçeklemenin birkaç yolu vardır, bunlardan birkaçı kolayca uygulanabilir. Bu işi yapmak için görüntü işleme kitaplıkları vardır, bu nedenle bunları yükleyememenizin başka bir nedeni yoksa, devam edin.


13
Belki tembel bir geliştiriciyim, ancak ImageMagick'in kurulum sürecini görür görmez ve onu Amazon AWS EC2 bulut sunucuma yüklemek için ne kadar harcayacağımı merak eder etmez hemen diğer seçenekleri aramaya başladım - özellikle de ihtiyacım olan tek şey küçük resimler için görüntüleri yeniden boyutlandırma yeteneği.
ChrisRich

7

Canvas, ImageMagic'ten 2,3 kat daha hızlıdır .

Görüntü manipülasyonu için Node.js modüllerini karşılaştırmayı deneyebilirsiniz - 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

3

Büyük bir resme ihtiyacınız yoksa, yüklemeden önce istemci tarafında yeniden boyutlandırabilirsiniz:

Dosya API'larını kullanarak JavaScript'teki dosyaları okuma

Sunucuya yüklemeden önce istemci tarafı javascript ile yeniden boyutlandırma

Birçok kullanıcı bir akıllı telefondan kendilerini iyi bir şekilde görebilir ve çoğu 200kB'nin üzerindedir. İstemci tarafından sağlanan verilere güvenilmeyeceğinden, sunucu tarafı kontrollerinin hala geçerli olduğunu unutmayın.


2
İstemciye asla güvenemezsiniz, bir kullanıcının oraya istediğini göndermek için yalnızca yükleme uç noktasını bilmesi gerekir. Dolayısıyla, dosya boyutu gibi doğrulamalar hala geçerlidir. Ancak, istemci tarafında yeniden boyutlandırma yine de iyi bir fikirdir.
Kev

1

Iwip kullanıyordum (daha önce arvind tarafından önerildiği gibi) ancak png- kırpmaya geçtim . Benim için biraz daha hızlı çalışıyor gibi görünüyor (Win 8.1 x64, Node v0.12.7). Depodaki kod inanılmaz derecede hafif görünüyor ve operasyonel olarak kullanımı basit.

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

Tabii ki, sadece png dosyaları yapacak ...


0

Sharp çok iyi çalışır ve akışlarla kullanımı kolaydır, bir cazibe gibi çalışır, ancak onu düğüm sürümüyle derlemeniz gerekir, bu onun bir dezavantajıdır. Sharp'ı görüntü işleme için AWS S3 kovasından bir görüntü ile kullanıyordum ve mükemmel bir şekilde çalıştım, ancak başka bir modül kullanmak zorunda kaldım. GM benim için çalışmadı ama Jimp çok iyi çalıştı!

Yazılı resmin yoluna dikkat etmelisiniz, yola "/" ile başlarsanız size bazı hatalar verebilir.

Jimp'i nodeJS'de böyle kullandım:

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

            });

Ayrıca yürütme sırasına dikkat edin, bir geri arama yapın, böylece istemediğinizde başka şeyler olmaz. Jimp.read () için "await" kullanmayı denedim, ancak işi iyi yapmadı.


Keskin 0.20'den itibaren, çoğu platformda tam düğüm sürümünüz için önceden derlenmiş bir ikili dosyayı otomatik olarak indirir, böylece hiçbir şey oluşturmanıza gerek kalmaz.
jcupitt

Ne yazık ki benim için işe yaramadı. Sharp'ı salt okunur bir dosya sisteminde, çeşitli node.js sürümleriyle kullanmam gerekiyordu ve kullandığım her düğüm sürümü için sharp modülünü indirmem gerekiyordu ve çok zaman alıyordu.
Alex Seceleanu

0

Bunu jimp (node_module) kullanarak yapabilirsiniz.

Yerel Yazma:

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'e veya istediğiniz yere yüklemek için.

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

0

Resize-img kitaplığını basitliği için seviyorum .

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

0

Google Drive API v3 kullanılarak görüntü yeniden boyutlandırma uygulandı . Bu yöntem, Google Apps Komut Dosyasının Google E-Tablolar'a resim eklemesi için önerilir.

Algoritma:

  1. Google Drive klasörüne resim yükleyin .
  2. Görüntünün genel URL'sini alın .
  3. URL'deki "yeniden boyutlandır" parametresini gerekli genişlik ve / veya yükseklik ile değiştirin. (Varsayılan küçük resim boyutu 220 pikseldir).
  4. Google Drive'dan yeniden boyutlandırılmış küçük resmi indirin.

Buradaki örneğe bakın: https://github.com/dobromyslov/google-drive-utils/blob/511c44c2c48862b47c60038423b7f71bf1d28f49/src/index.ts#L150

GDrive kotalarına dikkat edin:

  • günlük sorgu: 1000000000
  • kullanıcı başına 100 saniye başına sorgu: 1000
  • 100 saniye başına sorgu: 10000
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.