[FFmpeg-user] Lossless and colour preserving pix_fmt?

Jim DeLaHunt from.ffmpeg-user at jdlh.com
Thu Jan 11 05:52:59 EET 2018

On 2018-01-07 21:29, Jim DeLaHunt wrote:
> Hello, ffmpeg'rs:
> I'm trying to overlay animated GIFS onto one white background, with 
> some text at the top.  I'm looking for an incantation which a) does 
> the job and b) leaves all the colours of the animated gifs unchanged.
> What options tell ffmpeg not to mess with the colour values, not to 
> change colour spaces, not to reduce precision of colour coordinate 
> values?

The best answer to this appeared in an answer to SuperUser question, 
/Lossless universal video format /[1] 
[1] https://superuser.com/questions/486325/lossless-universal-video-format

Preserve colour space? Sorry, none. The Animated GIF colour values are 
defined as 24-bit RGB values in sRGB space.  As far as I can tell it's 
hard to get FFmpeg to use RGB for its operations, it really pushes you 
to YUV (luminance and two chroma values). However, the YUV values are 
24-bits. I speculate that perceptually, a conversion from sRGB to YUV 
back to sRGB will be lossless.

You need to prevent lossy compression by the pixel format (encoder). The 
*libx264* encoder with the option *-crf 0* provides lossless compression.

You also need to prevent downsampling of the U,V components of the YUV 
colour value. This is explained well at /Recommended 8-Bit YUV Formats 
for Video Rendering/ 
by Gary Sullivan and Stephen Estrop, Microsoft Corporation, 2002 and 2008.

The term *YUV444* refers to Y,U,V colour space, and 4:4:4 downsampling, 
i.e. U,V at same resolution as Y.
*YUV420* refers to U,V at 1/2 horizontal x 1/2 vertical = 1/4 overall 
resolution as Y.  That works against lossless encoding. Be sure your 
encoding is using a pix_fmt like YUV444. As far as I can tell, *libx264 
-crf 0* defaults to YUV444 pixel format.

Then Carl Eugen points out something else important: how to generate a 
good palette for the output GIF.

On 2018-01-08 04:25, Carl Eugen Hoyos wrote:
> Depending on the input file, this may not be possible.
> To create a (nice looking) gif - with most likely different colours - you
> need the palettegen and paletteuse filters.
I was making an assumption that when ffmpeg saved to GIF format, it by 
default created a palette which would render the animation well. It 
looks like that's incorrect, and the *palettegen* filter 
<http://ffmpeg.org/ffmpeg-all.html#palettegen-1>[3] can generate a 
better palette. Maybe there's some strong technical reason for this, 
such as the GIF output having to created a palette based on information 
only from the first frame, while palettegen can gather information from 
all frames.
[3] http://ffmpeg.org/ffmpeg-all.html#palettegen-1

In any case, here's how I addressed the problem.  I broke the task into 
four steps.

1. Read the animated GIF in, store as libx264 -crf 0 format in a 
Matroshka container.

2. Run the x264 video through palettegen, generating a palette as a PNG 

3. Read the x264 video in again, passing it and the palette through the 
paletteuse filter, saving as animated GIF.

4. Delete the x264 video and the palette.

This gave me acceptable quality. Here's roughly the commands I used:

% ffmpeg -i animated_blue_12.gif -filter_complex "
color=color=white at 1.0:size=696x400,
drawtext=fontsize=20:font=Arial:x=10:y=10:text=Hamburgefons Hamburgefons Hamburgefons
[0:v] setpts=PTS-STARTPTS [gs1];
[background][gs1] overlay=format=yuv444:shortest=1:x=20:y=40
" -c:v libx264 -crf 0 -preset ultrafast -y temp.mkv

% ffmpeg -i temp.mkv -vf palettegen palette.png

% ffmpeg -i temp.mkv -i palette.png -filter_complex paletteuse -y blue+text.gif

% rm temp.mkv palette.png

I hope that's helpful for someone!  Thanks,
        —Jim DeLaHunt, Vancouver, Canada

     --Jim DeLaHunt, jdlh at jdlh.com     http://blog.jdlh.com/ (http://jdlh.com/)
       multilingual websites consultant

       355-1027 Davie St, Vancouver BC V6E 4L2, Canada
          Canada mobile +1-604-376-8953

More information about the ffmpeg-user mailing list