2
$\begingroup$

I was using blender to render some animations for a personal blog, and I was hoping to embed the videos seamlessly into the post. I know that my website uses a background of 0xE3E5E7, so I set that as my background color in blender. When I render the animation to PNG, the background color stays at 0xE3E5E7, but once I compress it to mp4, ogv, etc. the background color changes a little bit, and sort of ruins the seamless integration I was hoping for.

I've tried using the Movie Sequence editor and using RGB curves to manually change the color balance so that the compressed video comes out right, but after about half an hour of trial-and-error, I wasn't able to actually get the output video to hit the desired color (it would get close, 0xE3E4E7, but it would never hit exactly).

Additionally, I've tried increasing the bitrate so that the compression wouldn't be much of an issue, but the problem still persists.

I was wondering if anyone knew of a way to render compressed video without color degradation or a way to filter an existing video to output something with a precise target color.

$\endgroup$
  • $\begingroup$ This sounds like the same problem as this question, which has since been deleted.. $\endgroup$ – gandalf3 Jun 16 '14 at 7:34
5
$\begingroup$

Observation is a Start

There's much knowledge in between your observation ("color changes a little bit") and the "whys" your observation manifests. Seeing as how this is a Blender forum, and most folks are intermediate to advanced, I will delve into some of the whys with the hope that you expand your colour knowledge and help to educate others.

First, unless we have done some dark alchemy via OpenColorIO, our image will be exiting Blender as an RGB based tri-colour model. So factoid number one: RGB is a relative colour system. But what does that mean?

If we take a flash light and cut some plastic of red, blue, and green transparency, we could cover our flash light with the plastic. This would deliver a coloured light of course. But what colour? That is precisely the question to ask when someone starts speaking in terms of values like 0xE3E5E7, which is nothing more than a hex value representing a numerical value relative to the RGB colour space in question. In this case, Blender assumes sRGB / 709 primaries. That is, the absolute colours referenced are relative to the sRGB or 709 specification. If our colour spaces are not aligned, despite having identical RGB values, the colours we look at will not be the same.

Into YCbCr

When we render the colours to a codec format, in most instances we are performing a transformation of the data into the codec model's format. Typically, most codecs will store data in a very different model compared to RGB, often being YCbCr. The YCbCr model extracts / isolates the luma from the curved RGB values and stores it in Y. The Cb and Cr values then represent two axes that stretch along yellow-blue (Cb) and green-red (Cr). A very different model with a unique transformation.

Second, the codec format typically requires a scaling of the ranges to meet broadcast specification standards. This is nothing more than shrinking the values to a smaller range via a scale, and then offsetting the values slightly.

Third, due to the human eye generally being less receptive to colour as compared to intensity, a codec will often scale down the Cb and Cr channels to make the codec smaller in size.

Fourth, the codec will likely compress all of this data even further using some form of lossy encoding standard, although it may also be lossless.

When Encoding Doesn't Match Decoding

Needless to say, the above steps outline a varying number of potentially complex transformations to get your RGB data out of the RGB model and into the YCbCr model. If any one of those steps is incorrectly handled by encoding or decoding, your results will vary quite dramatically.

So the simple question is "Given all of the above maze-like transforms that happen, can I get anything close to my original RGB image?" and the answer is unequivocally "Yes!" Can you do it with a simple click of a Blender render button? The chances are likely "No."

Let's assume we do a perfect encode of our material, what then? Then we are relying on the exact inverse of all of the above transformations to end up back with our perfect RGB values1. As you can guess, this only happens when an artist checks their work and the player is perfect. Even then, to achieve real-time playback, a piece of software may hand off the YCbCr stream to the graphics card, and you guessed it, they will often decode things incorrectly for any number of reasons.

Advice

If you are interested in achieving a perfect encode, the best advice is become a knowledgeable artist in the realm of colour and pixels. You have taken the first steps in noticing that things aren't quite right.

If you encode to a series of images and then encode again to your codec, you stand a much better chance of testing your pipeline for accuracy. In particular, because most encoding software may have different design constraints2, they may make different design decisions that result in different results. Therefore, the safest way to handle video is to encode the YCbCr yourself and then pass that raw data to an encoder and test the encoded values.

If they match, it is out of your hands and into your audience's set of qualitative evaluations at their end to decode it, if this is your goal. If they don't, something went wrong and you can correct it.

The above is a quick outline as to the sad reality of the complexities of your initial, seemingly simple first observation. Controlling the output on the other hand, is relatively easy and will get faster and faster with more knowledge. This is likely beyond the scope of this Stack Exchange answer though, so I'll leave it at that3.


  1. Quantization errors may be present depending on the many encoding options you choose. Broadcast scaling for example, will necessarily degrade your image due to a reduced number of bits storage.
  2. Many video encoders and decoders may target speed of encoding or decoding for quick encoding or speedy playback. Of course this will come at a cost, often times being accuracy due to lower bit depths used to encode or short cuts to achieve playback speed.
  3. Feel free to contact me if you want to explore this area. It is possible to encode your data to a bitwise precise encode, subject to quantization / specifications. I should be relatively easy to find.
$\endgroup$
0
$\begingroup$

You could attempt to export png files and sequence them and upscale the video. In the past i managed to get blender to compress this color correct. Unfortunately this can not be guaranteed. It may depend which type of compressor is used internally. This can vary from software encoding to hardware encoders like quicksync and nvenc. There's no setup for those inside of in blender tho. You could always try other video tools to encode.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.