add Codec/StbImage

This commit is contained in:
falsycat 2022-11-13 17:41:02 +09:00
parent 9e51470b11
commit b6f0f9fa0a
2 changed files with 95 additions and 0 deletions

View File

@ -139,6 +139,7 @@ target_sources(nf7
file/audio_context.cc
file/audio_device.cc
file/codec_stbimage.cc
file/font_context.cc
file/font_face.cc
file/gl_obj.cc

94
file/codec_stbimage.cc Normal file
View File

@ -0,0 +1,94 @@
#include <filesystem>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include <stb_image.h>
#include "nf7.hh"
#include "common/generic_type_info.hh"
#include "common/node.hh"
#include "common/pure_node_file.hh"
namespace nf7 {
namespace {
class StbImage final : public nf7::Node::Lambda,
public std::enable_shared_from_this<StbImage> {
public:
static inline nf7::GenericTypeInfo<nf7::PureNodeFile<StbImage>> kType = {
"Codec/StbImage", {"nf7::DirItem"},
};
static inline const nf7::Node::Meta kMeta = {{"input"}, {"image", "error"},};
using nf7::Node::Lambda::Lambda;
void Handle(const nf7::Node::Lambda::Msg& in) noexcept override
try {
std::string npath;
uint8_t comp = 4;
if (in.value.isTuple()) {
npath = in.value.tuple("npath").string();
comp = in.value.
tupleOr("comp", static_cast<nf7::Value::Integer>(comp)).
integerOrScalar<uint8_t>();
} else {
npath = in.value.string();
}
env().ExecAsync(shared_from_this(), [=, this]() {
std::optional<nf7::Value> ret;
try {
ret = Exec(npath, comp);
} catch (nf7::Exception& e) {
log_->Error(e);
}
env().ExecSub(shared_from_this(), [this, in, ret]() {
if (ret) {
in.sender->Handle("image", *ret, shared_from_this());
} else {
in.sender->Handle("error", nf7::Value::Pulse {}, shared_from_this());
}
});
});
} catch (nf7::Exception& e) {
log_->Error(e);
}
nf7::Value Exec(const std::string& npath, uint8_t comp) {
if (comp <= 0 || 4 < comp) {
throw nf7::Exception {"invalid comp (0~4 are allwoed)"};
}
int w, h, actual_comp;
uint8_t* data = stbi_load(npath.c_str(), &w, &h, &actual_comp, comp);
if (!data) {
throw nf7::Exception {"failed to load image from "+npath};
}
if (comp != 0) {
actual_comp = comp;
}
const auto size =
static_cast<size_t>(w)*
static_cast<size_t>(h)*
static_cast<size_t>(actual_comp);
std::vector<uint8_t> buf(size);
std::memcpy(buf.data(), data, size);
stbi_image_free(data);
return std::vector<nf7::Value::TuplePair> {
{"buf", std::move(buf)},
{"w", static_cast<nf7::Value::Integer>(w)},
{"h", static_cast<nf7::Value::Integer>(h)},
{"comp", static_cast<nf7::Value::Integer>(actual_comp)},
};
;
}
std::shared_ptr<nf7::LoggerRef> log_;
static_assert(PureNodeFile_LoggerRef<StbImage>);
};
}
} // namespace nf7