Giter Club home page Giter Club logo

gifski's Introduction

gif.ski

Highest-quality GIF encoder based on pngquant.

gifski converts video frames to GIF animations using pngquant's fancy features for efficient cross-frame palettes and temporal dithering. It produces animated GIFs that use thousands of colors per frame.

(CC) Blender Foundation | gooseberry.blender.org

It's a CLI tool, but it can also be compiled as a C library for seamless use in other apps.

Download and install

See releases page for executables.

If you have Homebrew, you can also get it with brew install gifski.

If you have Rust from rustup (1.63+), you can also build it from source with cargo install gifski.

Usage

gifski is a command-line tool. If you're not comfortable with a terminal, try the GUI version for Windows or for macOS.

From ffmpeg video

Tip: Instead of typing file paths, you can drag'n'drop files into the terminal window!

If you have ffmpeg installed, you can use it to stream a video directly to the gifski command by adding -f yuv4mpegpipe to ffmpeg's arguments:

ffmpeg -i video.mp4 -f yuv4mpegpipe - | gifski -o anim.gif -

Replace "video.mp4" in the above code with actual path to your video.

Note that there's - at the end of the command. This tells gifski to read from standard input. Reading a .y4m file from disk would work too, but these files are huge.

gifski may automatically downsize the video if it has resolution too high for a GIF. Use --width=1280 if you can tolerate getting huge file sizes.

From PNG frames

A directory full of PNG frames can be used as an input too. You can export them from any animation software. If you have ffmpeg installed, you can also export frames with it:

ffmpeg -i video.webm frame%04d.png

and then make the GIF from the frames:

gifski -o anim.gif frame*.png

Note that * is a special wildcard character, and it won't work when placed inside quoted string ("*").

You can also resize frames (with -W <width in pixels> option). If the input was ever encoded using a lossy video codec it's recommended to at least halve size of the frames to hide compression artefacts and counter chroma subsampling that was done by the video codec.

See gifski --help for more options.

Tips for smaller GIF files

Expect to lose a lot of quality for little gain. GIF just isn't that good at compressing, no matter how much you compromise.

  • Use --width and --height to make the animation smaller. This makes the biggest difference.
  • Add --quality=80 (or a lower number) to lower overall quality. You can fine-tune the quality with:
    • --lossy-quality=60 lower values make animations noisier/grainy, but reduce file sizes.
    • --motion-quality=60 lower values cause smearing or banding in frames with motion, but reduce file sizes.

If you need to make a GIF that fits a predefined file size, you have to experiment with different sizes and quality settings. The command line tool will display estimated total file size during compression, but keep in mind that the estimate is very imprecise.

Building

  1. Install Rust via rustup. This project only supports up-to-date versions of Rust. You may get errors about "unstable" features if your compiler version is too old. Run rustup update.
  2. Clone the repository: git clone https://github.com/ImageOptim/gifski
  3. In the cloned directory, run: cargo build --release. This will build in ./target/release.

Using from C

See gifski.h for the C API. To build the library, run:

rustup update
cargo build --release

and link with target/release/libgifski.a. Please observe the LICENSE.

C dynamic library for package maintainers

The build process uses cargo-c for building the dynamic library correctly and generating the pkg-config file.

rustup update
cargo install cargo-c
# build
cargo cbuild --prefix=/usr --release
# install
cargo cinstall --prefix=/usr --release --destdir=pkgroot

The cbuild command can be omitted, since cinstall will trigger a build if it hasn't been done already.

License

AGPL 3 or later. I can offer alternative licensing options, including commercial licenses. Let me know if you'd like to use it in a product incompatible with this license.

With built-in video support

The tool optionally supports decoding video directly, but unfortunately it relies on ffmpeg 6.x, which may be very hard to get working, so it's not enabled by default.

You must have ffmpeg and libclang installed, both with their C headers installed in default system include paths. Details depend on the platform and version, but you usually need to install packages such as libavformat-dev, libavfilter-dev, libavdevice-dev, libclang-dev, clang. Please note that installation of these dependencies may be quite difficult. Especially on macOS and Windows it takes expert knowledge to just get them installed without wasting several hours on endless stupid installation and compilation errors, which I can't help with. If you're cross-compiling, try uncommenting [patch.crates-io] section at the end of Cargo.toml, which includes some experimental fixes for ffmpeg.

Once you have dependencies installed, compile with cargo build --release --features=video or cargo build --release --features=video-static.

When compiled with video support ffmpeg licenses apply. You may need to have a patent license to use H.264/H.265 video (I recommend using VP9/WebM instead).

gifski -o out.gif video.mp4

Cross-compilation for iOS

The easy option is to use the included gifski.xcodeproj file to build the library automatically for all Apple platforms. Add it as a subproject to your Xcode project, and link with gifski-staticlib Xcode target. See the GUI app for an example how to integrate the library.

Cross-compilation for iOS manually

Make sure you have Rust installed via rustup. Run once:

rustup target add aarch64-apple-ios

and then to build the library:

rustup update
cargo build --lib --release --target=aarch64-apple-ios

The build may print "dropping unsupported crate type cdylib" warning. This is expected when building for iOS.

This will create a static library in ./target/aarch64-apple-ios/release/libgifski.a. You can add this library to your Xcode project. See gifski.app for an example how to use libgifski from Swift.

gifski's People

Contributors

0bmay avatar 20kdc avatar andylizi avatar badlogic avatar brlin-tw avatar chenrui333 avatar cl-jeremy avatar dependabot-preview[bot] avatar dependabot[bot] avatar hybridgorilla897 avatar jakechampion avatar kianmeng avatar kornelski avatar liamross avatar orhun avatar pekkarr avatar scribblemaniac avatar strafe avatar timvisee avatar vitorgalvao avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gifski's Issues

Any way or math formula to get an estimated filesize please ?

Hello kornelski,

After spending lot of time on trying to get the video support on windows i gave up on this and used my poor powershell knowledge to make me a small script to automate all this while using it inside Staxrip.

anim

I select/trim the section of the video i want, add filters or some text or whatever is needed then call the powershell script from a custom menu i added into Staxrip, set my parameters and it will feed ffmpeg with the avisynth script, exctract the frames and make the gif, just a few popup forms to set the parameters and the rest is automated :)

Still a work in progress that needs polishing but works nicely for now, only a bit slow due to no openmp on windows so now i'm wondering if it is possible somehow to grossly get an estimated size for the .gif before it is created. It doesn't need to be very precise tho.

I often need to create a few times the gif with different width/height (or quality setting) to comply with something acceptable i can upload and not end with a file too big, and with the slow speed to create the gif it can be painful so if i am able to get a rough size estimation directly in my script before launching the work it will be very helpful.

If you have any tips or ideas about a mathematical formula to get an estimated size based on the number of frames the gif will have, the quality selected for the gif and width & height maybe ?

Thanks a lot in advance.

Segfault on i686-pc-windows-gnu since v0.8.4

After upgrading from 0.8.3 (which worked fine) to 0.8.6 my bindings start segfaulting during the examples on mingw32 (i686-pc-windows-gnu). The problem does not occur on Linux or MacOS or even x86_64-pc-windows-gnu, only on 32bit windows.

It looks like the problem started somewhere in between 0.8.3 and 0.8.4. I'm sorry for not being able to provide more detailed information, I'm having a hard time getting a backtrace from gdb on Windows. Below what I am seeing.

Any guess to something that could have changed after 0.8.3 that affects i386 targets? There may also be a conflict between the version of gcc mingw32 that I use to compile my bindings and the one rust assumes, though it was working fine before.

capture

Linux != Ubuntu or Debian

Hi,
I know the title is a bit... enoying :)

But really, in "release" package, try to not call "Linux" Debian only packages... I was so exciting to use it in Fedora/CentOS/RedHat, then I was so disappointed to see a "linux" directory with only .deb file.

(Yes... I will compile it)

Cheers ;)

Quality 0 shows only first frame

Not sure if this is intentional, but with quality set to 0 only the first frame is filled. All other frames are completely transparent:

quality0

Quality 1 will show the animation again:

quality01

Compile fails

Hi.
I just tried to compile it from git. But it fails with the following error:
`andreas@Nbk:~/src/gifski$ cargo run --release --features=openmp

Downloading openmp-sys v0.1.1

Compiling glob v0.2.11
Compiling num_cpus v1.7.0
Compiling ansi_term v0.9.0
Compiling imgref v1.3.0
error: no method named min found for type usize in the current scope
--> /home/andreas/.cargo/registry/src/github.com-1ecc6299db9ec823/imgref-1.3.0/src/iter.rs:75:56
|
75 | self.buf_left = &self.buf_left[self.stride.min(self.buf_left.len()-1)..];
| ^^^
|
= note: the method min exists but the following trait bounds were not satisfied: usize : std::iter::Iterator

error: aborting due to previous error

error: Could not compile imgref.
Build failed, waiting for other jobs to finish...
error: build failed
andreas@Nbk:~/src/gifski$ #
`

Glitchy Animation Due to File Names

If you have a png sequence that are named like "Example1.png" "Example2.png" ... "Example10.png" "Example11.png". The gif animation will be glitchy. I had to use a separate program to batch rename the files to "Example001.png", "Example002.png", etc.

command used to generate the gif

gifski.exe Rainbow_Animation_*.png -o Rainbow_Animation.gif --fps 40

Before renaming the files:
arainbowanimationtest

After renaming the files:
arainbowanimation

I know that the best practice for naming files is to add zeros before the single number so the number is the same length as the largest number in the sequence. But adding support to get the correct sequence for "badly" named files should be there so it doesn't confuse any users. In some cases, the user can't help it since some animation applications doesn't name the files "correctly" and they also don't give you the option to format the filename on export. Alternatively, you could add a troubleshooting/FAQ page on the website.

Document library API

The webpage says:

...but it can also be compiled as library for seamelss use in other apps..

I'm interested in compiling it as a library and calling from C, which API should I be using?

NPM

It would be really cool if you could somehow put this on npm, if anything just a binary similar to the npm module ffmpeg-binaries.

Strange output when using WebM video directly

I tried to convert the WebM video file in test.zip directly with:

gifski -o a.gif test.webm

The result is this:

a

When I first convert the video to frames with ffmpeg and convert the frames I get a proper result:

ffmpeg -i test.webm frame%04d.png
gifski -o b.gif frame*.png

b

Tested with latest master revision and ffmpeg 3.4.

Option to turn off dithering - useful with screencasts where little changes on screen

I guess this might sound like it defeats the purpose of gifski, but when turning a screencapture into a gif, usually the frame-to-frame changes are absolutely minimal. It usually makes more sense to either turn off dithering, or to use a stable dithering option in that case.

gifski uses pngquant under the hood, right? And that already supports turning off FS dithering with --nofs for precisely this kind of use case (but I don't know how much work it is to integrate that with gifski of course).

For comparison, GIMP does both better and worse at this: I just tried converting a 2,1 MiB mp4, recordging of a short Full HD screen grab. processed with gifski it becomes a 54,8 MiB gif, with GIMP 14,3. However, GIMP takes a lot more time to generate the output, generates uglier colors than gifski, and somehow the resulting gif also manages to be a lot more sluggish to play back.

Video support is permanently disabled in this executable with CLI version

Hi, I`m getting this error while running the same command that worked fine with v0.6.0:

Command:

--quality 50 --fps 8 "C:\Users\Usr\AppData\Local\Temp\Frames\*.png" -o "C:\Users\Usr\Desktop\1.gif"

Result:

Error: Video support is permanently disabled in this executable.

To enable video decoding you need to recompile gifski from source with:
cargo build --release --features=video

Alternatively, use ffmpeg command to export PNG frames, and then specify
the PNG files as input for this executable.

Not sure what changed from v0.6.0 and v0.7.0...

FFmpeg 4.0 compatibility

I've also reported this to meh/rust-ffmpeg#112

I'm not sure whether you want to wait on them to fix it, help them fix it, or do something else.

The failure is

==> Downloading https://github.com/ImageOptim/gifski/archive/0.8.2.tar.gz
Already downloaded: /Users/joe/Library/Caches/Homebrew/gifski-0.8.2.tar.gz
==> Verifying gifski-0.8.2.tar.gz checksum
tar xzf /Users/joe/Library/Caches/Homebrew/gifski-0.8.2.tar.gz
==> cargo build --release --features=video
    Updating registry `https://github.com/rust-lang/crates.io-index`
    Updating git repository `https://github.com/kornelski/rust-ffmpeg.git`
    Updating git repository `https://github.com/meh/rust-ffmpeg-sys`
 Downloading pbr v1.0.0
 Downloading rayon v0.9.0
 Downloading imagequant v2.11.9
 Downloading gif-dispose v2.1.0
 Downloading lodepng v2.1.2
 Downloading error-chain v0.11.0
 Downloading wild v0.1.1
 Downloading imgref v1.3.3
 Downloading rgb v0.8.7
 Downloading clap v2.30.0
 Downloading gif v0.9.2
 Downloading resize v0.3.0
 Downloading glob v0.2.11
 Downloading kernel32-sys v0.2.2
 Downloading winapi v0.2.8
 Downloading libc v0.2.37
 Downloading time v0.1.39
 Downloading winapi-build v0.1.1
 Downloading rayon-core v1.4.0
 Downloading either v1.4.0
 Downloading rand v0.4.2
 Downloading lazy_static v1.0.0
 Downloading crossbeam-deque v0.2.0
 Downloading num_cpus v1.8.0
 Downloading crossbeam-utils v0.2.2
 Downloading crossbeam-epoch v0.3.0
 Downloading cfg-if v0.1.2
 Downloading nodrop v0.1.12
 Downloading scopeguard v0.3.3
 Downloading arrayvec v0.4.7
 Downloading memoffset v0.2.1
 Downloading lazy_static v0.2.11
 Downloading imagequant-sys v2.11.9
 Downloading cc v1.0.4
 Downloading lzw v0.10.0
 Downloading color_quant v1.0.0
 Downloading backtrace v0.3.5
 Downloading rustc-demangle v0.1.7
 Downloading bitflags v0.9.1
 Downloading pkg-config v0.3.9
 Downloading bindgen v0.32.3
 Downloading regex v0.2.6
 Downloading log v0.3.9
 Downloading cexpr v0.2.3
 Downloading proc-macro2 v0.2.3
 Downloading quote v0.4.2
 Downloading which v1.0.5
 Downloading env_logger v0.4.3
 Downloading clang-sys v0.21.2
 Downloading peeking_take_while v0.1.2
 Downloading log v0.4.1
 Downloading strsim v0.7.0
 Downloading atty v0.2.6
 Downloading unicode-width v0.1.4
 Downloading textwrap v0.9.0
 Downloading bitflags v1.0.1
 Downloading vec_map v0.8.0
 Downloading nom v3.2.1
 Downloading memchr v1.0.2
 Downloading utf8-ranges v1.0.0
 Downloading aho-corasick v0.6.4
 Downloading thread_local v0.3.5
 Downloading regex-syntax v0.4.2
 Downloading memchr v2.0.1
 Downloading unreachable v1.0.0
 Downloading void v1.0.2
 Downloading unicode-xid v0.1.0
 Downloading libloading v0.4.3
 Downloading ansi_term v0.10.2
   Compiling libloading v0.4.3
   Compiling either v1.4.0
   Compiling ffmpeg v0.2.0-alpha.2 (https://github.com/kornelski/rust-ffmpeg.git#0eea6d01)
   Compiling cc v1.0.4
   Compiling rgb v0.8.7
   Compiling winapi v0.2.8
   Compiling libc v0.2.37
   Compiling strsim v0.7.0
   Compiling regex-syntax v0.4.2
   Compiling utf8-ranges v1.0.0
   Compiling bindgen v0.32.3
   Compiling void v1.0.2
   Compiling bitflags v1.0.1
   Compiling vec_map v0.8.0
   Compiling scopeguard v0.3.3
   Compiling unicode-width v0.1.4
   Compiling nodrop v0.1.12
   Compiling peeking_take_while v0.1.2
   Compiling resize v0.3.0
   Compiling rayon-core v1.4.0
   Compiling winapi-build v0.1.1
   Compiling wild v0.1.1
   Compiling imgref v1.3.3
   Compiling bitflags v0.9.1
   Compiling pkg-config v0.3.9
   Compiling glob v0.2.11
   Compiling unicode-xid v0.1.0
   Compiling lazy_static v1.0.0
   Compiling rustc-demangle v0.1.7
   Compiling memoffset v0.2.1
   Compiling color_quant v1.0.0
   Compiling cfg-if v0.1.2
   Compiling ansi_term v0.10.2
   Compiling lzw v0.10.0
   Compiling lazy_static v0.2.11
   Compiling atty v0.2.6
   Compiling which v1.0.5
   Compiling time v0.1.39
   Compiling memchr v1.0.2
   Compiling rand v0.4.2
   Compiling lodepng v2.1.2
   Compiling memchr v2.0.1
   Compiling num_cpus v1.8.0
   Compiling unreachable v1.0.0
   Compiling textwrap v0.9.0
   Compiling arrayvec v0.4.7
   Compiling kernel32-sys v0.2.2
   Compiling proc-macro2 v0.2.3
   Compiling backtrace v0.3.5
   Compiling log v0.4.1
   Compiling crossbeam-utils v0.2.2
   Compiling clang-sys v0.21.2
   Compiling imagequant-sys v2.11.9
   Compiling gif v0.9.2
   Compiling nom v3.2.1
   Compiling thread_local v0.3.5
   Compiling aho-corasick v0.6.4
   Compiling clap v2.30.0
   Compiling crossbeam-epoch v0.3.0
   Compiling log v0.3.9
   Compiling error-chain v0.11.0
   Compiling gif-dispose v2.1.0
   Compiling regex v0.2.6
   Compiling quote v0.4.2
   Compiling crossbeam-deque v0.2.0
   Compiling pbr v1.0.0
   Compiling imagequant v2.11.9
   Compiling cexpr v0.2.3
   Compiling rayon v0.9.0
   Compiling env_logger v0.4.3
   Compiling ffmpeg-sys v3.4.1 (https://github.com/meh/rust-ffmpeg-sys#9056485f)
error[E0425]: cannot find value `AV_PIX_FMT_VDA_VLD` in this scope
   --> .brew_home/.cargo/git/checkouts/rust-ffmpeg-4e2fa0d809f646b8/0eea6d0/src/util/format/pixel.rs:696:26
    |
696 |             Pixel::VDA_VLD     => AV_PIX_FMT_VDA_VLD,
    |                                   ^^^^^^^^^^^^^^^^^^ did you mean `AV_PIX_FMT_VAAPI_VLD`?

error[E0425]: cannot find value `AV_PIX_FMT_VDA` in this scope
   --> .brew_home/.cargo/git/checkouts/rust-ffmpeg-4e2fa0d809f646b8/0eea6d0/src/util/format/pixel.rs:740:18
    |
740 |             Pixel::VDA => AV_PIX_FMT_VDA,
    |                           ^^^^^^^^^^^^^^ did you mean `AV_PIX_FMT_CUDA`?

error[E0425]: cannot find value `AVFMT_RAWPICTURE` in this scope
 --> .brew_home/.cargo/git/checkouts/rust-ffmpeg-4e2fa0d809f646b8/0eea6d0/src/format/format/flag.rs:9:25
  |
9 |         const RAW_PICTURE   = AVFMT_RAWPICTURE;
  |                               ^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find value `AV_CODEC_ID_VIMA` in this scope
    --> .brew_home/.cargo/git/checkouts/rust-ffmpeg-4e2fa0d809f646b8/0eea6d0/src/codec/id.rs:1252:33
     |
1252 |             Id::VIMA                  => AV_CODEC_ID_VIMA,
     |                                          ^^^^^^^^^^^^^^^^ did you mean `AV_CODEC_ID_IMC`?

error[E0425]: cannot find value `AV_CODEC_CAP_HWACCEL_VDPAU` in this scope
  --> .brew_home/.cargo/git/checkouts/rust-ffmpeg-4e2fa0d809f646b8/0eea6d0/src/codec/capabilities.rs:11:31
   |
11 |         const HWACCEL_VDPAU       = AV_CODEC_CAP_HWACCEL_VDPAU;
   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find value `FF_DEBUG_MV` in this scope
  --> .brew_home/.cargo/git/checkouts/rust-ffmpeg-4e2fa0d809f646b8/0eea6d0/src/codec/debug.rs:11:23
   |
11 |         const MV          = FF_DEBUG_MV;
   |                             ^^^^^^^^^^^ did you mean `FF_DEBUG_ER`?

error[E0425]: cannot find value `FF_DEBUG_PTS` in this scope
  --> .brew_home/.cargo/git/checkouts/rust-ffmpeg-4e2fa0d809f646b8/0eea6d0/src/codec/debug.rs:15:23
   |
15 |         const PTS         = FF_DEBUG_PTS;
   |                             ^^^^^^^^^^^^ did you mean `FF_FDEBUG_TS`?

error[E0425]: cannot find value `FF_DEBUG_VIS_QP` in this scope
  --> .brew_home/.cargo/git/checkouts/rust-ffmpeg-4e2fa0d809f646b8/0eea6d0/src/codec/debug.rs:19:23
   |
19 |         const VIS_QP      = FF_DEBUG_VIS_QP;
   |                             ^^^^^^^^^^^^^^^ did you mean `FF_DEBUG_QP`?

error[E0425]: cannot find value `FF_DEBUG_VIS_MB_TYPE` in this scope
  --> .brew_home/.cargo/git/checkouts/rust-ffmpeg-4e2fa0d809f646b8/0eea6d0/src/codec/debug.rs:20:23
   |
20 |         const VIS_MB_TYPE = FF_DEBUG_VIS_MB_TYPE;
   |                             ^^^^^^^^^^^^^^^^^^^^ did you mean `FF_DEBUG_MB_TYPE`?

error[E0599]: no variant named `XVMC` found for type `util::format::pixel::Pixel` in the current scope
   --> .brew_home/.cargo/git/checkouts/rust-ffmpeg-4e2fa0d809f646b8/0eea6d0/src/util/format/pixel.rs:803:4
    |
10  | pub enum Pixel {
    | -------------- variant `XVMC` not found here
...
803 |             Pixel::XVMC   => AV_PIX_FMT_XVMC,
    |             ^^^^^^^^^^^ variant not found in `util::format::pixel::Pixel`

error[E0308]: mismatched types
  --> .brew_home/.cargo/git/checkouts/rust-ffmpeg-4e2fa0d809f646b8/0eea6d0/src/filter/mod.rs:64:22
   |
64 |             Some(Filter::wrap(ptr))
   |                               ^^^ types differ in mutability
   |
   = note: expected type `*mut sys::AVFilter`
              found type `*const sys::AVFilter`

error: aborting due to 11 previous errors

error: Could not compile `ffmpeg`.

To learn more, run the command again with --verbose.

regressed by
FFmpeg/FFmpeg@2b32031
FFmpeg/FFmpeg@693a11b
and more

How is gifski licensed?

The web page mentions gifski is open source, but I found no information on the license used in the repository.

Progress bar shows no progress when converting video directly

The progress bar seems to count the number of input files. When I just convert a singe video with gifski -o a.gif test.webm it just shows

Frame 1 / 1  #####################################################################################################

which version of rust to install gifski ???

hello ,
I am trying to install gifski on Windows with: cargo install gifski
I tested with version 1.20.0 1.24.0 1.19.0 1.5.0 1.8.0
None of them worked. I still have errors.

errors with version 1.22.0
error[E0308]: mismatched types
--> c....\cargo\registry\src\github.com-1ecc6299db9ec823\lodepng-2.1.4\src\ffi.rs:388:47

errors with version 1.20.0:
error: use of unstable library feature 'ord_max_min' (see issue #25663)
--> C:....cargo\registry\src\github.com-1ecc6299db9ec823\imgref-1.3.3\src\lib.rs:135:44
|
135 | let non_padded = &buf[0..buf.len().min(stride * self.height())];
| ^^^

Compiling memoffset v0.2.1

@kornelski

Native application

I'm still fascinated how well works gifski.

Although it's very simple to use it (just two commands), it is limited to dev people.

How difficult could create an app to use it from a GUI?

Something simple and similar to ImageOptim. Probably it could be done using electron.

Inspiration: https://sindresorhus.com/heic-converter

GifskiError to string API

It would be useful to expose a function that translates the GifskiError enum into an error message string that the application or can show to the user. Similar to e.g. curl_easy_strerror.

Error: INVALID_POINTER/Segmentation Fault

Stumbled across this while working on a reddit bot that reverses gifs.

Took the mp4 of an imgur gif https://i.imgur.com/sG7sgqZ.mp4

Created pngs using ffmpeg with the command ffmpeg -i in.mp4 frame%04d.png

Then ran gifski gifski -o temp.gif frame*.png

Different runs have had different results. Sometimes it sits there and then comes back with either Segmentation Fault or Error: INVALID_POINTER. Other times it gets about two frames into the process before giving one of the errors.

I'm using Debian 9 with ffmpeg version N-89805-gcbbb206 and gifski 0.7.1

Can't Open Gif

I have an issue with the Gifski Gif’s I can’t open them on my Android phone but when I use other encoders the Gif’s work

Self-containted release tarballs

For build tools that disallow networking access during compilation, it would be useful if tarballs with source code contained all dependent libraries.

error: Could not compile `lodepng`.

when installing I get:

$ cargo install gifski
    Updating registry `https://github.com/rust-lang/crates.io-index`
  Installing gifski v0.8.2
   Compiling rustc-demangle v0.1.7
   Compiling lazy_static v0.2.11
   Compiling either v1.4.0
   Compiling ansi_term v0.11.0
   Compiling rgb v0.8.7
   Compiling winapi v0.2.8
   Compiling vec_map v0.8.0
   Compiling strsim v0.7.0
   Compiling bitflags v1.0.1
   Compiling rayon-core v1.4.0
   Compiling imgref v1.3.3
   Compiling wild v0.1.1
   Compiling libc v0.2.39
   Compiling unicode-width v0.1.4
   Compiling nodrop v0.1.12
   Compiling resize v0.3.0
   Compiling cfg-if v0.1.2
   Compiling glob v0.2.11
   Compiling winapi-build v0.1.1
   Compiling lzw v0.10.0
   Compiling cc v1.0.6
   Compiling memoffset v0.2.1
   Compiling color_quant v1.0.0
   Compiling scopeguard v0.3.3
   Compiling lazy_static v1.0.0
   Compiling arrayvec v0.4.7
   Compiling textwrap v0.9.0
   Compiling crossbeam-utils v0.2.2
   Compiling num_cpus v1.8.0
   Compiling atty v0.2.8
   Compiling lodepng v2.1.2
   Compiling rand v0.4.2
error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/lib.rs:288:16
    |
288 |             k: self.text_keys,
    |                ^^^^^^^^^^^^^^ expected i8, found u8
    |
    = note: expected type `*mut *mut i8`
               found type `*mut *mut u8`

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/lib.rs:289:16
    |
289 |             v: self.text_strings,
    |                ^^^^^^^^^^^^^^^^^ expected i8, found u8
    |
    = note: expected type `*mut *mut i8`
               found type `*mut *mut u8`

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/lib.rs:297:16
    |
297 |             k: self.itext_keys,
    |                ^^^^^^^^^^^^^^^ expected i8, found u8
    |
    = note: expected type `*mut *mut i8`
               found type `*mut *mut u8`

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/lib.rs:298:16
    |
298 |             l: self.itext_langtags,
    |                ^^^^^^^^^^^^^^^^^^^ expected i8, found u8
    |
    = note: expected type `*mut *mut i8`
               found type `*mut *mut u8`

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/lib.rs:299:16
    |
299 |             t: self.itext_transkeys,
    |                ^^^^^^^^^^^^^^^^^^^^ expected i8, found u8
    |
    = note: expected type `*mut *mut i8`
               found type `*mut *mut u8`

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/lib.rs:300:16
    |
300 |             s: self.itext_strings,
    |                ^^^^^^^^^^^^^^^^^^ expected i8, found u8
    |
    = note: expected type `*mut *mut i8`
               found type `*mut *mut u8`

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/lib.rs:310:32
    |
310 |                 string_cleanup(&mut *self.text_keys.offset(i));
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected i8, found u8
    |
    = note: expected type `&mut *mut i8`
               found type `&mut *mut u8`

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/lib.rs:311:32
    |
311 |                 string_cleanup(&mut *self.text_strings.offset(i));
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected i8, found u8
    |
    = note: expected type `&mut *mut i8`
               found type `&mut *mut u8`

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/lib.rs:329:32
    |
329 |                 string_cleanup(&mut *self.itext_keys.offset(i));
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected i8, found u8
    |
    = note: expected type `&mut *mut i8`
               found type `&mut *mut u8`

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/lib.rs:330:32
    |
330 |                 string_cleanup(&mut *self.itext_langtags.offset(i));
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected i8, found u8
    |
    = note: expected type `&mut *mut i8`
               found type `&mut *mut u8`

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/lib.rs:331:32
    |
331 |                 string_cleanup(&mut *self.itext_transkeys.offset(i));
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected i8, found u8
    |
    = note: expected type `&mut *mut i8`
               found type `&mut *mut u8`

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/lib.rs:332:32
    |
332 |                 string_cleanup(&mut *self.itext_strings.offset(i));
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected i8, found u8
    |
    = note: expected type `&mut *mut i8`
               found type `&mut *mut u8`

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/ffi.rs:475:28
    |
475 |     let k = CStr::from_ptr(key);
    |                            ^^^ expected u8, found i8
    |
    = note: expected type `*const u8`
               found type `*const i8`

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/ffi.rs:476:28
    |
476 |     let s = CStr::from_ptr(str);
    |                            ^^^ expected u8, found i8
    |
    = note: expected type `*const u8`
               found type `*const i8`

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/ffi.rs:487:28
    |
487 |     let k = CStr::from_ptr(key);
    |                            ^^^ expected u8, found i8
    |
    = note: expected type `*const u8`
               found type `*const i8`

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/ffi.rs:488:28
    |
488 |     let l = CStr::from_ptr(langtag);
    |                            ^^^^^^^ expected u8, found i8
    |
    = note: expected type `*const u8`
               found type `*const i8`

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/ffi.rs:489:28
    |
489 |     let t = CStr::from_ptr(transkey);
    |                            ^^^^^^^^ expected u8, found i8
    |
    = note: expected type `*const u8`
               found type `*const i8`

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/ffi.rs:490:28
    |
490 |     let s = CStr::from_ptr(str);
    |                            ^^^ expected u8, found i8
    |
    = note: expected type `*const u8`
               found type `*const i8`

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/ffi.rs:843:30
    |
843 |     let tmp = CStr::from_ptr(filename);
    |                              ^^^^^^^^ expected u8, found i8
    |
    = note: expected type `*const u8`
               found type `*const i8`

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/rustimpl.rs:556:64
    |
556 |             realloc_push(&mut self.itext_keys, self.itext_num, key)?;
    |                                                                ^^^ expected u8, found i8
    |
    = note: expected type `*mut u8`
               found type `*mut i8`

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/rustimpl.rs:557:68
    |
557 |             realloc_push(&mut self.itext_langtags, self.itext_num, langtag)?;
    |                                                                    ^^^^^^^ expected u8, found i8
    |
    = note: expected type `*mut u8`
               found type `*mut i8`

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/rustimpl.rs:558:69
    |
558 |             realloc_push(&mut self.itext_transkeys, self.itext_num, transkey)?;
    |                                                                     ^^^^^^^^ expected u8, found i8
    |
    = note: expected type `*mut u8`
               found type `*mut i8`

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/rustimpl.rs:559:67
    |
559 |             realloc_push(&mut self.itext_strings, self.itext_num, str)?;
    |                                                                   ^^^ expected u8, found i8
    |
    = note: expected type `*mut u8`
               found type `*mut i8`

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/rustimpl.rs:569:62
    |
569 |             realloc_push(&mut self.text_keys, self.text_num, k)?;
    |                                                              ^ expected u8, found i8
    |
    = note: expected type `*mut u8`
               found type `*mut i8`

error[E0308]: mismatched types
   --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/rustimpl.rs:570:65
    |
570 |             realloc_push(&mut self.text_strings, self.text_num, v)?;
    |                                                                 ^ expected u8, found i8
    |
    = note: expected type `*mut u8`
               found type `*mut i8`

   Compiling time v0.1.39
error[E0308]: mismatched types
  --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/iter.rs:19:77
   |
19 |                 debug_assert!(!(*self.k).is_null()); let k = CStr::from_ptr(*self.k);
   |                                                                             ^^^^^^^ expected u8, found i8
   |
   = note: expected type `*const u8`
              found type `*mut i8`

error[E0308]: mismatched types
  --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/iter.rs:20:77
   |
20 |                 debug_assert!(!(*self.v).is_null()); let v = CStr::from_ptr(*self.v);
   |                                                                             ^^^^^^^ expected u8, found i8
   |
   = note: expected type `*const u8`
              found type `*mut i8`

error[E0308]: mismatched types
  --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/iter.rs:47:77
   |
47 |                 debug_assert!(!(*self.k).is_null()); let k = CStr::from_ptr(*self.k);
   |                                                                             ^^^^^^^ expected u8, found i8
   |
   = note: expected type `*const u8`
              found type `*mut i8`

error[E0308]: mismatched types
  --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/iter.rs:48:77
   |
48 |                 debug_assert!(!(*self.l).is_null()); let l = CStr::from_ptr(*self.l);
   |                                                                             ^^^^^^^ expected u8, found i8
   |
   = note: expected type `*const u8`
              found type `*mut i8`

error[E0308]: mismatched types
  --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/iter.rs:49:77
   |
49 |                 debug_assert!(!(*self.t).is_null()); let t = CStr::from_ptr(*self.t);
   |                                                                             ^^^^^^^ expected u8, found i8
   |
   = note: expected type `*const u8`
              found type `*mut i8`

error[E0308]: mismatched types
  --> /home/pi/.cargo/registry/src/github.com-1ecc6299db9ec823/lodepng-2.1.2/src/iter.rs:50:77
   |
50 |                 debug_assert!(!(*self.s).is_null()); let s = CStr::from_ptr(*self.s);
   |                                                                             ^^^^^^^ expected u8, found i8
   |
   = note: expected type `*const u8`
              found type `*mut i8`

error: aborting due to 31 previous errors

error: Could not compile `lodepng`.
warning: build failed, waiting for other jobs to finish...
error: failed to compile `gifski v0.8.2`, intermediate artifacts can be found at `/tmp/cargo-install.isVgnDvHhWuD`

Caused by:
  build failed

this is on a raspberry pi 3:

$ lsb_release -a
No LSB modules are available.
Distributor ID:	Raspbian
Description:	Raspbian GNU/Linux 8.0 (jessie)
Release:	8.0
Codename:	jessie

additional details:

$ cargo --version
cargo 0.23.0 (61fa02415 2017-11-22)
$ rustc --version
rustc 1.22.1 (05e2e1c41 2017-11-22)

Build failure on Windows:

The lodepng dependency problem is fixed, but now it fails like below. Is this a problem with my gcc?

   Compiling wild v0.1.1
   Compiling gif v0.9.2
   Compiling kernel32-sys v0.2.2
   Compiling imagequant-sys v2.11.9
   Compiling crossbeam-utils v0.2.2
   Compiling num_cpus v1.8.0
   Compiling lodepng v2.1.5
   Compiling gif-dispose v2.1.0
   Compiling crossbeam-epoch v0.3.1
   Compiling crossbeam-deque v0.2.0
error: linking with `gcc` failed: exit code: 1
  |
  = note: "gcc" "-Wl,--enable-long-section-names" "-fno-use-linker-plugin" "-Wl,--nxcompat" "-nostdlib" "-Wl,--large-address-aware" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\i686-pc-windows-gnu\\lib\\dllcrt2.o" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\i686-pc-windows-gnu\\lib\\rsbegin.o" "-L" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\i686-pc-windows-gnu\\lib" "C:\\projects\\gifski\\GIFSKI~1.RCH\\00_PKG~1\\gifski\\src-i386\\myrustlib\\target\\i686-pc-windows-gnu\\release\\deps\\imagequant_sys-f6a62ba14f74e711.imagequant_sys0-f5c8c61e9753212fc2f5e5c2991a4af6.rs.rcgu.o" "C:\\projects\\gifski\\GIFSKI~1.RCH\\00_PKG~1\\gifski\\src-i386\\myrustlib\\target\\i686-pc-windows-gnu\\release\\deps\\imagequant_sys-f6a62ba14f74e711.imagequant_sys1-f5c8c61e9753212fc2f5e5c2991a4af6.rs.rcgu.o" "C:\\projects\\gifski\\GIFSKI~1.RCH\\00_PKG~1\\gifski\\src-i386\\myrustlib\\target\\i686-pc-windows-gnu\\release\\deps\\imagequant_sys-f6a62ba14f74e711.imagequant_sys2-f5c8c61e9753212fc2f5e5c2991a4af6.rs.rcgu.o" "-o" "C:\\projects\\gifski\\GIFSKI~1.RCH\\00_PKG~1\\gifski\\src-i386\\myrustlib\\target\\i686-pc-windows-gnu\\release\\deps\\imagequant_sys-f6a62ba14f74e711.dll" "-Wl,--version-script=C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\rustc.evs7Io2gLfdR\\list" "C:\\projects\\gifski\\GIFSKI~1.RCH\\00_PKG~1\\gifski\\src-i386\\myrustlib\\target\\i686-pc-windows-gnu\\release\\deps\\imagequant_sys-f6a62ba14f74e711.crate.allocator.rcgu.o" "-Wl,--gc-sections" "-nodefaultlibs" "-L" "C:\\projects\\gifski\\GIFSKI~1.RCH\\00_PKG~1\\gifski\\src-i386\\myrustlib\\target\\i686-pc-windows-gnu\\release\\deps" "-L" "C:\\projects\\gifski\\GIFSKI~1.RCH\\00_PKG~1\\gifski\\src-i386\\myrustlib\\target\\release\\deps" "-L" "C:\\projects\\gifski\\GIFSKI~1.RCH\\00_PKG~1\\gifski\\src-i386\\myrustlib\\target\\i686-pc-windows-gnu\\release\\build\\imagequant-sys-96ebfd2eb1e88e00\\out" "-L" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\i686-pc-windows-gnu\\lib" "-Wl,-Bstatic" "-Wl,--whole-archive" "-l" "imagequant" "-Wl,--no-whole-archive" "C:\\projects\\gifski\\gifski.Rcheck\\00_pkg_src\\gifski\\src-i386\\myrustlib\\target\\i686-pc-windows-gnu\\release\\deps\\librgb-effc7185392cff7d.rlib" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\i686-pc-windows-gnu\\lib\\libstd-7d1b8f671c6600f1.rlib" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\i686-pc-windows-gnu\\lib\\libpanic_unwind-366f3877c2c9fb8a.rlib" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\i686-pc-windows-gnu\\lib\\libunwind-f979bb52af5245af.rlib" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\i686-pc-windows-gnu\\lib\\liblibc-f8976d50c9357b07.rlib" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\i686-pc-windows-gnu\\lib\\liballoc_system-3800d261ecc181c1.rlib" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\i686-pc-windows-gnu\\lib\\liballoc-bfabd4c61c613469.rlib" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\i686-pc-windows-gnu\\lib\\libstd_unicode-cf317c34da92a23b.rlib" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\i686-pc-windows-gnu\\lib\\libcore-fab41fba8f33ac45.rlib" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\i686-pc-windows-gnu\\lib\\libcompiler_builtins-e0875e0e27f2835e.rlib" "-Wl,-Bdynamic" "-l" "advapi32" "-l" "ws2_32" "-l" "userenv" "-l" "shell32" "-Wl,-Bstatic" "-l" "gcc_eh" "-l" "pthread" "-shared" "-Wl,-Bdynamic" "-lmingwex" "-lmingw32" "-lgcc" "-lmsvcrt" "-lmsvcrt" "-luser32" "-lkernel32" "C:\\Users\\appveyor\\.rustup\\toolchains\\stable-x86_64-pc-windows-gnu\\lib\\rustlib\\i686-pc-windows-gnu\\lib\\rsend.o"
  = note: ld: unrecognized option '--large-address-aware'
          ld: use the --help option for usage information
          
error: aborting due to previous error
The following warnings were emitted during compilation:
warning: nearest.c: In function 'nearest_init':
warning: nearest.c:136:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes]
warning:  }
warning:  ^
warning: nearest.c: In function 'nearest_search':
warning: nearest.c:190:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes]
warning:  }
warning:  ^
warning: nearest.c: In function 'nearest_free':
warning: nearest.c:195:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes]
warning:  }
warning:  ^
warning: kmeans.c: In function 'kmeans_init':
warning: kmeans.c:26:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes]
warning:  }
warning:  ^
warning: kmeans.c: In function 'kmeans_update_color':
warning: kmeans.c:36:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes]
warning:  }
warning:  ^
warning: kmeans.c: In function 'kmeans_finalize':
warning: kmeans.c:64:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes]
warning:  }
warning:  ^
warning: kmeans.c: In function 'kmeans_do_iteration':
warning: kmeans.c:93:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes]
warning:  }
warning:  ^
warning: mediancut.c: In function 'mediancut':
warning: mediancut.c:408:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes]
warning:  }
warning:  ^
warning: mempool.c: In function 'mempool_create':
warning: mempool.c:50:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes]
warning:  }
warning:  ^
warning: mempool.c: In function 'mempool_alloc':
warning: mempool.c:61:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes]
warning:  }
warning:  ^
warning: mempool.c: In function 'mempool_destroy':
warning: mempool.c:70:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes]
warning:  }
warning:  ^
warning: pam.c: In function 'pam_computeacolorhash':
warning: pam.c:66:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes]
warning:  }
warning:  ^
warning: pam.c: In function 'pam_add_to_hash':
warning: pam.c:157:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes]
warning:  }
warning:  ^
warning: pam.c: In function 'pam_allocacolorhash':
warning: pam.c:177:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes]
warning:  }
warning:  ^
warning: pam.c: In function 'pam_acolorhashtoacolorhist':
warning: pam.c:233:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes]
warning:  }
warning:  ^
warning: pam.c: In function 'pam_freeacolorhash':
warning: pam.c:241:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes]
warning:  }
warning:  ^
warning: pam.c: In function 'pam_freeacolorhist':
warning: pam.c:247:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes]
warning:  }
warning:  ^
warning: pam.c: In function 'pam_colormap':
warning: pam.c:264:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes]
warning:  }
warning:  ^
warning: pam.c: In function 'pam_duplicate_colormap':
warning: pam.c:273:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes]
warning:  }
warning:  ^
warning: pam.c: In function 'pam_freecolormap':
warning: pam.c:278:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes]
warning:  }
warning:  ^
warning: pam.c: In function 'to_f_set_gamma':
warning: pam.c:285:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes]
warning:  }
warning:  ^
warning: blur.c: In function 'liq_max3':
warning: blur.c:91:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes]
warning:  }
warning:  ^
warning: blur.c: In function 'liq_min3':
warning: blur.c:118:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes]
warning:  }
warning:  ^
warning: blur.c: In function 'liq_blur':
warning: blur.c:132:1: warning: visibility attribute not supported in this configuration; ignored [-Wattributes]
warning:  }
warning:  ^
error: Could not compile `imagequant-sys`.
warning: build failed, waiting for other jobs to finish...
error: build failed

Segmentation fault: 11 when using --fast

  • Running macOS 10.12.6 (16G1212)
  • Running late 2013 Retina MacBook Pro (with GT 750M; tried forcing it on with no change)
  • Running HOMEBREW_VERSION: 1.5.4
  • Installed via brew install gifski

gifski test.mp4 --fps 60 --fast -W 540 -o b.gif results in

Frame 1 / 260  _............................................................ 7m
Segmentation fault: 11

However, gifski test.mp4 --fps 60 -W 540 -o b.gif works fine.

Variable framerate

Is it possible to create a variable framerate gif with this tool?

Something like the -concat option available with FFmpeg.

Feature Request: Manually Set Frame Delay

Hi,

I'm really impressed with the results of gifski!

Photoshop offers a nice feature for animated gifs: The ability to set the length of time a frame is displayed on a per-frame basis.

It looks like this:

screen-shot-2018-03-09-at-12 31 36-pm

It would be great to have the ability to do this in gifski.

Maybe it could be based on the filename like:

frame0001-delay:200.png
frame0002-delay:1000.png

Where 200 and 1000 are the length of time in milliseconds the frame should be displayed.

Alternatively, it could be a flag with a list of delays like:

gifski -o anim.gif frame*.png --delay 200,1000

Thanks for making gifski!

Ben

Option for faster encoding

Currently it's slow, because:

  • every frame depends on previous frame, so encoding is serial. The input could be split into chunks and encoded in parallel (although that would increase memory usage a lot, since output writing needs to be sequential still)

  • pngquant is used with high quality setting. Even with fast/lower quality setting it should still be better than most gif encoders.

FTBFS: gif version mismatch

I just now tried to install on stable-x86_64-pc-windows-msvc with rustc 1.26.2, and I get the following error:

    Updating registry `https://github.com/rust-lang/crates.io-index`
  Installing gifski v0.8.3
   Compiling nodrop v0.1.12
   Compiling cfg-if v0.1.3
   Compiling winapi v0.3.5
   Compiling memoffset v0.2.1
   Compiling lazy_static v1.0.1
   Compiling cc v1.0.17
   Compiling winapi-build v0.1.1
   Compiling scopeguard v0.3.3
   Compiling rayon-core v1.4.0
   Compiling libc v0.2.42
   Compiling color_quant v1.0.0
   Compiling rgb v0.8.9
   Compiling unicode-width v0.1.5
   Compiling rustc-demangle v0.1.8
   Compiling lzw v0.10.0
   Compiling winapi v0.2.8
   Compiling glob v0.2.11
   Compiling vec_map v0.8.1
   Compiling strsim v0.7.0
   Compiling imgref v1.3.4
   Compiling either v1.5.0
   Compiling bitflags v1.0.3
   Compiling resize v0.3.0
   Compiling crossbeam-utils v0.2.2
   Compiling arrayvec v0.4.7
   Compiling num_cpus v1.8.0
   Compiling textwrap v0.9.0
   Compiling kernel32-sys v0.2.2
   Compiling lodepng v2.1.5
   Compiling gif v0.10.0
   Compiling gif v0.9.2
   Compiling wild v0.1.1
   Compiling crossbeam-epoch v0.3.1
   Compiling imagequant-sys v2.12.0
   Compiling gif-dispose v2.1.1
   Compiling crossbeam-deque v0.2.0
   Compiling imagequant v2.11.9
   Compiling rand v0.4.2
   Compiling time v0.1.40
   Compiling backtrace v0.3.8
   Compiling atty v0.2.10
   Compiling clap v2.31.2
   Compiling error-chain v0.11.0
   Compiling rayon v0.9.0
   Compiling pbr v1.0.1
   Compiling gifski v0.8.3
error[E0308]: mismatched types
   --> src/lib.rs:358:43
    |
358 |             screen.blit(Some(&frame.pal), dispose, 0, 0, frame.image.as_ref(), transparent_index)?;
    |                                           ^^^^^^^ expected enum `gif::common::DisposalMethod`, found enum `gif::DisposalMethod`
    |
    = note: expected type `gif::common::DisposalMethod`
               found type `gif::DisposalMethod`
note: Perhaps two different versions of crate `gif` are being used?
   --> src/lib.rs:358:43
    |
358 |             screen.blit(Some(&frame.pal), dispose, 0, 0, frame.image.as_ref(), transparent_index)?;
    |                                           ^^^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
error: failed to compile `gifski v0.8.3`, intermediate artifacts can be found at `C:\Users\Dan\AppData\Local\Temp\cargo-installAon2GQ`

Caused by:
  Could not compile `gifski`.

To learn more, run the command again with --verbose.

Note in particular this part, which seems wrong:

   Compiling gif v0.10.0
   Compiling gif v0.9.2

Does your gif dependency need to be updated to match a transitive dependency?

Frame background not disposing

Here's the original GIF:

orig

Here's the one merged with gifski:

test

The command:

gifski -o test.gif --fps 10 output/frame*.png

The frames are extracted by imagemagick with the following command:

convert orig.gif -coalesce output/frame%03d.png

"spotch" artifacts , ?dithering or ?quant artifacts ?

First, thanks for the tool - I just heard about it recently

Some artifacts generated around deadpool's ear. I circled it in this single frame preview. No artifacts of this kind with other methods. 3/56 frames affected
https://s9.postimg.org/tuue0bvtb/splotch.png

Not sure if they are quantization artifacts , dithering artifacts or something else. I didn't have time to do other testing yet

Source images and final gif . (Source was section from Deadpool 1 YT trailer, cropped, trimmed in avisynth to png sequence)
~21Mb zip archive
http://www.mediafire.com/file/zdeykyjnq07lrcg/giftest.zip

cmd used (0.8.2)
[code]
gifski.exe --fps 15 -o gifski.gif giftest*.png
[/code]

Compiling gifski 0.3.0 from source fails

Compiling gifski 0.3.0 from source fails with:

    Updating registry `https://github.com/rust-lang/crates.io-index`
 Downloading pbr v1.0.0
 Downloading lodepng v2.0.4
 Downloading gif-dispose v2.0.1
 Downloading time v0.1.38
 Downloading rgb v0.8.1
 Downloading imagequant-sys v2.11.1
   Compiling scopeguard v0.3.3
   Compiling winapi v0.2.8
   Compiling rgb v0.7.2
   Compiling imgref v1.2.2
   Compiling bitflags v0.9.1
   Compiling cc v1.0.3
   Compiling vec_map v0.8.0
   Compiling rgb v0.8.1
   Compiling ansi_term v0.9.0
   Compiling winapi-build v0.1.1
   Compiling futures v0.1.17
   Compiling libc v0.2.33
   Compiling lazy_static v0.2.9
   Compiling cfg-if v0.1.2
   Compiling unicode-width v0.1.4
   Compiling either v1.3.0
   Compiling strsim v0.6.0
   Compiling lzw v0.10.0
   Compiling rayon-core v1.2.1
   Compiling color_quant v1.0.0
   Compiling rustc-demangle v0.1.5
   Compiling kernel32-sys v0.2.2
   Compiling textwrap v0.9.0
   Compiling coco v0.1.1
   Compiling atty v0.2.3
   Compiling num_cpus v1.7.0
   Compiling time v0.1.38
   Compiling lodepng v2.0.4
   Compiling rand v0.3.17
   Compiling imagequant-sys v2.11.1
   Compiling backtrace-sys v0.1.16
   Compiling gif v0.9.2
   Compiling clap v2.27.1
   Compiling threadpool v1.7.1
   Compiling gif-dispose v2.0.1
   Compiling pbr v1.0.0
   Compiling rayon v0.8.2
note: link against the following native artifacts when linking against this static library

note: the order and any duplication can be significant on some platforms, and so may need to be preserved

note: library: dl

note: library: rt

note: library: pthread

note: library: gcc_s

note: library: c

note: library: m

note: library: rt

note: library: pthread

note: library: util

   Compiling imagequant v2.11.4
   Compiling backtrace v0.3.3
   Compiling error-chain v0.11.0
   Compiling gifski v0.3.0 (file:///home/phw/devel/aur4/gifski/src/gifski-0.3.0)
error[E0308]: mismatched types
  --> src/lib.rs:77:29
   |
77 |             Ok((ImgVec::new(image.buffer, image.width, image.height), delay))
   |                             ^^^^^^^^^^^^ expected struct `rgb::RGBA`, found a different struct `rgb::RGBA`
   |
   = note: expected type `std::vec::Vec<rgb::RGBA<u8>>` (struct `rgb::RGBA`)
              found type `std::vec::Vec<rgb::RGBA<u8>>` (struct `rgb::RGBA`)
note: Perhaps two different versions of crate `rgb` are being used?
  --> src/lib.rs:77:29
   |
77 |             Ok((ImgVec::new(image.buffer, image.width, image.height), delay))
   |                             ^^^^^^^^^^^^
   = help: here are some functions which might fulfill your needs:
           - .to_vec()

error[E0308]: mismatched types
   --> src/lib.rs:100:29
    |
100 |         img.add_fixed_color(RGBA8::new(0,0,0,0));
    |                             ^^^^^^^^^^^^^^^^^^^ expected struct `rgb::RGBA`, found a different struct `rgb::RGBA`
    |
    = note: expected type `rgb::RGBA<u8>` (struct `rgb::RGBA`)
               found type `rgb::RGBA<u8>` (struct `rgb::RGBA`)
note: Perhaps two different versions of crate `rgb` are being used?
   --> src/lib.rs:100:29
    |
100 |         img.add_fixed_color(RGBA8::new(0,0,0,0));
    |                             ^^^^^^^^^^^^^^^^^^^

error[E0308]: mismatched types
   --> src/lib.rs:107:59
    |
107 |         Ok((Img::new(pal_img, img.width(), img.height()), pal))
    |                                                           ^^^ expected struct `rgb::RGBA`, found a different struct `rgb::RGBA`
    |
    = note: expected type `std::vec::Vec<rgb::RGBA<u8>>` (struct `rgb::RGBA`)
               found type `std::vec::Vec<rgb::RGBA<u8>>` (struct `rgb::RGBA`)
note: Perhaps two different versions of crate `rgb` are being used?
   --> src/lib.rs:107:59
    |
107 |         Ok((Img::new(pal_img, img.width(), img.height()), pal))
    |                                                           ^^^
    = help: here are some functions which might fulfill your needs:
            - .to_vec()

error[E0308]: mismatched types
   --> src/lib.rs:177:87
    |
177 |                 screen = Some(gif_dispose::Screen::new(image.width(), image.height(), RGBA8::new(0,0,0,0), None));
    |                                                                                       ^^^^^^^^^^^^^^^^^^^ expected struct `rgb::RGBA`, found a different struct `rgb::RGBA`
    |
    = note: expected type `rgb::RGBA<u8>` (struct `rgb::RGBA`)
               found type `rgb::RGBA<u8>` (struct `rgb::RGBA`)
note: Perhaps two different versions of crate `rgb` are being used?
   --> src/lib.rs:177:87
    |
177 |                 screen = Some(gif_dispose::Screen::new(image.width(), image.height(), RGBA8::new(0,0,0,0), None));
    |                                                                                       ^^^^^^^^^^^^^^^^^^^

error[E0308]: mismatched types
   --> src/lib.rs:189:42
    |
189 |                     let diff = colordiff(a,b);
    |                                          ^ expected struct `rgb::RGBA`, found a different struct `rgb::RGBA`
    |
    = note: expected type `rgb::RGBA<u8>` (struct `rgb::RGBA`)
               found type `rgb::RGBA<u8>` (struct `rgb::RGBA`)
note: Perhaps two different versions of crate `rgb` are being used?
   --> src/lib.rs:189:42
    |
189 |                     let diff = colordiff(a,b);
    |                                          ^

error[E0308]: mismatched types
   --> src/lib.rs:204:65
    |
204 |                 Self::quantize(image.as_ref(), &importance_map, bg, fast)?
    |                                                                 ^^ expected struct `rgb::RGBA`, found a different struct `rgb::RGBA`
    |
    = note: expected type `std::option::Option<imgref::Img<&[rgb::RGBA<u8>]>>` (struct `rgb::RGBA`)
               found type `std::option::Option<imgref::Img<&[rgb::RGBA<u8>]>>` (struct `rgb::RGBA`)
note: Perhaps two different versions of crate `rgb` are being used?
   --> src/lib.rs:204:65
    |
204 |                 Self::quantize(image.as_ref(), &importance_map, bg, fast)?
    |                                                                 ^^
    = help: here are some functions which might fulfill your needs:
            - .take()
            - .unwrap()

error[E0308]: mismatched types
   --> src/lib.rs:224:34
    |
224 |                 screen.blit(Some(&image8_pal), gif::DisposalMethod::Keep, 0, 0, image8.as_ref(), transparent_index)
    |                                  ^^^^^^^^^^^ expected slice, found struct `std::vec::Vec`
    |
    = note: expected type `&[rgb::RGBA<u8>]`
               found type `&std::vec::Vec<rgb::RGBA<u8>>`
    = help: here are some functions which might fulfill your needs:
            - .as_slice()

error: aborting due to 7 previous errors

Running arch linux with rust 1.21.0 and cargo 0.22.0

Installation on ubuntu 17.10 fails

Tried to run cargo install gifski but it fails:

Compiling gifski v0.8.3
error[E0308]: mismatched types
--> src/lib.rs:358:43
|
358 | screen.blit(Some(&frame.pal), dispose, 0, 0, frame.image.as_ref(), transparent_index)?;
| ^^^^^^^ expected enum gif::common::DisposalMethod, found enum gif::DisposalMethod
|
= note: expected type gif::common::DisposalMethod
found type gif::DisposalMethod
note: Perhaps two different versions of crate gif are being used?
--> src/lib.rs:358:43
|
358 | screen.blit(Some(&frame.pal), dispose, 0, 0, frame.image.as_ref(), transparent_index)?;
| ^^^^^^^

error: aborting due to previous error

For more information about this error, try rustc --explain E0308.
error: failed to compile gifski v0.8.3, intermediate artifacts can be found at /tmp/cargo-installOeuOri

Caused by:
Could not compile gifski.

To learn more, run the command again with --verbose.

Building works fine for me.

Build fails on Arch Linux due to missing static openmp libraries

I am trying to build gifski on Arch Linux with:

cargo build --release --features=video,openmp

It fails with:

[...]
   Compiling crossbeam-deque v0.2.0
   Compiling gif-dispose v2.1.0
   Compiling pbr v1.0.0
   Compiling regex v0.2.6
error: could not find native static library `gomp`, perhaps an -L flag is missing?

The following warnings were emitted during compilation:

warning: Unable to find library libgomp.a for cc in ["/usr/lib/gcc/x86_64-pc-linux-gnu/7.3.1/", "/usr/lib/gcc/x86_64-pc-linux-gnu/7.3.1/../../../../x86_64-pc-linux-gnu/lib/x86_64-pc-linux-gnu/7.3.1/", "/usr/lib/gcc/x86_64-pc-linux-gnu/7.3.1/../../../../x86_64-pc-linux-gnu/lib/../lib/", "/usr/lib/gcc/x86_64-pc-linux-gnu/7.3.1/../../../x86_64-pc-linux-gnu/7.3.1/", "/usr/lib/gcc/x86_64-pc-linux-gnu/7.3.1/../../../../lib/", "/lib/x86_64-pc-linux-gnu/7.3.1/", "/lib/../lib/", "/usr/lib/x86_64-pc-linux-gnu/7.3.1/", "/usr/lib/../lib/", "/usr/lib/gcc/x86_64-pc-linux-gnu/7.3.1/../../../../x86_64-pc-linux-gnu/lib/", "/usr/lib/gcc/x86_64-pc-linux-gnu/7.3.1/../../../", "/lib/", "/usr/lib/"]

error: Could not compile `openmp-sys`.
warning: build failed, waiting for other jobs to finish...
error: build failed

The build worked fine in 0.8.0. I think gifski switched to a static openmp build with this release, but Arch does not provide static librarries and prefers dynamic linking. Could you provide an option to use the non-static version?

--fast parameter makes Gifski crash under windows

Hello,

--fast parameter seems to crash Gifski 0.7.3 ( release from releases page on git ) under windows, ( tested with win7 x64 )

Checked the options with -h, the --fast switch is indicated :
2018-01-24_132405_cr
( btw: seems like there is a little typo for the --quiet description, "Don not" instead of "Do not" i suppose )

With command :
gifski -o anim.gif --fast "H:\Gif_Frames\frame"*".png"
or when frames are in the same folder :
gifski -o anim.gif --fast frame*.png
or with FPS added like here
gifski -o anim.gif --fps 30 --fast "H:\Gif_Frames\frame"*".png"

The first frame of the gif is created then I get a crash and a memory related error :
2018-01-24_133044
Translation: Instruction @ 0x3fa5a262 use memory address 0x00000000. The memory can't be in "written" state.

No problems at all to create gif's when not using --fast option and for example a command like :
gifski -o anim.gif --fps 30 --quality 100 "H:\Gif_Frames\frame"*".png"
This works fine.

Also i don't know where to ask so forgive me if it's not the right place or send me to the appropriate place to ask about this :

I use the official released binaries, i can't compil stuff myself and the few times i tried to compile things it ended in headaches and failures... but i'm interested in the version able to use directly videos for input via ffmpeg and i'm wondering about a few things :

  • Does it supports all input formats ffmpeg support ( including avisynth .avs extension files ? )
  • Is there a difference in the gif output size, i mean if we take a video and input it directly vs a video that we first convert to png's is there any differences at all ?
  • related to above : is ffmpeg "piping" directly the video to gifski or decomposing the input video into png's frames internally before feeding gifski.

Not sure if you or someone else have tested to see if there is a difference of size ( and quality maybe ? ) of the output gif using the 2 methods.

Like i said i can't really compile stuff, but before spending again half a week trying to get gifski compiled to work with videos ( and probably failing miserably at it in the end ) i would like to know if when using ffmpeg there is a real difference and how frames are sent to gifski, would particularly be interested in feeding it directly with .avs files since ffmpeg supports it.

Thank you very much.

--fps doesn't work on videos

If I understand right, I think --fps just tells gifski the framerate to use when importing PNGs. It seems to have no effect on video. So if I have a 60fps video (which doesn't seem possible to play in any browser I've tested), I can't process video directly with gifski. There's also no option to downsample or ignore frames, so it seems like only option is to do the two-step (video→PNG→GIF) process, pass -r to ffmpeg to lower the framerate, and then pass that same framerate to gifski with --fps.

Would it be possible to support --fps on video so you can use the one-step process with high-framerate videos and downsample in gifski?

Windows: drag-and-droppable batch files like for pngquant?

So recently I had the luck that I could help out a scientist friend who had gigantic, mostly-empty PNGs of his data with only a handful of colours, by using pngquant to vastly reduce the PNG size without any visible loss.

To my very happy surprise, it came with a drag-and-drop batch file for automatically reducing a large stack of images, and it's pretty simple:

@echo off

set path=%~d0%~p0

:start

"%path%pngquant.exe" --force --verbose --quality=45-85 %1
"%path%pngquant.exe" --force --verbose --ordered --speed=1 --quality=50-90 %1

shift
if NOT x%1==x goto start

I was wondering: could we add the same for the Windows build of gifski? Or maybe even a version that includes ffmpeg to make converting a bunch of videos as simple as dragging/dropping it on the batch file?

Build from source on mac with all features.

Hello,

Here is how I built gifski from source:

# clone the repo
git clone https://github.com/ImageOptim/gifski

On mac gcc is a symlink to Clang, but the old apple version doesn't have built-in support for OpenMP see here so:

brew install gcc
export CC="/usr/local/bin/gcc-7"
cargo update
cargo build --release --features=openmp

But is fails when adding ffmpeg support:

cargo build --release --features=video,openmp --verbose

The output (shortened to essential):

It rightly links against brew libs (ffmpeg installed from HEAD):

rustc --crate-name ffmpeg --crate-type lib-L native=/usr/local/Cellar/ffmpeg/HEAD-7414d0b/lib

The errors:

pixel.rs : 696 Pixel::VDA_VLD => AV_PIX_FMT_VDA_VLD,
| ^^^^^^^^^^^^^^^^^^ did you mean AV_PIX_FMT_VAAPI_VLD?
740 Pixel::VDA => AV_PIX_FMT_VDA,
| ^^^^^^^^^^^^^^ did you mean AV_PIX_FMT_CUDA?
803 Pixel::XVMC => AV_PIX_FMT_XVMC,
| ^^^^^^^^^^^ variant not found in util::format::pixel::Pixel

Website IPv6 support

The website is inaccessible over IPv6.

Seems like this is a matter of adding [2a01:488:66:1000:53a9:244:0:1] (the IPv6 address for ImageOptim's website) to DNS, as fetching gif.ski from it works:

> curl https://[2a01:488:66:1000:53a9:244:0:1] -H "Host:gif.ski" -k
<!DOCTYPE html>
<meta charset=utf8>
<title>gifski ÔÇö highest-quality GIF converter</title>
[...]

C-API returning error code 15

I try to use the gifski C-API but not able to get it work

Error 15 is reported when I try to call to functions gifski_add_frame_rgba, gifski_write

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.