Hi, I would like to get HDR pixel values output of the viewport buffer. In the viewport_thumbneil_generator example, a low dynamic range image is processed as RGBA.
try:
ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.POINTER(ctypes.c_byte * buffer_size)
ctypes.pythonapi.PyCapsule_GetPointer.argtypes = [ctypes.py_object, ctypes.c_char_p]
content = ctypes.pythonapi.PyCapsule_GetPointer(buffer, None)
except Exception as e: # pylint: disable=broad-except
carb.log_error(f"[Thumbnail] Failed to get capture buffer: {e}")
return
# Crop and down sample
data = self._generate_thumbnail_data(content.contents, (width, height))
I can use this to get the pixel values from the buffer.
image_array = np.frombuffer(raw_data, dtype=np.uint8)
If I use capture_viewport_to_buffer(camera_viewport, on_viewport_captured, True) to get the HDR to the buffer, how do I get the pixel values, how many bits for each pixel?
The RTX Renderer works natively in High Dynamic Range full 32bit float. It will only write 8bit when asked to. The buffer will be in 32bit. If you ask it to write out to EXRs, it will stay in 32bit.
Thank you Richard, would it be possible to give an example on how to read HDR to the buffer? I used viewport utility function and use Ture for is_hdr flag: capture_viewport_to_buffer(camera_viewport, on_viewport_captured, True)
But it seems the callback is never reached.
Hi Richard, Thank you very much for the example. It works great! I tried to get the number of bytes and use it in the main but some how it keeps freezing Omniverse. Any suggestions?
import omni.kit.app
from omni.kit.viewport.utility import get_active_viewport, capture_viewport_to_buffer
import asyncio
import carb
# Global variable to store the number of bytes
captured_num_bytes = 0
# Event to signal when capture is complete
capture_complete_event = asyncio.Event()
async def capture_viewport_buffer(viewport_api, in_capture_callback, is_hdr: bool = False, wait_frames: int = 3):
is_hdr = bool(is_hdr)
capture_callback = in_capture_callback
hdr_setting_path = "/app/captureFrame/hdr"
settings = carb.settings.get_settings()
prev_is_hdr = bool(settings.get(hdr_setting_path))
if prev_is_hdr != is_hdr:
settings.set(hdr_setting_path, is_hdr)
app = omni.kit.app.get_app()
for _ in range(max(1, wait_frames)):
await app.next_update_async()
# Wrap capture-callback in a local version that puts
def capture_wrapper(*args, **kwargs):
settings.set(hdr_setting_path, prev_is_hdr)
in_capture_callback(*args, **kwargs)
capture_callback = capture_wrapper
capture_viewport_to_buffer(viewport_api, capture_callback, is_hdr=is_hdr)
def capture_callback(capsule_bytes, num_bytes, width, height, byte_format, *args, **kwargs):
global captured_num_bytes
expected_num_bytes = 0
if byte_format == byte_format.RGBA16_SFLOAT:
expected_num_bytes = width * height * 4 * 2
elif byte_format == byte_format.RGBA8_UNORM:
expected_num_bytes = width * height * 4 * 1
print("width", width)
print("height", height)
print("byte_format", byte_format)
print("num_bytes", num_bytes)
print("expected_num_bytes", expected_num_bytes)
assert num_bytes == expected_num_bytes
# Store the number of bytes in the global variable
captured_num_bytes = num_bytes
# Set the event to signal that capture is complete
capture_complete_event.set()
async def capture():
# Start the capture process
await capture_viewport_buffer(get_active_viewport(), capture_callback, is_hdr=True)
# Wait for the capture to complete
await capture_complete_event.wait()
# Run the main function and wait for it to complete
asyncio.run(capture())
# Print the captured number of bytes after the main function completes
print("Captured number of bytes:", captured_num_bytes)
asyncio.ensure_future does NOT seem to wait for the capture to finish. Is there a way to wait for the capture() to finish so I could use the updated global variable? Many thanks.