1

I'm trying to scale an RGB image in a gamma-correct way, i.e. with a gamma transform before and after the scaler. Because gamma correction at 8 bits/channel creates "banding", I convert the image to 16 bits/channel (gbrp16le) at the beginning, and then back to rgb24 when everything's done.

Problem is, this process somehow results in inaccurate colors: instead of black (rgb 0,0,0) I get a dark violet (rgb 25,0,27).

My command line (Windows batch, so the ^ character escapes double-quotes and newlines):

ffmpeg -loglevel 42 -hide_banner -y -i testcase.png -vf ^"^
    format=gbrp16le,^
    lutrgb='r=gammaval(2.2):g=gammaval(2.2):b=gammaval(2.2)',^
    scale=iw/2:ih/2:flags=bicubic,^
    lutrgb='r=gammaval(0.454545):g=gammaval(0.454545):b=gammaval(0.454545)',^
    format=gbrp16le,^
    format=rgb24^" ^
testcase-out.png

(The second format=gbrp16le is because the scaler itself seems to convert to rgb24 otherwise, and gives me banding after the 2nd gamma transform)

Sample input "testcase.png" - the black area surrounding the bars is rgb 0,0,0:

Sample input (testcase.png)

And the output is this. Maybe hard to see, but if you actually check the color values, the blacks have now become 25,0,27 (#19001B):

Sample output (testcase-out.png)

At this loglevel I also get the following details about what the filtergraph is doing:

[Parsed_scale_2 @ 0000000002c90340] w:iw/2 h:ih/2 flags:'bicubic' interl:0
[graph 0 input from stream 0:0 @ 000000000019d200] w:420 h:212 pixfmt:rgb24 tb:1/25 fr:25/1 sar:0/1
[auto_scaler_0 @ 00000000001aa4c0] w:iw h:ih flags:'bicubic' interl:0
[Parsed_format_0 @ 00000000006f8f00] auto-inserting filter 'auto_scaler_0' between the filter 'graph 0 input from stream 0:0' and the filter 'Parsed_format_0'
[auto_scaler_1 @ 00000000001aa5c0] w:iw h:ih flags:'bicubic' interl:0
[Parsed_format_5 @ 000000000019cf80] auto-inserting filter 'auto_scaler_1' between the filter 'Parsed_format_4' and the filter 'Parsed_format_5'
[auto_scaler_0 @ 00000000001aa4c0] w:420 h:212 fmt:rgb24 sar:0/1 -> w:420 h:212 fmt:gbrp16le sar:0/1 flags:0x4
[Parsed_scale_2 @ 0000000002c90340] w:420 h:212 fmt:gbrp16le sar:0/1 -> w:210 h:106 fmt:gbrp16le sar:0/1 flags:0x4
[auto_scaler_1 @ 00000000001aa5c0] w:210 h:106 fmt:gbrp16le sar:0/1 -> w:210 h:106 fmt:rgb24 sar:0/1 flags:0x4

Is there a clue there? How can this be fixed?

A few things I've already tried:

  • Adding other scaler flags (accurate_rnd, full_chroma_int, full_chroma_inp, bitexact)
  • Changing src_range and dst_range in the scaler options, just in case it's a "full" vs. "limited" issue (although the green channel is not affected)
  • Removing ICC profile from the input .png
  • Changing gbrp16le to other pixel formats with >8 bits/channel, e.g. gbrp10le
  • Using different scaling algorithms (e.g. lanczos, neighbor)

None of the above helps...

2
  • Have you tried without the scaling? Just the color conversion? Commented Jan 14, 2021 at 19:31
  • @EugenRieck: Yes, without the "scale" the blacks stay black. (Actually rgb 1,0,2 rather than 0,0,0 exactly - but that's a much smaller error which I can live with, or possibly fix with something like "curves" or "normalize" without being too destructive).
    – CugelTC
    Commented Jan 14, 2021 at 21:10

1 Answer 1

1

I've updated my FFmpeg build and the problem is gone - evidently this bug was already fixed some time within the last 2 months.

(Previous build was 4.3.1-2020-11-19, current build is 2021-01-12-git-ca21cb1e36)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .