-
Notifications
You must be signed in to change notification settings - Fork 233
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
Properly convert Java char to C char in inputSwizzle #876
Conversation
Thank you for this. I will review it as soon as I can. I have other PRs to review first. In the meantime, please add a test for swizzle to |
I have added a test that calls EDIT: The following is obsolete. See the comment below for details. There does not seem to be a way to check whether the result image is the "broken" one, or the one where the RGBA -> BRGA swizzle has properly been applied... |
I have added a test to compare the result of (I tried this initially, and it didn't work as expected, but this was caused by an issue in the |
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.
One question to be answered and 1 change to make.
t.compressBasisEx(p); | ||
|
||
// Obtain the texture data, and compare it to the | ||
// expected data of the reference texture |
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.
Since you are creating the texture in the test, I'd prefer not to need a reference file. You can transcode the swizzled t
to KTX_TTF_RGBA32
and compare those pixels with the pixels in rgba
. Given the full on colors you are using I don't think compression & transcode will change them.
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'd also like to avoid that reference file. (One reason: The tests/testimages
directory already contains >100 files, without any information about what these files are, where they come from, and what they are used for. I'd like to avoid throwing more images on that pile...)
And what you suggested might ... nearly work: From a quick test, converting the resulting data to KTX_TTF_RGBA32
gave the following input/output pxiel values:
Pixel 0 in input 255, 0, 0, 255
Pixel 0 in output 2, 255, 2, 255
...
Pixel 256 in input 0, 255, 0, 255
Pixel 256 in output 0, 0, 253, 255
...
Pixel 512 in input 0, 0, 255, 255
Pixel 512 in output 253, 0, 0, 255
The swizzling is applied correctly, but there is a slight deviation in the formerly "pure" colors, of +/- 2
in some components. I don't know where this might come from - maybe something about SRGB, or it's a compression artifact, or whatnot. If you have an idea what might be causing this (or how to avoid this), I could change it accordingly.
Regarldless of that, the test could be changed to not use a reference image, by comparing the result of converting the image to KTX_TTF_RGBA32
to pixel values that are created programmatically (using the same functions that are used for creating the input image).
This could then be
- A fixed comparison to the values that I currently see in the output (
2, 255, 2
) - Or a comparison with
expected=(0, 255, 0)
but with some "epsilon" of maybe+/-5
to account for the slight changes...
Any preference?
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 prefer the fixed comparison as the test will not then be sensitive to changes in the encoder. You could also try ktxTexture2_CompressAstcEx
. Perhaps that will have less artifacts.
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.
You could also try ktxTexture2_CompressAstcEx. Perhaps that will have less artifacts.
Actually, in order to have proper test coverage, I can not only 'try' this (as an alternative), but actually have to test this in addition to the current test. Both of them (basis and astc) are going through different code paths (even though they are doing the same sort of conversion for the swizzling).
The test failed on GNU/Linux and macOS but passes on Windows. I'm surprised by that. |
I'm a little bit surprised by that as well. Looking at the failed build output:
It does compare the array obtained with (Maybe this becomes obsolete when the reference file is no longer used, but I'm still curious...) |
Yes it does. See BinomialLLC/basis_universal#60. |
@MarkCallow The test has been updated to no longer compare to a reference image. Instead, it is converting the texture to As you have seen, there are follow-ups for this PR:
|
There are three PRs open right now. (And sorry for that. I certainly did not anticipate "big" changes in the beginning, and only wanted to fix that swizzle thing, but ... the requirements for further changes 'piled up' in the process). Given that these PRs build upon one another, there are the options to
The last one will probably be 'large', and involve more changes, discussion, and reviews. So the first ones could be merged as intermediate steps, because they are still 'self-contained'. None of these PRs is "time-critical", so to speak. (And it's unlikely that there are conflicts with other areas - who's using JNI after all? 😁 ). So we can defer merging anything until you're back (c.f. your comment at #879 (comment) ) In the 'supercompression' PR, you added a comment about the test that actually refers back to a comment here, where you said
What I did:
What you now suggested, as pseudocode: byte input[] = createInput();
// Compress to basis, once without and once with swizzling
KtxTexture2 original = compressWithoutSwizzle(input);
KtxTexture2 swizzled = compressWithSwizzle(input);
// Transcode to RGBA32
byte originalRgba[] = original.transcodeToRgba32();
byte swizzledRgba[] = swizzled.transcodeToRgba32();
// Check each pixel of the swizzled output if it is
// exactly the same as the swizzled pixel in the
// output that was created without swizzling
for (each pixel) {
swizzledRgba[pixel] = swizzle(originalRgba[pixel]);
} If this is correct, then I can change this accordingly. (It involves implementing a 'swizzle(pixel)' function for the test, but ... OK) |
A quick test suggests that the proposed approach does not work as expected. When implemented based on the pseudocode, the output will be
So apparently
produce different results, exactly in ths Given that...
... I'm leaning towards not trying to make "this test perfect" now. Improving the tests and coverage (including the subtle questions about slight color deviations) may be part of #886 . If your concern is that this test might break unpredictably, I'll just remove the "pixel color comparison". Then we'd have a working swizzle functionality, even though it's not covered by a test, similar to a million other things that are 'working 🤞' but not covered by a test. And by the way: All this suggests for me that there is zero test coverage for the effects of swizzling on the native side either. One could certainly argue about the responsibility of the Java bindings for "pixel-perfect comparisons" here... |
There are unittests for the function that performs the swizzle before submitting the data to the encoder and there are tests of the
|
Thanks @MarkCallow , that seems to work (at least locally - let's see whether the build passes...) If the number of this kind of tests (which compare actual pixel values) increases, some of the required functionality could be moved into the |
@MarkCallow I think this should be ready to merge, if you agree. When this is merged, I'd wrap up #879 (which should only be a small one then). For the "big" one, #886 , I'll do some more testing/polishing , and ... we'll have to figure out a way how this could sensibly be "reviewed".... |
This builds upon #876 , which is already merged. It exposes the `deflateZstd` and `deflateZLIB` functions of the `ktxTexture2` class to the Java `KtxTexture2` class.
Fixes #875
As detailed in the issue: The Java
char[]
array for the input swizzle was casted to ajbyteArray
in the JNI layer, in order to write it to the C/C++char[4]
array. This cast was invalid and caused data corruption.There could be two ways of tackling this:
inputSwizzle
in the Java layer tobyte[]
(which has 8 bits, and would make the cast valid). This would be a breaking change, and may require the inconvenient casting at the call site likep.setInputSwizzle(new byte[]{ (byte)'b', (byte)'r', (byte)'g', (byte)'a' });
char[]
array as ajcharArray
, and cast the elements to (C/C++)char
individuallyThis PR takes the second option (but we could do this either way, depending on the preferences from others).
With this change, running the test/example program that is given in the issue produces the following results (showing the PNG files here - the KTX ones are attached below)
Without calling
setInputSwizzle
, the result is this:(
output_swizzle_unswizzled.png
)With
setInputSwizzle(new char[]{ 'r', 'g', 'b', 'a' });
(which should not change anything), the result is this:(
output_swizzle_rgba_fixed.png
)With
setInputSwizzle(new char[]{ 'b', 'r', 'g', 'a' });
, actually swizzling things around, the result is this:(
output_swizzle_brga-fixed.png
)The KTX and PNG files are attached here:
KTX swizzle results 2024-03-22.zip
This PR does not involve any unit tests. I wouldn't know how to add one exactly - maybe just comparing the output to a "golden" reference file?