-
-
Notifications
You must be signed in to change notification settings - Fork 698
cgifsave: palette change POC #2824
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
cgifsave: palette change POC #2824
Conversation
e1bb183
to
712f057
Compare
Oh, nice! It seems to work well on the test images I tried. @dloebl, any thoughts? |
26929fa
to
420bcd4
Compare
0ea45c8
to
e97850e
Compare
e97850e
to
c7a24b8
Compare
libvips/foreign/cgifsave.c
Outdated
|
||
best_dist = VIPS_MIN(best_dist, dist); | ||
|
||
/* We fond the closest entry |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: fond -> found
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, fixed
libvips/foreign/cgifsave.c
Outdated
if( cgif->frame_checksum == 0 || | ||
checksum != cgif->frame_checksum ) { | ||
cgif->frame_checksum = checksum; | ||
static double pal_change_threshold = 64.0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method seems to be similar to the way the maxerror
parameter is handled right now: cgifsave.c#L177
We could make the threshold dynamic (e.g. use maxerror
here) and set maxerror
to a value > 0 by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think maxerror
fits well here. For example, 64 is a good value for the inter-palette error while it is too large for the inter-frame error. Yet I agree that this number should be dynamic. Maybe we should rename maxerror
to, for example, interframe_maxerror
and add a new param for inter-palette max error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made it dynamic and renamed maxerror
. If everything is ok, I'll squash the commits. /cc @jcupitt
Looks like a nice improvement to me 👍 |
5bb685e
to
a819f16
Compare
I'm seeing some errors with video clips -- it's tagging pixels as transparent when they should all stay solid. Perhaps dispose isn't always being set correctly? |
Could you give a sample, please? I have like 16 test GIFs, and all of them work fine. |
Sorry, it's not a GIF I can share :( I'm trying to find another example, but no luck so far. Let's fix this up and merge it, then try to resolve any fails in another PR. |
Hi, shall I fix the merge conflict? |
I made a GIF I can share that fails. This terrible GIF: http://www.rollthepotato.net/~john/skate.gif Converted using this branch:
Becomes: http://www.rollthepotato.net/~john/x.gif It looks like every pixel which is equal to the previous pixel becomes transparent in the output, which causes a lot of artefacts at the start of the clip. |
a819f16
to
62000a9
Compare
Rebased and squashed the branch.
Oh, thank you! I'll dig it. |
I've tested @jcupitt could you test it again on your end? Maybe it was fixed after the rebase? |
I wiped everything and rebuilt, and I see still bad artefacts. Could it be the cgif version? I'm using git master. |
Maybe it's similar to the issue mentioned here? |
@dloebl That's it, thank you! I'll try to fix it. |
Also I noticed that these pixels are not transparent but just grey. And, as Daniel said, artifacts appear only when dithering is enabled. So I believe it's a bug in LIQ 2.17 itself, and we can do nothing with it. |
Ah good spot. But these artefacts only appear with this branch -- master seems to work fine. I think something in this PR has triggered this behaviour. |
Master uses local palette for basically every frame while this branch doesn't use a local palette when reusing a global one. I noticed that LIQ 2.17 changes palette a lot during remapping, which is not good for us. AFAIK the only way to bypass this is using the histogram API, which is basically what liq_image_quantize does. But fork by @lovell doesn't have such API :( |
BTW it seems like the same problem may occur when we reuse the global palette from the source image, too. |
Perhaps we should merge, and then try to find a workaround for this in another PR. What do you think? |
It seems like I fixed it! I added the
Somehow code with this hack works even faster than without it. Probably because LIQ doesn't change the palette. |
That's great! All my tests pass too, well done. I see some small leaks in valgrind, but maybe that's just libimagequant. Let's merge and maybe try to patch them in another PR. |
I did a quick benchmark against imagemagick:
So for this GIF at least (a short video clip) libvips is now 10x faster, needs 4x less memory, and makes GIFs which are 20% smaller! Nice work everyone. |
.... and the dithering of the libvips one is better too, so they look nicer. |
Against libvips 8.12:
|
Hey!
This is the POC of my approach to generating palettes for
cgifsave
. How it works:With this approach, we mitigate the difference between neighbor frame colors which helps transparency and frame optimizers do their jobs.
Some numbers:
Master speeed:
New speeed:
Result sizes
Here I resized the images a bit to increase the color number.
Findings
As we see, the memory footprint is more or less the same for both approaches, yet my approach is slightly faster and produces slightly smaller files. Also, this approach doesn't have a frame size limitation.