gifski
gifski copied to clipboard
Output file drops every 8 frames
I'm trying to create a perfect gradient GIF, where each frame is a single solid color. I have all of the PNGs (65,536 in total) and double-checked the color values for each, where it increases by 1 each frame; so rgb(0,0,0), rgb(1,0,0), rgb(2,0,0) etc.
When running gifski, it says it's collated them all, but when I inspect the GIF - which should have 65,536 frames - it only has 8,446 frames, or ~7.7 frames for every one it should have. I can see this when I inspect the individual frames too - when I inspect the GIF, each frame color steps up by 8 (rgb(0,0,0), rgb(8,0,0), rgb(16,0,0) etc.) instead of 1.
I'm not sure if this is related to https://github.com/ImageOptim/gifski/pull/154 - disable the dropping of 'duplicate' frames (I can see how they'd appear virtually identical to an optimizer). I can see the argument --no-duplicate-skip / --no-skip-duplicates in the PR, but it doesn't look like it made it to build 1.4.0 (I tried both and it threw an error both times).
Is there a way to run it and get it to collate all frames without dropping any?
In order to compress screen casts efficiently gifski ignores small differences between frames. There's a minimum color difference required between pixels of consecutive frames. If frames are approximately the same, they're forced to be exactly the same, and then removed as redundant.
So I downloaded rustup & the source for v1.4.3, but I've never touched Rust before (and also I'm terrible at math - I'm great with PHP & JS though 🤷🏻♀️). I skipped through lib.rs, but I can't identify the place where this happens.
If I wanted to change it so that it wouldn't dispose of any frame, regardless of the color difference, where would I do it?
The frame diffing is quite fundamentally integrated throughout the whole pipeline:
Perhaps you can break it by setting threshold to 0:
https://github.com/ImageOptim/gifski/blob/main/src/denoise.rs#L87
Ah, that almost worked - setting it to 0 results in a divide by zero error when running it. Setting it to 1 results in a color difference of 2 (rgba(0, 0, 2), rgba(0, 0, 4), rgba(0, 0, 6) etc.). I tried changing it to a non-integer, but that throws errors during compiling as everything else using it expects an int.
I can generate the images as anything - PNGs, JPGs or GIFs. I guess at this point I just need something that will stitch all the separate images together without skipping any. I tried gifsicle, and although it doesn't skip frames, it looks like it struggles with the colors - it always throws an error about there being more than 256 colors, the results - starting from black and incrementing by 1 in the blue channel - end up like rgba(4, 2, 4), rgba(4, 2, 4), rgba(4, 2, 4) for 8 frames, then up by 6-8 frames for the blue value. I'm not sure if it's trying to use a global color table for the whole file, rather than for each frame?
The frame diffing is quite fundamentally integrated throughout the whole pipeline:
Perhaps you can break it by setting threshold to 0:
https://github.com/ImageOptim/gifski/blob/main/src/denoise.rs#L87 I encountered the same problem. Gifski is a great library, and I used the Gifski C API to encode desktop frames as GIFs. It runs very well, and the only issue is that we need to support encoding desktop frames at the specified frame rate even when there is no change, instead of discarding duplicate frames. I tried setting the threshold to 0, but it crashed directly. Can you guide me on how to modify the code? Sincerely thank you
What does it even mean to have every frame? Is it about having the pixels, or just frame delays the same? Would inserting 1x1 transparent pixel frames when nothing changes be sufficient?
As for editing gifski source, you'd want to remove denoise entirely. Just skip it and feed every frame to the rest of the pipeline. There are checks for identical frames later in the diff step. You'd need to remove that too.
And then there's trimming of frames to minimum area. I've recently updated that to keep 1x1 frame instead of skipping again.
Frames in GIF are costly, even empty transparent space compresses poorly in GIF! So as you can see, gifski tries really hard to skip them whenever possible.
What does it even mean to have every frame? Is it about having the pixels, or just frame delays the same? Would inserting 1x1 transparent pixel frames when nothing changes be sufficient?
As for editing gifski source, you'd want to remove denoise entirely. Just skip it and feed every frame to the rest of the pipeline. There are checks for identical frames later in the diff step. You'd need to remove that too.
And then there's trimming of frames to minimum area. I've recently updated that to keep 1x1 frame instead of skipping again.
Frames in GIF are costly, even empty transparent space compresses poorly in GIF! So as you can see, gifski tries really hard to skip them whenever possible.
Thank you very much for your reply. What I mean is, for example, if I call gifski-add_frame_rgba_stride n times and I want n frames in the gif file, what should I do for this requirement
But why? How do you even tell the difference? Do you expect the frames to also contain all the pixels you've specified? If I reduce these redundant frames to be just 1x1 transparent pixel, does that count as including the frames?
But why? How do you even tell the difference? Do you expect the frames to also contain all the pixels you've specified? If I reduce these redundant frames to be just 1x1 transparent pixel, does that count as including the frames?
For example, if I call gifski_add_frame_rgba_stride 10 times (regardless of whether the buffer content is the same or the difference is significant), I want the gif decoding tool to be able to decode 10 frames (for example, currently image previews on Mac can only decode less than 10 frames). Can you achieve the 1x1 transparent pixel you mentioned?
But why? How do you even tell the difference? Do you expect the frames to also contain all the pixels you've specified? If I reduce these redundant frames to be just 1x1 transparent pixel, does that count as including the frames?
Thank you again for your reply. Perhaps my English is not very good. I am working on a software that saves desktop recordings as GIFs. Each frame of the desktop content may be the same, but I am not concerned. I only hope that I can call Gifski-add_frame_rgba_stride a few times and the GIF decoding tool can decode several frames of images. What do I need to do? Thank you for your reply
This is my C++pseudocode. I want to get a GIF file with 10 frames, but now there is only one frame. What do I need to do?
#include <iostream>
#include <fstream>
#include "../libgifski/include/gifski.h"
int main()
{
std::cout << "begin\n";
gifski* gif_writer_ = nullptr;
GifskiSettings ski_settings;
ski_settings.width = 348;
ski_settings.height = 160;
ski_settings.quality = 70;
gif_writer_ = gifski_new(&ski_settings);
if (!gif_writer_) {
return 0;
}
gifski_set_file_output(gif_writer_, "output.gif");
auto frame_count = 0;
auto stride_ = 1392;
std::ifstream in("a_348x160.rgba", std::ios::binary);
unsigned char rgba_buffer_[1392 * 160];
in.read((char*)rgba_buffer_, 1392 * 160);
in.close();
for (int i = 0; i < 10; ++i) {
gifski_add_frame_rgba_stride(gif_writer_, i,
ski_settings.width,
ski_settings.height, stride_,
rgba_buffer_, i * 1.0 / 10);
}
gifski_finish(gif_writer_);
}