Skip to content

feat: add Image pixel buffer and image I/O (PPM/EXR/PNG)#2

Open
mtao wants to merge 2 commits into
mainfrom
feature/image-and-io
Open

feat: add Image pixel buffer and image I/O (PPM/EXR/PNG)#2
mtao wants to merge 2 commits into
mainfrom
feature/image-and-io

Conversation

@mtao
Copy link
Copy Markdown
Owner

@mtao mtao commented Mar 28, 2026

Summary

Implements Phase 3 of the ART viewer plan: a real pixel buffer and image I/O infrastructure.

art::Image (PBRT Film-style pixel buffer)

  • Direct pixel access (set_pixel/pixel) and weighted sample accumulation (add_sample/resolved_pixel)
  • Bulk operations: set_scanline, set_tile, pixels() span, raw_pixels()
  • Atomic progress tracking (increment_progress/pixels_completed/progress_fraction)
  • Atomic dirty tracking (version() + set_on_update() callback)
  • Tone-mapped conversion (to_rgba8 with exposure/gamma)
  • Move-only semantics (explicit move ctor/assignment due to std::atomic members)
  • 21 test cases, 246 assertions

Camera::render() → Image

  • No longer prints ASCII to stdout
  • Creates Image(nx, ny), writes white pixels for hits, black for misses
  • Calls increment_progress() per pixel

Image I/O

  • Generic art::io::load()/art::io::save() dispatch on file extension (Auto mode) or explicit ImageFormat enum
  • PPM: always available, no dependencies (P6 binary load + tone-mapped save)
  • EXR: optional via -Dexr=true (tinyexr subproject wrap with miniz)
  • PNG: optional via -Dpng=true (stb_image/stb_image_write subproject wrap)
  • Format stubs return descriptive error when support not compiled
  • has_exr_support() / has_png_support() / has_ppm_support() queries
  • Roundtrip tests for all three formats (EXR/PNG tests SKIP when not compiled)

Build

  • Default build (no I/O libs): 31 test cases, 274 assertions, 2 skipped
  • Full build (-Dexr=true -Dpng=true): 31 test cases, 292 assertions, 0 skipped

Implement Phase 3 of the ART viewer plan:

- art::Image: PBRT Film-style pixel buffer with direct pixel access,
  weighted sample accumulation, bulk set (scanline/tile), progress
  tracking (atomic), dirty notification (version + callback), and
  tone-mapped RGBA8 conversion. Move-only due to std::atomic members.

- Camera::render() now produces Image pixels (white for hits, black
  for misses) instead of printing ASCII to stdout.

- Image I/O with generic load()/save() dispatch on file extension:
  - PPM: always available, no dependencies (P6 binary format)
  - EXR: optional via -Dexr=true (tinyexr subproject wrap)
  - PNG: optional via -Dpng=true (stb_image subproject wrap)

- 31 test cases (292 assertions with all I/O enabled, 274 without)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant