npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

tinygif

v2.3.0

Published

Fast and efficient animated gif creator in EcmaScript.

Downloads

8

Readme

Tinygif

Fast and efficient animated gif creator in EcmaScript.

This code is based on @sole's https://github.com/sole/Animated_GIF. It adds a few optimizations:

  • Optimized for reading from a canvas (requires a single worker)
  • Starting processing while still recording frames
  • Leverage global palette where possible
  • Try to use a 256 color palette before Quantizing
  • Attempt to skip duplicate frames
  • Render/write only the changed portion (delta) of each frame

In general this makes processing much faster and significantly reduces the size of the generated files hence, more eficient.

How it works

Tinygif records 5 seconds of a canvas and generates a Gif. There are three phases:

  • Capturing - every 20 ms a new frame is captured from the canvas (note 20ms is the default delay for 50 frames per second which is the default FPS)
  • Processing - each captured frame is processed to determine the optimal palette for the frame and what changed per frame. This happens in a web worker and starts immediately in the background once frames are captured
  • Rendering - when capturing and processing are complete a final Gif is rendered from the processed frames. It is returned as a Blob

How to use it

let canvas = document.getElementById("demo-canvas")

let start = Date.now()

const progress = (recorder, count) => {
  console.log((Date.now() - start) + 'ms elapsed; Frames: ' + count)
}

const record = async () => {
  start = Date.now()
  let tg = new Tinygif({}, progress) // you may need new Tinygif.default(...)
  let blob = await tg.record(canvas)
  let img = document.createElement("img")
  img.src = URL.createObjectURL(blob)
  document.body.appendChild(img)
  // Note there is usually a delay between the end of capturing
  // frames (which fire progress events) and completing the processing
  // of frames and the rendering of the movie
  console.log((Date.now() - start) + 'ms elapsed; Done')
}

// Record for five seconds, the default
record()

Todo

  • In the case of Neural Quantization the generated palette is complex and unlikely to be reusable. Additionally it is usually 256 colors (we sample the maximum we can). Because of this we don't even attempt to re-use the global palette per frame to save time. This is a good trade-off and almost always right - but we could go further. Once the palette is full (because it is based on the quantizer or just completely full of colors) nothing further will change the preamble/header. At that point gif rendering (the step after frame processing) could begin immediately. Not only would this save time but rendered frames could be completely discarded and this would reduce the total amount of memory used while generating. For longer gifs this would be a dramatic saving. Additionally, reduced memory could prevent swapping and increase speed.
  • I've experimented with removing the worker code and just processing directly; this prevented a lot of buffer copying and stringifying and generally sped things up but frame-lag became a real issue for complex canvas animations. I would love to simplify the interface and make workers optional.
  • When capturing is not in sync (it takes longer to capture a frame than the interval) the code does not adjust well. Some options:
    • Use setTimeout instead of setInterval and correct for drift
    • Adjust the delay of the generated frame so account for the lag (this is difficult because frame delays are in hundredths of seconds making them not precise enough)
    • Skip frames (this looks very choppy)
    • If you don't capture enough frames and you don't adjust the delays then you end up with an animation that plays faster than the recorded time and looks "sped up". This is the trade-off we are accepting for now.
  • Upgrade more code to ES2017
  • https://developer.mozilla.org/en-US/docs/Web/API/Transferable, https://developers.google.com/web/updates/2011/12/Transferable-Objects-Lightning-Fast

Dev

Run a dev server: yarn start

Build continuously: yarn build:watch

Change the version in package.json and npm publish

Credits

We based it on:

  • https://github.com/sole/Animated_GIF

We're using these fantastic libraries to do GIF stuff:

  • Anthony Dekker's NeuQuant image quantization algorithm which was ported from C into Java by Kevin Weiner and then to ActionScript 3 by Thibault Imbert, and to JavaScript by antimatter15, and fixed, patched and revised by sole.
  • Dean McNamee's omggif library - for actually encoding into GIF89

Thanks to: