Lee Maan
Lee Maan

Reputation: 719

Node ImageMagick succeed locally but fails in AWS Lambda

I'm using this Node ImageMagick for validating images via converting them in AWS Lambda function. Locally I have no problem, but when I deploy my function I get the error no decode delegate for this image format on some images only:

{ Error: Command failed: convert: no decode delegate for this image format `/tmp/925bf249f8297827f51f0370642eb560.jpg' @ error/constitute.c/ReadImage/544.
convert: no images defined `/tmp/5d2baeb2-de13-4868-a970-ad919c609440.png' @ error/convert.c/ConvertImageCommand/3046.

at ChildProcess.<anonymous> 
(/var/task/node_modules/imagemagick/imagemagick.js:88:15)
at emitTwo (events.js:106:13)
at ChildProcess.emit (events.js:191:7)
at maybeClose (internal/child_process.js:886:16)
at Socket.<anonymous> (internal/child_process.js:342:11)
at emitOne (events.js:96:13)
at Socket.emit (events.js:188:7)
at Pipe._handle.close [as _onclose] (net.js:497:12) timedOut: false, killed: false, code: 1, signal: null }

This is after I failed to use ImageMagick that's built-in for AWS Lambda. Any idea how I can solve this?

Upvotes: 1

Views: 1559

Answers (1)

Lee Maan
Lee Maan

Reputation: 719

Finally I figured it out! There is no short way for this. This is what I ended up doing:

  • I ran Parallel on my Mac and I got the binaries of ImageMagick installed on a virtual CentOS machine. To install the binaries I followed the guides in the official website. I wrote a lot of commands in my virtual machine but I can summarise them in:

    yum install sudo -y
    sudo yum -y install libpng-devel libjpeg-devel libtiff-devel gcc
    sudo curl -O http://www.imagemagick.org/download/ImageMagick.tar.gz
    sudo yum install tar -y
    sudo tar zxvf ImageMagick.tar.gz
    cd ImageMagick-7.0.8-22
    sudo ./configure --prefix=/var/task/imagemagick --enable-shared=no --enable-static=yes
    sudo yum install make -y
    sudo yum install automake autoconf libtool -y
    sudo sed -i 's|(gitversion|(./gitversion|' configure.ac
    sudo yum install git -y
    sudo autoreconf -i
    sudo sed -i '$a LANG=en_US.utf-8' /etc/environment
    sudo sed -i '$a LC_ALL=en_US.utf-8' /etc/environment
    sudo make
    sudo make install
    tar zcvf ~/imagemagick.tgz /var/task/imagemagick/`
    
  • Then I copied the installation folder from the virtual machine into a folder I named /lib in my root directory of AWS Lambda repository.

  • Then in order to use the new binaries, I needed to copy ImageMagick folder from /lib into my node_modules on every deployment. This is because AWS Lambda didn't allow me to access any binary file from the /lib directly for unknown reason. In order to perform the copy on every deployment I added the following line to my deploy.sh file:

    `cp -R ./lib/imagemagick ./node_modules/imagemagick`
    
  • Now the binaries are ready to be used, but still AWS Lambda didn't give me permission to run any command directly from within node_modules. So every time I needed to run a particular command I needed to copy it (it is a binary file) into the /tmp folder and then I needed to change its mode chmod to be able to run it. This is the code for every needed command (in Node):

    const command = '/node_modules/imagemagick/[command path and file]';
    execSync(`cp -a ${command} /tmp/`);
    fs.chmodSync(command, 755);
    execSync(`chmod +x ${command}`);
    
  • Now the command is ready to be used with child_process. For example:

    const argus = [originalImage, '-o', newImage];
    child_process.execFile(command, argus, (err, stdout, stderr) (
        if (err) throw err;
        console.log('IMAGE CONVERTED');
    )}
    
  • The above applies not only on ImageMagick, but on any other binary needed with AWS Lambda. I applied the same on Google's WebP library somewhere else in my function. I downloaded its Linux binaries from Google developers website.

This is it. My code works as expected. If you have any better idea on improving it I would appreciate a comment.

Upvotes: 3

Related Questions