KhronosGroup / KTX-Software

KTX (Khronos Texture) Library and Tools
Other
854 stars 226 forks source link

Converting transfer functions (using assign-oetf and convert-oetf) #871

Closed SeanCurtis-TRI closed 5 months ago

SeanCurtis-TRI commented 5 months ago

Based on the documentation, I would expect the following to work:

ktx create --encode=basis-lz --format=R8G8B8_SRGB --assign-oetf=srgb --convert-oetf=linear foo.png foo.ktx2

(Converting the sRGB png into a linear color space ktx2 file). It's pretty clear that the documentation says if the oe transfer function assigned is different from the convert transfer function, that it gets converted.

However, I get the error message:

ktx create fatal: Invalid value to --convert-oetf "linear" for format "R8G8B8_SRGB". Transfer function must be sRGB for sRGB formats. See 'ktx create --help'.

Is my understanding incorrect or is this a bug? What am I missing?

MarkCallow commented 5 months ago

The KTX spec. requires an sRGB OETF (transfer function) for _SRGB formats as explained in the error message. If you really want linear, use --format R8G8B8.

We have discussions underway re clarifying handling of OETF and primaries in the tool and adding support for not-KHR_DF_TRANSFER_LINEAR OETFs for non-_SRGB formats which is allowed by the spec. The documentation will be updated as part of that work.

SeanCurtis-TRI commented 5 months ago

Oops. In my example above, I failed to include the --encode parameter. (Now edited to correct this oversight).

With that correction, I don't understand your answer:

Based on that, I drew what seemed like very direct, obvious conclusions:

  1. My --format should reflect the format of my input file (which is sRGB).
  2. I can get ktx to convert transfer functions so that my output file is in linear space.

Can I not convert an input sRGB file to an output linear file?

What have I misunderstood in the documentation? The language seems very clear, but inconsistent with the error message.

MarkCallow commented 5 months ago

@aqnuep do you have any comment?

aqnuep commented 5 months ago

--format is documented that if "when used with --encode it specifies the format of the input file before the encoding step." (emphasis mine).

Maybe the description needs to be clarified, but the format in this case should still respect the target color space in the sense that for a linear target transfer function you need a non-SRGB format. It matters even if you further encode the texture with BasisLZ, as the image is first converted to the target format (e.g. R8G8B8A8_UNORM) and then encoded with BasisLZ.

SeanCurtis-TRI commented 5 months ago

Certainly clarification of the documentation would be an acceptable way to resolve this. Your responses are certainly painting a different picture from what the documentation claims. So, without some clear reference to the documentation and how I misread it, it suggests a defect in the documentation. I look forward to seeing how the discussions resolving transfer functions play out.

But, putting aside the question of documentation correctness (as, regarding this issues, it appears it can't be trusted), I'll reiterate my core question:

Can ktx be used to convert input sRGB into output linear?

aqnuep commented 5 months ago

Yes, ktx can be used to convert (PNG) input sRGB to linear output.

If the input PNG file already has an sRGB color space encoded, and the target format is a UNORM one then the conversion will happen automatically. If you're not sure the input PNG file actually has the sRGB color space encoded in it, then you can use --assign-oetf srgb, as you tried to treat the input PNG file as having sRGB color space. Also, the way you use --convert-oetf linear to force the conversion to linear is correct. Only the --format was misused (understandably due to the ambiguity in the documentation).

aqnuep commented 5 months ago

One thing I forgot to mention is that if you do want to convert sRGB to linear and you do specify the --assign-oetf srgb to force the input you also have to force the conversion with --convert-oetf linear, because assign-only, without convert, means that you simply override the OETF without wanting a conversion to happen.

SeanCurtis-TRI commented 5 months ago

If you look at the original post (with the correcting edit), you'll not I did both --assign-oetf srgb and --convert-oetf linear (as suggested by the documentation) and still got the error message. So, maybe there's more defect than just the documentation?

aqnuep commented 5 months ago

If you look at the original post (with the correcting edit), you'll not I did both --assign-oetf srgb and --convert-oetf linear (as suggested by the documentation) and still got the error message. So, maybe there's more defect than just the documentation?

But you also specified --format=R8G8B8_SRGB instead of --format=R8G8B8_UNORM, which is the root cause of the error.

SeanCurtis-TRI commented 4 months ago

I feel like I'm walking around in circles. Of course I noted --format=...SRGB because that is documented to specify the input format when --encode is specified. But the error seems to arise from the fact that it disagrees with the requested output oetf.

aqnuep commented 4 months ago

--format is not the input format, it was just ambiguously defined in the help text, as it's only the "input format" of the encoding, and in fact it's really the target format, that just happens to be encoded afterwards.

We already fixed the help text and man page. Please just change the command you use as follows and it should work:

ktx create --encode=basis-lz --format=R8G8B8_UNORM --assign-oetf=srgb --convert-oetf=linear foo.png foo.ktx2
SeanCurtis-TRI commented 4 months ago

I fear there is still a basis of disagreement.

I have a wood-grain png. When loaded it appears (as the attached image shows):

image

When I run the following

ktx create --encode=basis-lz --format=R8G8B8_SRGB --assign-oetf=srgb --convert-oetf=srgb foo.png foo.ktx2

I get this appearance. This is what we would expect. One can see some compression artifacts, but the color space has been preserved.

image

However, when I run your command:

ktx create --encode=basis-lz --format=R8G8B8_UNORM --assign-oetf=srgb --convert-oetf=linear foo.png foo.ktx2

I get the following image.

image

My interpretation is that the --format is definitely being associated with the input data. The sRGB values are being misinterpreted as unnormalized linear and, therefore, when I output the linear result, it's dark.

What am I missing?

aqnuep commented 4 months ago

When you request the conversion from sRGB to linear, obviously, the data will change, because you decode the sRGB values into linear values. By default, transcoding BasisLZ into RGBA will lead you an R8G8B8A8_UNORM image (currently there's no control over this in libktx IIRC).

In the end what matters is whether you present the RGBA texture resulting from transcode through a linear or an sRGB view (which you did not specify here). It is difficult to judge what's happening without knowing the full pipeline you use to achieve these images.

SeanCurtis-TRI commented 4 months ago

Sorry for this tardy delay.

Thanks for your patience and help. We've got it all up and running and your last note was 100% correct and I was misinterpreting the rendering results. Thanks again.

MarkCallow commented 4 months ago

Glad you resolved it, @SeanCurtis-TRI.

By default, transcoding BasisLZ into RGBA will lead you an R8G8B8A8_UNORM image (currently there's no control over this in libktx IIRC).

The transcoder selects _SRGB if the DFD's transfer function is sRGB, and there is an SRGB variant of the chosen transcode target, otherwise it selects _UNORM.