Repository navigation
perf: faster JPEG streaming (zero-copy VTK capture, 4:2:0 turbo-jpeg) #65
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鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| import json | ||
|
|
||
| import numpy as np | ||
| import vtkmodules.vtkRenderingOpenGL2 # noqa | ||
| from packaging.version import Version | ||
| from trame_common.utils import profiler | ||
|
|
@@ -27,6 +28,7 @@ def __init__(self, vtk_render_window: vtkRenderWindow): | |
| self._window_to_image.ReadFrontBufferOff() | ||
| self._window_to_image.ShouldRerenderOff() | ||
| self._window_to_image.FixBoundaryOn() | ||
| self._window_to_image.SetInputBufferTypeToRGBA() | ||
|
|
||
| @property | ||
| def img_cols_rows(self): | ||
|
|
@@ -40,7 +42,10 @@ def img_cols_rows(self): | |
| scalars = image_data.GetPointData().GetScalars() | ||
| np_image = vtk_to_numpy(scalars) | ||
| np_image = np_image.reshape((rows, cols, -1)) | ||
| np_image[:] = np_image[::-1, :, :] | ||
| # Flip into a new RGBA buffer and return its RGB channels as a view: | ||
| # VTK's alpha is 0 on the background, and the encoders can read the | ||
| # 4-byte pixels in place (see encoders.img.rgbx_view) | ||
| np_image = np.ascontiguousarray(np_image[::-1])[..., :3] | ||
|
Contributor
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. This would be the wrong place to put this. If rgbx_view needs a contiguous array, then it can be put in the specific code and not leak here.
Contributor
Author
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. I can drop this and simply do: np_image = np_image[::-1, :, :3]Is that acceptable?
Contributor
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. There shouldn't be any changes to what the VTK side returns as this would break the current contract and break any other users accessing the data and expecting the current format. If you need this change it would be better to move it inside rgbx_view instead. This way it will only afect this specific code path and not others. On a side note, I will test your branch on real projects before accepting anything, but I'm concerned the changes in this file may be an hallucination and may flip the render window / flip the color space. The tests in trame-rca are not remotely complete and just checking a grey cone doesn't inform if you have completely flipped what you wanted to display.
Contributor
Author
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. I can move it. I understand your concerns. This is why I don't blindly ask Claude to do things without my input and without review first. I only pushed two commits for this PR, but that's because my understanding is kitware does not typically use squash+merge, and so the commits should stand on their own, ready to be integrated as-is directly into the main branch. And so locally my development branch initially had many commits, iterated upon by me after much back-and-forth with Claude, and then at the end I rewrote history and force-pushed just the two commits. There is lots of local benchmarking and visual testing, as well as testing with If you'd prefer, next time I can add commits without a force-push, and then you can squash+merge into main? What is the standard here for this repo?
Collaborator
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. I like to have isolated commit (rather than a big squash), that way the release notes point to each step/goal and it is easier to track. But if a PR is small enough and does not tackle 2+ things at once, then it can be squashed. For me the split you did in your commits were perfect.
Contributor
Author
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.
I added image orientation tests as part of #66. That should help give confidence here that this PR doesn't break anything. Please review #66 first.
Contributor
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. Thanks @user27182, I reviewed #65 and added a small request on git history. You may want to relax the tests in #65 to avoid having to fix them just after in this PR.
Contributor
Author
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.
Contributor
Author
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.
# master: copy the flipped rows back into VTK's own buffer
np_image[:] = np_image[::-1, :, :]
# this PR: copy the flipped rows into a new buffer
np_image = np.ascontiguousarray(np_image[::-1])Both make the rows top-down. This PR does it with one copy instead of two (NumPy buffers the overlapping in-place assignment through a temporary), and no longer writes into VTK's buffer.
Agreed that the existing contract should not be broken, and this PR does change the layout of the returned array, though not the values. To let the encoders read 4-byte pixels in place, it captures RGBA and returns the RGB channels as a view ( That only matters to code that reads the array's raw memory as packed RGB, e.g. The layout change is what makes the zero-copy path possible: with packed RGB,
|
||
| return np_image, cols, rows | ||
|
|
||
| @property | ||
|
|
||
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 added another comment in the vtk_rca.py, but since the RGBX contiguous view is only required by this function, please move the conversion scope inside this function directly and remove this comment
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 confirm, you want this function moved to
vtk_rca.py, is that correct?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.
No, I meant that this function should be moved to the turbo_jpeg.py file.
If your change provides any performance update to the PIL code path, then it can stay here, but if not, I would rather this stays an implementation detail of the turbo_jpeg encoding to avoid any unwanted side effects in the PIL case.
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.
rgbx_view applies to both encoders though. For simplicity, if you prefer, I can make this PR Pillow-only, and drop all turbo-jpeg changes, and move
rgbx_viewintopil.pyinstead. That should make the implementation and tests a lot clearer in scope.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.
My bad, I had missread the commit messages.
I still think the changes should be scoped to pil and turbo_jpeg encodings as any other changes to the VTK RCA img to row may break the current contract of what the method returns.
So this method can stay here, the comment still needs to be updated.