-
-
Notifications
You must be signed in to change notification settings - Fork 851
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
Color conversion with ICC profiles #1567
Draft
JimBobSquarePants
wants to merge
94
commits into
main
Choose a base branch
from
icc-color-conversion
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 1 commit
Commits
Show all changes
94 commits
Select commit
Hold shift + click to select a range
16179b3
Copy original PR changes.
JimBobSquarePants eeb40f5
Merge branch 'master' into icc-color-conversion
JimBobSquarePants 8b96d37
Merge branch 'master' into icc-color-conversion
JimBobSquarePants aa2f1e9
Merge branch 'master' into icc-color-conversion
JimBobSquarePants 3debb26
Merge branch 'master' into icc-color-conversion
brianpopow 0812085
Fix warnings
brianpopow 1094dc6
Add color conversion trait to be able to filter for those tests
brianpopow 759f053
Fix failing MatrixCalculator test
brianpopow 4cde4ef
Merge branch 'master' into icc-color-conversion
JimBobSquarePants a973713
Merge branch 'master' into icc-color-conversion
JimBobSquarePants 33339d0
Merge branch 'master' into icc-color-conversion
JimBobSquarePants cdb495c
Merge branch 'master' into icc-color-conversion
JimBobSquarePants 5f7acc1
Merge remote-tracking branch 'origin/main' into icc-color-conversion
brianpopow 7e2bc20
Merge branch 'main' into icc-color-conversion
JimBobSquarePants dc166a7
Fix build
JimBobSquarePants dcc8147
Cleanup icc tests
brianpopow 73c8d8f
Fix Copyright notice
brianpopow d229fed
Fix icc namespaces
brianpopow 0a08da0
Use file scoped namespaces
brianpopow daf366b
Cleanup and add conversion tests
JimBobSquarePants 54856ff
Fix reader and out of range exception
JimBobSquarePants eee14c6
Remove invalid test.
JimBobSquarePants f60d4b8
Merge branch 'main' into icc-color-conversion
JimBobSquarePants 8de137e
Cleanup code style
JimBobSquarePants fb8003c
Remove double clamping
JimBobSquarePants 9f0f9cb
Optimize matrix read/write
JimBobSquarePants ece11eb
Create ColorProfileHandling.cs
JimBobSquarePants bd7257b
Merge branch 'main' into icc-color-conversion
JimBobSquarePants 9a21485
Nullable disable
JimBobSquarePants ba76964
Merge branch 'main' into icc-color-conversion
JimBobSquarePants 98d1758
Merge branch 'main' into icc-color-conversion
JimBobSquarePants 66554cb
Add ability to convert ICC profile on decode
JimBobSquarePants e90f165
Merge branch 'main' into icc-color-conversion
JimBobSquarePants 8c580a7
Handle nullability in decoder base
JimBobSquarePants a81dac9
Add reference files.
JimBobSquarePants 902ed99
Add tolerance for Mac
JimBobSquarePants e3aa452
Merge branch 'main' into icc-color-conversion
JimBobSquarePants 0dd68fe
Merge branch 'main' into icc-color-conversion
JimBobSquarePants 6e3dc81
Update decoder bases following merge
JimBobSquarePants b7833a4
Merge branch 'main' into icc-color-conversion
JimBobSquarePants c3984aa
Add failing tests
JimBobSquarePants 0fff06d
Port 1d, 2d, 3d, 4d and nd interpolation from reference implementation
brianpopow f1c05ee
Remove not used IccClut constructors
brianpopow 3be31c3
Preserve alpha component
JimBobSquarePants 6c2ee90
Fix CieLab docs
JimBobSquarePants 20e9b7f
Fix out of bounds error
brianpopow d6fbc01
Change clut values from jagged array to flat array
brianpopow 67ed4ce
Fix warnings
brianpopow b036cc3
Fix mistake reading the clut values
brianpopow 52f88c8
Fix oob in n-dimension calculator.
JimBobSquarePants ed47678
Add Lab<=>Xyz conversion
JimBobSquarePants 10bea86
Add ICC reader tests
brianpopow 5b131ad
Add reference output for issue-129
brianpopow ed8091b
Merge branch 'main' into icc-color-conversion
JimBobSquarePants 6225db3
Merge branch 'main' into icc-color-conversion
JimBobSquarePants a65c599
Merge branch 'main' into icc-color-conversion
JimBobSquarePants 60f3d9d
Merge branch 'main' into icc-color-conversion
JimBobSquarePants c940b86
Merge branch 'main' into icc-color-conversion
JimBobSquarePants a567613
Merge branch 'main' into icc-color-conversion
JimBobSquarePants 3e06687
Update IccReader.cs
JimBobSquarePants c1ebbfe
Fix build
JimBobSquarePants d89d8c5
Update IccReader.cs
JimBobSquarePants 63c89ca
Use scaled Vector4 conversion and optimize
JimBobSquarePants 3389d7a
Add some debugging helpers to the converter
JimBobSquarePants 7b0ff3b
Merge branch 'main' into icc-color-conversion
JimBobSquarePants 29ed2b4
Merge branch 'main' into icc-color-conversion
JimBobSquarePants 5f975e5
Update to latest main build
JimBobSquarePants 79f5dfa
Update IccProfileConverterTests.cs
JimBobSquarePants b88b2a9
Merge branch 'main' into icc-color-conversion
JimBobSquarePants bca4cad
Merge branch 'main' into icc-color-conversion
JimBobSquarePants 6e2c29c
Merge branch 'main' into icc-color-conversion
JimBobSquarePants 5b374da
Fix IccClut test setup and calculator guards
JimBobSquarePants 441f07e
Update ColorProfileConverter to handle ICCProfiles
JimBobSquarePants 6654218
Suppress warning
JimBobSquarePants 21fec4e
Demonstrate ICC conversion comparison to Unicolour
waacton fd2e8a9
Migrate tests
JimBobSquarePants 19ff69d
Add ICC files to LFS
JimBobSquarePants 3cd7d67
Update TestIccProfiles.cs
JimBobSquarePants 0327dca
Adjust PCS values for v2 profiles using perceptual intent
waacton 9de3935
Remove TODO
waacton 8e92f20
Fix XYZ PCS conversions
waacton 312b55e
Cleanup
JimBobSquarePants 44aae40
Merge branch 'main' into icc-color-conversion
JimBobSquarePants df3d230
Extract conversion for v2 perceptual intent
waacton d20fddb
Precalculate v2 perceptual PCS adjustment
waacton d60ac76
Bypass PCS adjustment when not needed
waacton cfa2760
Add failing tests for CMYK to RGB using Matrix TRC
waacton 369bf5f
Fix CMYK to RGB using TRCs
waacton 7d4a742
Add RGB to CMYK tests and fix TRC calculator
waacton f4e9509
Handle tests in cases where PCS adjustment is bypassed
waacton 9ceed23
Fix expected values of CLUT unit tests
waacton f21c0c2
Fix LUT entry calculator for XYZ PCS with non-identity matrix
waacton f147aad
Minor cleanup
JimBobSquarePants 7492109
Merge branch 'main' into icc-color-conversion
JimBobSquarePants File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,13 +49,13 @@ private static IccLut CreateLut(int length) | |
|
||
public static object[][] Lut8ConversionTestData = | ||
{ | ||
new object[] { Lut8, new Vector4(0.2f, 0.3f, 0, 0), new Vector4(0.339762866f, 0, 0, 0) }, | ||
new object[] { Lut8Matrix, new Vector4(0.21f, 0.31f, 0.41f, 0), new Vector4(0.431305826f, 0, 0, 0) }, | ||
new object[] { Lut8, new Vector4(0.2f, 0.3f, 0, 0), new Vector4(0.4578933760499877f, 0, 0, 0) }, | ||
new object[] { Lut8Matrix, new Vector4(0.21f, 0.31f, 0.41f, 0), new Vector4(0.40099657491875312f, 0, 0, 0) }, | ||
}; | ||
|
||
public static object[][] Lut16ConversionTestData = | ||
{ | ||
new object[] { Lut16, new Vector4(0.2f, 0.3f, 0, 0), new Vector4(0.245625019f, 0, 0, 0) }, | ||
new object[] { Lut16Matrix, new Vector4(0.21f, 0.31f, 0.41f, 0), new Vector4(0.336980581f, 0, 0, 0) }, | ||
new object[] { Lut16, new Vector4(0.2f, 0.3f, 0, 0), new Vector4(0.3543750030529918f, 0, 0, 0) }, | ||
new object[] { Lut16Matrix, new Vector4(0.21f, 0.31f, 0.41f, 0), new Vector4(0.29739562389689594f, 0, 0, 0) }, | ||
}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These test values are updated in the same way as the CLUT tests, calculated independently in Unicolour. |
||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
It seems
Vector4.Transform
was performing Vector × Matrix not Matrix × Vector? My matrix maths is rusty, but in lieu of some kind ofMatrix4x4.Transform(matrix, vector)
function it sounds like transposing the matrix has the same effect as changing the order of multiplication.This issue wasn't caught yet because none of the ICC conversion tests use a profile of CMYK data ⇒ XYZ PCS. And even if it did, it would only get caught if using a non-identity matrix? As always, I'll be surprised if we can find a profile that meets these conditions, though we can include it in testing if we do.
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.
Honestly, I'm not sure. @saucecontrol could I borrow your brain here please?
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.
Vector4.Transform
is a dot (inner) product, which is commutative between a vector and matrix1.I can work up some profiles to test some of these edge cases if you'd like. I swear one of these days I'm going to get around to finishing my implementation of LUT profile transforms, and I'll need them then anyway.
Footnotes
Well, not in general, but in this case it's a square matrix and a vector with length equal to the length of each matrix dimension, so it is here. ↩
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.
Here we want a matrix multiplication M×V which isn't commutative, but doing V⋅MT effectively calculates M×V in this particular case.
Is that an OK assumption to make given we're restricted to
Matrix4x4
andVector4
? Is there a more suitableSystem.Numerics
way to do this?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 don't want M×V, you want M⋅V, and I promise it's commutative.
The reason transposing gives you the correct result is that
Vector4.Transform
assumes the matrix is row-major, i.e. the V is a 1x4 matrix. Most of ICC docs describe the matrices as column-major, which would mean your V is a 4x1 matrix.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 can also see from the implementation of
Vector4.Transform
why it's done row-major -- that enables SIMD acceleration per row because of the memory layout. For perf reasons, you'll want to normalize to row major on the edges of the API.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 think some of my assumptions have muddied the waters a bit, so I'm going to try to summarise, and if I'm still making a mess I'll have to leave this to someone else.
System.Numerics
to know if there's a more conventional way to "achieve the effect of matrix multiplication" than transposing the 4x4 matrix - @JimBobSquarePants perhaps any 4x4 matrices just need to be initialised row-major?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.
This is also commutative, as it is also a dot product. The only difference is whether you compute the dot product of the vector with each row of the matrix or with each column of the matrix.
There is no fast way to compute it column-wise, because it means gathering the non-adjacent values in memory. In fact, transposing the matrix with SIMD and then performing a row-wise dot product with SIMD is the fast way to do this, although it is much less fast than normalizing your matrix to row-major when reading the profile and skipping the transpose step during processing.
Exactly
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.
Just to be sure the maths explanation is clear:
M⋅V where M is 4x4 can be summarized as VMatrix1⋅VColor + VMatrix2⋅VColor + VMatrix3⋅VColor + VMatrix4⋅VColor where VMatrix represents either the rows (VColor is 1x4) or columns (VColor is 4x1) of the matrix.
That result is the same as V⋅M, which would be VColor⋅VMatrix1 + VColor⋅VMatrix2 + VColor⋅VMatrix3 + VColor⋅VMatrix4, because V⋅V is commutative.
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.
Sure, I'm referring to matrix multiplication in general.
I'm not sure how feasible initialising row-major is when we also need the inverse of the matrix for reverse transforms, will see.