blocky/playground/input_imgseq.cc
2022-06-22 11:48:52 +09:00

97 lines
2.1 KiB
C++

#include <string>
#include <numeric>
#include <vector>
#include <imgui.h>
#include <imgui_stdlib.h>
#include "app.hh"
#include "input.hh"
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
namespace pg {
namespace {
class ImgSeq final : public App, public Input::Data {
public:
static inline TypeInfo kType = TypeInfo::Create<ImgSeq>("Input_ImgSeq");
ImgSeq() noexcept : Data("imgseq") {
}
~ImgSeq() noexcept {
DropCache();
}
void DropCache() noexcept {
for (auto& frame : frames_) {
stbi_image_free(const_cast<uint8_t*>(frame.second.rgba));
}
frames_.clear();
}
void Update() noexcept override {
const auto id = std::to_string(index())+" Input_ImgSeq | "+
std::to_string(reinterpret_cast<uintptr_t>(this));
if (ImGui::Begin(id.c_str())) {
bool mod = false;
mod |= ImGui::InputText("dir", &path_);
mod |= ImGui::DragInt("start", &st_, 1, 0, 1024);
mod |= ImGui::DragInt("end", &ed_, 1, 0, 1024);
if (mod) DropCache();
if (msg_.size() > 0) {
ImGui::TextUnformatted(msg_.c_str());
}
}
ImGui::End();
}
Frame Fetch(size_t n) noexcept override
try {
n += static_cast<size_t>(st_);
if (n >= static_cast<size_t>(ed_)) {
throw "frame number out of range";
}
auto itr = frames_.find(n);
if (itr != frames_.end()) return itr->second;
const auto fname = path_+"/"+std::to_string(n)+".png";
int w, h, comp;
uint8_t* buf = stbi_load(fname.c_str(), &w, &h, &comp, 4);
if (buf == nullptr) {
throw stbi_failure_reason();
}
const Frame ret = {
.w = static_cast<size_t>(w),
.h = static_cast<size_t>(h),
.rgba = buf,
};
frames_[n] = ret;
return ret;
} catch (const char* msg) {
msg_ = msg;
return {.w = 0, .h = 0, .rgba = nullptr};
}
size_t frames() noexcept override {
if (ed_ <= st_) return 0;
return static_cast<size_t>(ed_-st_);
}
private:
std::string path_;
int st_ = 1, ed_ = 100;
std::string msg_;
std::unordered_map<size_t, Frame> frames_;
};
}
} // namespace pg