Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support for animated WEBP & GIF #2012

Merged
merged 11 commits into from
Aug 17, 2020
Merged

feat: support for animated WEBP & GIF #2012

merged 11 commits into from
Aug 17, 2020

Conversation

deftomat
Copy link
Contributor

@deftomat deftomat commented Dec 19, 2019

Requires libvips 8.9

New features:

  • load & save WEBP animations
  • load & save GIF animations

Please keep in mind that to create a GIF file, libvips must be compiled with imageMagick support (which could be a real pain 😞 )

@OJezu
Copy link

OJezu commented Dec 19, 2019

Re: imagemagick support

FROM node:12-slim

# Install libraries and programs
RUN true \
  && apt-get update \
  && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
      # needed for building
      automake build-essential \
      # libvips image libraries
      libjpeg-dev libtiff-dev libpng-dev libgif-dev librsvg2-dev libpoppler-glib-dev zlib1g-dev fftw3-dev liblcms2-dev \
      libmagickwand-dev libpango1.0-dev  libexif-dev liborc-0.4-dev libwebp-dev \
      # needed to rebuild sharp against global libvips
      python \
      # custom allocator to preserve rss memory
      libjemalloc1 \
  && apt-get autoremove -y \
  && apt-get autoclean \
  && apt-get clean \
  && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
  && true

# get your own from https://github.com/libvips/libvips/releases
COPY ./lib/vips-8.7.3.tar.gz /tmp/

