summaryrefslogtreecommitdiffhomepage
path: root/anim-crop-tool
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2022-09-30 18:55:15 +0200
committerStanislaw Halik <sthalik@misaki.pl>2022-09-30 18:55:15 +0200
commit5ee36284ab2f2d85679f83ad7680a741bf7f6702 (patch)
tree825566e0a21b6b7b8d0ad3f81880ebe4c3f3ce3d /anim-crop-tool
parentc7ce9f57f53325e47574bf0fcdaa495146656289 (diff)
.
Diffstat (limited to 'anim-crop-tool')
-rw-r--r--anim-crop-tool/CMakeLists.txt10
-rw-r--r--anim-crop-tool/atlas.cpp63
-rw-r--r--anim-crop-tool/atlas.hpp37
3 files changed, 110 insertions, 0 deletions
diff --git a/anim-crop-tool/CMakeLists.txt b/anim-crop-tool/CMakeLists.txt
new file mode 100644
index 00000000..7b6d22a8
--- /dev/null
+++ b/anim-crop-tool/CMakeLists.txt
@@ -0,0 +1,10 @@
+find_package(OpenCV QUIET REQUIRED COMPONENTS core imgcodecs imgproc)
+set(self "${PROJECT_NAME}-anim-crop-tool")
+
+include_directories(SYSTEM PRIVATE ${OpenCV_INCLUDE_DIRS})
+link_libraries(Corrade::Utility)
+link_libraries(${PROJECT_NAME}-anim)
+
+file(GLOB sources "*.cpp" CONFIGURE_ARGS)
+add_executable(${self} ${sources})
+install(TARGETS ${self} RUNTIME DESTINATION "bin")
diff --git a/anim-crop-tool/atlas.cpp b/anim-crop-tool/atlas.cpp
new file mode 100644
index 00000000..a588ff3c
--- /dev/null
+++ b/anim-crop-tool/atlas.cpp
@@ -0,0 +1,63 @@
+#undef NDEBUG
+
+#include "atlas.hpp"
+#include "anim/serialize.hpp"
+
+#include <cassert>
+#include <filesystem>
+#include <opencv2/imgcodecs.hpp>
+
+void anim_atlas_row::add_entry(const anim_atlas_entry& x) noexcept
+{
+ auto& frame = *x.frame;
+ const auto& mat = x.mat;
+ frame.offset = {xpos, ypos};
+ frame.size = {mat.cols, mat.rows};
+
+ assert(mat.rows > 0 && mat.cols > 0);
+ data.push_back(x);
+ xpos += mat.cols;
+ max_height = std::max(mat.rows, max_height);
+}
+
+void anim_atlas::advance_row() noexcept
+{
+ auto& row = rows.back();
+ if (row.data.empty())
+ return;
+ assert(row.xpos); assert(row.max_height);
+ ypos += row.max_height;
+ maxx = std::max(row.xpos, maxx);
+ rows.push_back({{}, 0, 0, ypos});
+}
+
+Magnum::Vector2i anim_atlas::offset() const noexcept
+{
+ const auto& row = rows.back();
+ return {row.xpos, row.ypos};
+}
+
+Magnum::Vector2i anim_atlas::size() const noexcept
+{
+ const anim_atlas_row& row = rows.back();
+ // prevent accidentally writing out of bounds by forgetting to call
+ // anim_atlas::advance_row() one last time prior to anim_atlas::size()
+ return {std::max(maxx, row.xpos), ypos + row.max_height};
+}
+
+bool anim_atlas::dump(const std::filesystem::path& filename) const noexcept
+{
+ auto sz = size();
+ cv::Mat4b mat(sz[1], sz[0]);
+ mat.setTo(0);
+
+ for (const anim_atlas_row& row : rows)
+ for (const anim_atlas_entry& x : row.data)
+ {
+ auto offset = x.frame->offset, size = x.frame->size;
+ cv::Rect roi = {offset[0], offset[1], size[0], size[1]};
+ x.mat.copyTo(mat(roi));
+ }
+
+ return cv::imwrite(filename.string(), mat);
+}
diff --git a/anim-crop-tool/atlas.hpp b/anim-crop-tool/atlas.hpp
new file mode 100644
index 00000000..5c5e918f
--- /dev/null
+++ b/anim-crop-tool/atlas.hpp
@@ -0,0 +1,37 @@
+#pragma once
+
+#include <vector>
+#include <Magnum/Magnum.h>
+#include <Magnum/Math/Vector2.h>
+#include <opencv2/core/mat.hpp>
+
+struct anim_frame;
+
+namespace std::filesystem { class path; }
+
+struct anim_atlas_entry
+{
+ anim_frame* frame;
+ cv::Mat4b mat;
+};
+
+struct anim_atlas_row
+{
+ std::vector<anim_atlas_entry> data;
+ int max_height = 0, xpos = 0, ypos = 0;
+
+ void add_entry(const anim_atlas_entry& x) noexcept;
+};
+
+class anim_atlas
+{
+ std::vector<anim_atlas_row> rows = {{}};
+ int ypos = 0, maxx = 0;
+
+public:
+ void add_entry(const anim_atlas_entry& x) noexcept { rows.back().add_entry(x); }
+ void advance_row() noexcept;
+ Magnum::Vector2i offset() const noexcept;
+ Magnum::Vector2i size() const noexcept;
+ [[nodiscard]] bool dump(const std::filesystem::path& filename) const noexcept;
+};