Skip to content

Commit

Permalink
New cross-language example snippet better demonstrating image formats (
Browse files Browse the repository at this point in the history
…#7785)

### What


![full](https://github.com/user-attachments/assets/70208860-ee0c-4196-aa2c-860e39dbe889)

* Fixes #7691

Also unearthed a snippet that showed use with PIL & OpenCV which we
didn't reference so far 😱 . Overlapping, but still useful on its own, so
I put it into our docs as well!

### Checklist
* [x] pass main ci
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/7785?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/7785?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!
* [x] If have noted any breaking changes to the log API in
`CHANGELOG.md` and the migration guide

- [PR Build Summary](https://build.rerun.io/pr/7785)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
  • Loading branch information
Wumpf authored Oct 17, 2024
1 parent d50e9e0 commit 26ccb83
Show file tree
Hide file tree
Showing 10 changed files with 261 additions and 126 deletions.
3 changes: 2 additions & 1 deletion crates/store/re_types/definitions/rerun/archetypes/image.fbs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ namespace rerun.archetypes;
/// \cpp If needed, this "borrow-behavior" can be extended by defining your own `rerun::CollectionAdapter`.
///
/// \example archetypes/image_simple image="https://static.rerun.io/image_simple/06ba7f8582acc1ffb42a7fd0006fad7816f3e4e4/1200w.png"
/// \example archetypes/image_send_columns title="Advanced usage of `send_columns` to send multiple images at once" image="https://static.rerun.io/image_send_columns/321455161d79e2c45d6f5a6f175d6f765f418897/1200w.png"
/// \example archetypes/image_formats title="Logging images with various formats" image="https://static.rerun.io/image_formats/7b8a162fcfd266f303980439beea997dc8544c24/full.png"
/// \example archetypes/image_send_columns !api title="Image from file, PIL & OpenCV" image="https://static.rerun.io/image_advanced/81fc8a255488615510790ee41be314e054978d51/full.png"
table Image (
"attr.rust.derive": "PartialEq",
"attr.cpp.no_field_ctors",
Expand Down
90 changes: 44 additions & 46 deletions crates/store/re_types/src/archetypes/image.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 10 additions & 6 deletions docs/content/reference/types/archetypes/image.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 2 additions & 4 deletions docs/snippets/all/archetypes/image_advanced.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,11 @@
image = np.array(PILImage.open(file_path))
rr.log("from_pillow_rgba", rr.Image(image))

# Convert to RGB, fill transparent pixels with a color, and log the image.
# Drop the alpha channel from the image.
image_rgb = image[..., :3]
image_rgb[image[:, :, 3] == 0] = (45, 15, 15)
rr.log("from_pillow_rgb", rr.Image(image_rgb))

# Read with OpenCV
# Read with OpenCV.
image = cv2.imread(file_path)

# OpenCV uses BGR ordering, we need to make this known to Rerun.
rr.log("from_opencv", rr.Image(image, color_model="BGR"))
64 changes: 64 additions & 0 deletions docs/snippets/all/archetypes/image_formats.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include <algorithm>
#include <cstdint>
#include <vector>

#include <rerun.hpp>

int main() {
const auto rec = rerun::RecordingStream("rerun_example_image_formats");
rec.spawn().exit_on_failure();

// Simple gradient image
std::vector<uint8_t> image(256 * 256 * 3);
for (size_t y = 0; y < 256; ++y) {
for (size_t x = 0; x < 256; ++x) {
image[(y * 256 + x) * 3 + 0] = static_cast<uint8_t>(x);
image[(y * 256 + x) * 3 + 1] = static_cast<uint8_t>(std::min<size_t>(255, x + y));
image[(y * 256 + x) * 3 + 2] = static_cast<uint8_t>(y);
}
}

// RGB image
rec.log("image_rgb", rerun::Image::from_rgb24(image, {256, 256}));

// Green channel only (Luminance)
std::vector<uint8_t> green_channel(256 * 256);
for (size_t i = 0; i < 256 * 256; ++i) {
green_channel[i] = image[i * 3 + 1];
}
rec.log(
"image_green_only",
rerun::Image(rerun::borrow(green_channel), {256, 256}, rerun::ColorModel::L)
);

// BGR image
std::vector<uint8_t> bgr_image(256 * 256 * 3);
for (size_t i = 0; i < 256 * 256; ++i) {
bgr_image[i * 3 + 0] = image[i * 3 + 2];
bgr_image[i * 3 + 1] = image[i * 3 + 1];
bgr_image[i * 3 + 2] = image[i * 3 + 0];
}
rec.log(
"image_bgr",
rerun::Image(rerun::borrow(bgr_image), {256, 256}, rerun::ColorModel::BGR)
);

// New image with Separate Y/U/V planes with 4:2:2 chroma downsampling
std::vector<uint8_t> yuv_bytes(256 * 256 + 128 * 256 * 2);
std::fill_n(yuv_bytes.begin(), 256 * 256, static_cast<uint8_t>(128)); // Fixed value for Y
size_t u_plane_offset = 256 * 256;
size_t v_plane_offset = u_plane_offset + 128 * 256;
for (size_t y = 0; y < 256; ++y) {
for (size_t x = 0; x < 128; ++x) {
auto coord = y * 128 + x;
yuv_bytes[u_plane_offset + coord] = static_cast<uint8_t>(x * 2); // Gradient for U
yuv_bytes[v_plane_offset + coord] = static_cast<uint8_t>(y); // Gradient for V
}
}
rec.log(
"image_yuv422",
rerun::Image(rerun::borrow(yuv_bytes), {256, 256}, rerun::PixelFormat::Y_U_V16_FullRange)
);

return 0;
}
18 changes: 18 additions & 0 deletions docs/snippets/all/archetypes/image_formats.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"""Create and log an image with various formats."""

import numpy as np
import rerun as rr

rr.init("rerun_example_image_formats", spawn=True)

# Simple gradient image, logged in different formats.
image = np.array([[[x, min(255, x + y), y] for x in range(0, 256)] for y in range(0, 256)], dtype=np.uint8)
rr.log("image_rgb", rr.Image(image))
rr.log("image_green_only", rr.Image(image[:, :, 1], color_model="l")) # Luminance only
rr.log("image_bgr", rr.Image(image[:, :, ::-1], color_model="bgr")) # BGR

# New image with Separate Y/U/V planes with 4:2:2 chroma downsampling
y = bytes([128 for y in range(0, 256) for x in range(0, 256)])
u = bytes([x * 2 for y in range(0, 256) for x in range(0, 128)]) # Half horizontal resolution for chroma.
v = bytes([y for y in range(0, 256) for x in range(0, 128)])
rr.log("image_yuv422", rr.Image(bytes=y + u + v, width=256, height=256, pixel_format=rr.PixelFormat.Y_U_V16_FullRange))
53 changes: 53 additions & 0 deletions docs/snippets/all/archetypes/image_formats.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
use rerun::external::ndarray;

fn main() -> Result<(), Box<dyn std::error::Error>> {
let rec = rerun::RecordingStreamBuilder::new("rerun_example_image_formats").spawn()?;

// Simple gradient image
let image = ndarray::Array3::from_shape_fn((256, 256, 3), |(y, x, c)| match c {
0 => x as u8,
1 => (x + y).min(255) as u8,
2 => y as u8,
_ => unreachable!(),
});

// RGB image
rec.log(
"image_rgb",
&rerun::Image::from_color_model_and_tensor(rerun::ColorModel::RGB, image.clone())?,
)?;

// Green channel only (Luminance)
rec.log(
"image_green_only",
&rerun::Image::from_color_model_and_tensor(
rerun::ColorModel::L,
image.slice(ndarray::s![.., .., 1]).to_owned(),
)?,
)?;

// BGR image
rec.log(
"image_bgr",
&rerun::Image::from_color_model_and_tensor(
rerun::ColorModel::BGR,
image.slice(ndarray::s![.., .., ..;-1]).to_owned(),
)?,
)?;

// New image with Separate Y/U/V planes with 4:2:2 chroma downsampling
let mut yuv_bytes = Vec::with_capacity(256 * 256 + 128 * 256 * 2);
yuv_bytes.extend(std::iter::repeat(128).take(256 * 256)); // Fixed value for Y.
yuv_bytes.extend((0..256).flat_map(|_y| (0..128).map(|x| x * 2))); // Gradient for U.
yuv_bytes.extend((0..256).flat_map(|y| std::iter::repeat(y as u8).take(128))); // Gradient for V.
rec.log(
"image_yuv422",
&rerun::Image::from_pixel_format(
[256, 256],
rerun::PixelFormat::Y_U_V16_FullRange,
yuv_bytes,
),
)?;

Ok(())
}
1 change: 1 addition & 0 deletions rerun_cpp/src/rerun.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ namespace rerun {
using datatypes::Float32;
using datatypes::KeypointPair;
using datatypes::Mat3x3;
using datatypes::PixelFormat;
using datatypes::Quaternion;
using datatypes::Rgba32;
using datatypes::RotationAxisAngle;
Expand Down
Loading

0 comments on commit 26ccb83

Please sign in to comment.