# Build libvips
RUN true\
  && cd /tmp \
  && tar zxvf vips-8.7.3.tar.gz \
  && cd /tmp/vips-8.7.3 \
  && ./configure --enable-debug=no $1 \
  && make -j4 \
  && make install \
  && ldconfig \
  && rm -rf /tmp/* /var/tmp/* \
  true

# Change memory allocator to avoid leaks
ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.1

Use this as base for image of docker container with your application for imagemagic-enabled libvips.

@lovell
Copy link
Owner

lovell commented Dec 20, 2019

Thanks for this PR Tomáš, much appreciated, I expect to have some time to take a proper look at this during the next week or so.

@lovell
Copy link
Owner

lovell commented Dec 27, 2019

@deftomat There's now a pre-release 8.9.0-rc4 version of the prebuilt libvips binaries available to help with this PR.

You might also want to rebase against the wit branch as it has a couple of other changes required for libvips v8.9.x.

This should allow you to fix up the linting errors and test failures.

@salipitchero
Copy link

salipitchero commented Jan 6, 2020

hi @deftomat & @lovell

just to jump in on this, this seems to rebase pretty easily with the wit branch. Linting and tests pass apart from three.

  1) GIF input
       Animated GIF first page to PNG:
     Error: VipsOperation: class "magicksave_buffer" not found

  2) GIF input
       Animated GIF all pages to PNG "toilet roll":
     Error: VipsOperation: class "magicksave_buffer" not found

  3) Input/output
       Output filename with unknown extension
         Autoconvert GIF input to PNG output:
     Uncaught Error: VipsOperation: class "magicksave" not found

not sure if the tests need amending, or if, in an environment without libvips + imagemagick, it needs a fallback.

@christianbundy
Copy link

This is super exciting! Would this change require ImageMagick for everyone using Sharp, or just people who want WebP / GIF?

@lovell
Copy link
Owner

lovell commented Jan 8, 2020

@christianbundy Please see #1372 (comment)

"The prebuilt libvips binaries provided by sharp do not include *magick. To take advantage, you will need to compile your own libvips with support for *magick and install it globally before installing sharp."

@elemarin
Copy link

@lovell is there plans for creating a version of sharp that includes prebuild libvips with *magick support? maybe have a flag during installation or something like that? since we use Sharp in a production application running in windows, and using a globally installed version of libvips is not supported in windows, this means that we will never be able to use these features.

@lovell
Copy link
Owner

lovell commented Jan 14, 2020

@elndro85 No, but all the tools to build your own are open source - see https://github.com/lovell/sharp-libvips

@summera
Copy link

summera commented Jan 15, 2020

@lovell in order to get this built and working with magick support for linux-x64, for example, would you simply need to add ImageMagick-devel as a package dependency in the Dockerfile from https://github.com/lovell/sharp-libvips/blob/master/linux-x64/Dockerfile and build with the build script?

I did that and also attempted a rebase of this branch on top of your wit branch for testing sharp with the libvips binaries I built, but it resulted in a lot of issues when installing sharp after the rebase. Anything I can help with to move this along?

@kapouer
Copy link
Contributor

kapouer commented Jan 21, 2020

What about APNG ?

@lovell
Copy link
Owner

lovell commented Jan 21, 2020

@kapouer libpng, as used by libvips, does not support APNG.

@summera
Copy link

summera commented Jan 28, 2020

@lovell looks like your wit branch was merged and there was a new release. Does this branch now need to be rebased on master before it's ready?

@lovell
Copy link
Owner

lovell commented Jan 28, 2020

The latest version of sharp depends on (and provides a prebuilt) libvips v8.9.0 as required by the changes in this PR, so yes, it can now be rebased against the master branch.

@deftomat
Copy link
Contributor Author

deftomat commented Jan 29, 2020

AWESOME! 🥳

Sorry to everyone which is waiting for this. I didn't have a much time lately but I will try to finish it this weekend.

@Charuru
Copy link

Charuru commented Feb 7, 2020

How about this weekend?

@adityapatadia
Copy link

How about next one?

@lovell
Copy link
Owner

lovell commented Mar 14, 2020

@deftomat The internals of sharp have been migrated to N-API hence there are now a few conflicts in this PR. As always, I'm happy to keep PRs open for as long as necessary; please ignore any implied time pressure in comments.

I'd also be happy to accept an alternative PR that focuses on WebP. Avoiding the *magick dependency might make for a simpler method by which to introduce this feature initially.

@adityapatadia
Copy link

Jokes aside, I am really interested in getting this merged to master so it can be released. @deftomat @lovell can you let me know if I can help in any way. I have limited knowledge of C but I will try as much as I can.

@adityapatadia
Copy link

Even if we can get WebP ones without Magick support it will still be good.

@deftomat
Copy link
Contributor Author

@adityapatadia

Ok, let's finish this PR. We need to upgrade our fork to the latest Sharp anyway.

@adityapatadia
Copy link

@adityapatadia

Ok, let's finish this PR. We need to upgrade our fork to the latest Sharp anyway.

Please let me know how can I help you in this. I am ready to offer my axe.

src/pipeline.cc Outdated Show resolved Hide resolved
@deftomat
Copy link
Contributor Author

deftomat commented Apr 27, 2020

@lovell

I got the following test failures:

1) GIF input
       Animated GIF first page to PNG:
     Error: VipsOperation: class "magicksave_buffer" not found

  

  2) GIF input
       Animated GIF all pages to PNG "toilet roll":
     Error: VipsOperation: class "magicksave_buffer" not found

  

  3) Input/output
       Output filename with unknown extension
         Autoconvert GIF input to PNG output:
     Uncaught Error: VipsOperation: class "magicksave" not found

  

  4) Utilities
       Counters
         Have zero value at rest:

      AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:

I'm not sure how we want to test GIF features as ImageMagick support is not included by default.

Also, I'm not sure what the 4th failure means.

Copy link
Owner

@lovell lovell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking so much better, thank you very much - I've left a few comments inline.

lib/output.js Outdated Show resolved Hide resolved
src/common.cc Show resolved Hide resolved
src/common.cc Outdated Show resolved Hide resolved
test/unit/gif.js Outdated Show resolved Hide resolved
@lovell
Copy link
Owner

lovell commented Jun 30, 2020

I've created #2275 with some thoughts on possible future improvements to handling animated/multipage images beyond this PR.

@lovell
Copy link
Owner

lovell commented Aug 14, 2020

@deftomat I'm preparing v0.26.0 for release. hopefully in the next few days. Are you able to take a look at the last couple of remaining comments? I might have a chance to address them myself, otherwise this can wait until a future v0.26.x release.

@deftomat
Copy link
Contributor Author

@lovell I will try this weekend

@deftomat
Copy link
Contributor Author

@lovell Comments resolved!

@lovell lovell merged commit cb1baed into lovell:master Aug 17, 2020
@lovell
Copy link
Owner

lovell commented Aug 17, 2020

@deftomat Marvellous, thank you very much for persisting with this Tomáš.

lovell added a commit that referenced this pull request Aug 17, 2020
@lovell
Copy link
Owner

lovell commented Aug 18, 2020

Commit 4beae0d adds animated as a constructor property shortcut for pages=-1 to allow the following API:

// Convert an animated GIF to an animated WebP (available from v0.26.0)
sharp('in.gif', { animated: true }).toFile('out.webp');

@deftomat
Copy link
Contributor Author

Sounds good!

@lovell
Copy link
Owner

lovell commented Aug 25, 2020

v0.26.0 now available, enjoy!

@nglazov
Copy link

nglazov commented Aug 31, 2020

@lovell may it be used with resize somehow?
I'm getting large canvas with all frames instead of animated gif
111

My code

sharp(buffer, { animated: true })
    .resize({
        height: 100,
        width: 100,
    })
    .toBuffer();

@JulianBerger
Copy link

@lovell may it be used with resize somehow?
I'm getting large canvas with all frames instead of animated gif

Thats what #2275 is about

@davekiss
Copy link

I'm an idiot and don't know what I'm doing, but would like to use this feature on AWS Lambda – can anyone help with steps to compile libvips + *magick so it can be used there?

@deftomat
Copy link
Contributor Author

deftomat commented Sep 21, 2020

@davekiss Hi, we have our custom sharp-libvips fork where we add IM support.

You need to add something like the following before libvips build:

mkdir ${DEPS}/libtool
curl -Ls http://ftpmirror.gnu.org/libtool/libtool-${VERSION_LIBTOOL}.tar.gz | tar xzC ${DEPS}/libtool --strip-components=1
cd ${DEPS}/libtool
./configure --host=${CHOST} --prefix=${TARGET} --enable-shared --disable-static --disable-dependency-tracking
make install-strip

mkdir ${DEPS}/imagemagick
cd ${DEPS}/imagemagick
curl -O https://imagemagick.org/download/ImageMagick.tar.gz
tar xzf ImageMagick.tar.gz
rm ImageMagick.tar.gz
cd */.
./configure \
  --host=${CHOST} \
  --prefix=${TARGET} \
  --enable-shared \
  --disable-static \
  --with-modules \
  --without-bzlib \
  --without-dps \
  --without-freetype \
  --without-jbig \
  --without-jpeg \
  --without-jp2 \
  --without-lcms \
  --without-lzma \
  --without-png \
  --without-tiff \
  --without-wmf \
  --without-xml \
  --without-zlib \
  --without-perl \
  --without-x \
  --without-magick-plus-plus \
  --enable-delegate-build \
  --disable-dependency-tracking \
  --disable-docs \
  --disable-openmp \
  --disable-installed
