|
15 | 15 | // std
|
16 | 16 | #include <chrono>
|
17 | 17 | #include <cstring>
|
| 18 | +#include <filesystem> |
| 19 | +#include <iomanip> |
18 | 20 | #include <limits>
|
| 21 | +#include <sstream> |
| 22 | +// stb |
| 23 | +#define STB_IMAGE_WRITE_IMPLEMENTATION |
| 24 | +#include "stb_image_write.h" |
19 | 25 |
|
20 | 26 | namespace tsd::ui::imgui {
|
21 | 27 |
|
@@ -610,6 +616,53 @@ void Viewport::updateImage()
|
610 | 616 | m_latestAnariFL = duration * 1000;
|
611 | 617 | m_minFL = std::min(m_minFL, m_latestAnariFL);
|
612 | 618 | m_maxFL = std::max(m_maxFL, m_latestAnariFL);
|
| 619 | + |
| 620 | + // Handle screenshot saving |
| 621 | + if (m_saveNextFrame) { |
| 622 | + // Wait for the frame to be ready |
| 623 | + anari::wait(m_device, frame); |
| 624 | + |
| 625 | + // Map the color channel to get the frame buffer data |
| 626 | + auto fb = anari::map<uint32_t>(m_device, frame, "channel.color"); |
| 627 | + |
| 628 | + if (fb.data) { |
| 629 | + // Generate timestamped filename |
| 630 | + auto now = std::chrono::system_clock::now(); |
| 631 | + auto time_t = std::chrono::system_clock::to_time_t(now); |
| 632 | + auto ms = std::chrono::duration_cast<std::chrono::milliseconds>( |
| 633 | + now.time_since_epoch()) |
| 634 | + % 1000; |
| 635 | + |
| 636 | + std::stringstream ss; |
| 637 | + ss << "screenshot_" |
| 638 | + << std::put_time(std::localtime(&time_t), "%Y%m%d_%H%M%S") << "_" |
| 639 | + << std::setfill('0') << std::setw(3) << ms.count() << ".png"; |
| 640 | + |
| 641 | + // Ensure the screenshot is saved in the current working directory |
| 642 | + std::filesystem::path workingDir = std::filesystem::current_path(); |
| 643 | + std::filesystem::path filename = workingDir / ss.str(); |
| 644 | + |
| 645 | + // Use STB's built-in vertical flip functionality for simplicity |
| 646 | + stbi_flip_vertically_on_write(1); |
| 647 | + |
| 648 | + // Save the screenshot with full alpha channel preservation |
| 649 | + stbi_write_png( |
| 650 | + filename.c_str(), fb.width, fb.height, 4, fb.data, 4 * fb.width); |
| 651 | + |
| 652 | + // Reset the flip setting to avoid affecting other code |
| 653 | + stbi_flip_vertically_on_write(0); |
| 654 | + |
| 655 | + tsd::core::logStatus( |
| 656 | + "Screenshot saved to '%s'", filename.string().c_str()); |
| 657 | + } else { |
| 658 | + tsd::core::logWarning("Failed to map frame buffer for screenshot"); |
| 659 | + } |
| 660 | + |
| 661 | + // Unmap the frame buffer |
| 662 | + anari::unmap(m_device, frame, "channel.color"); |
| 663 | + |
| 664 | + m_saveNextFrame = false; |
| 665 | + } |
613 | 666 | }
|
614 | 667 |
|
615 | 668 | void Viewport::echoCameraConfig()
|
|
0 commit comments