make install-strip

And then use --with-magick in libvips build script instead of --without-magick.

Not entirely sure if that is enough as we customised it a while ago but it should be enough.

Then, just follow https://sharp.pixelplumbing.com/install#custom-prebuilt-binaries to build it in AWS Lambda docker container, deploy sharp as layer and require it directly from /opt/sharp directory instead of node_modules.

@OJezu
Copy link

OJezu commented Sep 21, 2020

@davekiss It's the first comment. #2012 (comment)

@cthorner
Copy link

cthorner commented Sep 23, 2020

How would I stitch together images and output an animated gif? Do I need to create the buffer with some other tool? Or can I use sharp to incrementally add the images, maybe even as a stream?

To be more specific, can I do something like this:

sharp(
 [
  {input: firstPage}, 
  { input: secondPage}
 ], 
 { animated: true }]
).gif({ animated: true, delay: [100, 200], pageHeight: 200 }) })
.toFile('somefile.gif')

Or should I be using compose?

On a side note, compiling imagemagick with the above instructions didn't work for me. I'm getting a format not detected error from imagemagick for 'gif'. Do I need to add LDFLAGS or something like that?

@xdays
Copy link

xdays commented Nov 3, 2020

Does anyone have a sample code for animated webp resizing?

I have a workable piece of code for gif:

sharp('tb.gif', {
  animated: true
})
  .resize(60).gif({
    pageHeight: 60
  })
  .toFile('resized.gif');

but webp doesn't work

sharp("tb.webp", {
  animated: true,
})
  .resize(160)
  .webp({
    pageHeight: 160,
  })
  .toFile("resized.webp", (err, info) => {
    console.log(err, info);
  });

@gonber
Copy link

gonber commented Feb 9, 2021

Is this supposed to also allow resizing? I'm struggling to get sharp({ animated: true }).resize(...) to work with a GIF. Thanks!
Nevermind, saw issue #2296 #2275

Repository owner locked and limited conversation to collaborators Feb 10, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.