diff --git a/CMakeLists.txt b/CMakeLists.txt index bf4a9da..ffd686a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ project(ftxui ) option(FTXUI_QUIET "Set to ON for FTXUI to be quiet" OFF) -option(FTXUI_BUILD_EXAMPLES "Set to ON to build examples" OFF) +option(FTXUI_BUILD_EXAMPLES "Set to ON to build examples" ON) option(FTXUI_BUILD_DOCS "Set to ON to build docs" OFF) option(FTXUI_BUILD_TESTS "Set to ON to build tests" OFF) option(FTXUI_BUILD_TESTS_FUZZER "Set to ON to enable fuzzing" OFF) @@ -173,5 +173,21 @@ include(cmake/ftxui_export.cmake) include(cmake/ftxui_install.cmake) include(cmake/ftxui_package.cmake) +# --- Find OpenCV and add as a dependency --- +find_package(OpenCV REQUIRED) +include_directories(${OpenCV_INCLUDE_DIRS}) + +target_link_libraries(screen + PUBLIC ${OpenCV_LIBS} +) +target_link_libraries(dom + PUBLIC ${OpenCV_LIBS} +) +target_link_libraries(component + PUBLIC ${OpenCV_LIBS} +) + add_subdirectory(examples) add_subdirectory(doc) + + diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 953efa9..a47db46 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -14,6 +14,10 @@ endfunction(example) add_subdirectory(component) add_subdirectory(dom) +# Add the pixelate example +add_executable(pixelate ${CMAKE_CURRENT_SOURCE_DIR}/dom/pixelate.cpp) +target_link_libraries(pixelate PRIVATE dom) + if (EMSCRIPTEN) string(APPEND CMAKE_EXE_LINKER_FLAGS " -s ALLOW_MEMORY_GROWTH=1") target_link_options(component PUBLIC "SHELL: -s ALLOW_MEMORY_GROWTH=1") diff --git a/examples/dom/pixelate.cpp b/examples/dom/pixelate.cpp new file mode 100644 index 0000000..f43db1d --- /dev/null +++ b/examples/dom/pixelate.cpp @@ -0,0 +1,37 @@ +#include "ftxui/dom/canvas.hpp" +#include // for getchar +#include // for cos +#include // for Fit, canvas, operator|, border, Element +#include // for Pixel, Screen +#include // for vector, allocator + +#include "ftxui/dom/canvas.hpp" // for Canvas +#include "ftxui/dom/node.hpp" // for Render +#include "ftxui/screen/color.hpp" // for Color, Color::Red, Color::Blue, Color::Green, ftxui + +using namespace ftxui; +using namespace cv; + +int main(int argc, char* argv[]) { + if (argc != 2 && argc != 4) { + std::cerr << "Usage: " << argv[0] << " [width] [height]" << std::endl; + return 1; + } + + std::string image_path = argv[1]; + int width, height; + + if (argc == 4) { + width = std::stoi(argv[2]); + height = std::stoi(argv[3]); + } else { + // default-values + width = 100; + height = 50; + } + + // call static method + Canvas::DrawImageOnTerminal(image_path, width, height); + + return 0; +} diff --git a/include/ftxui/dom/canvas.hpp b/include/ftxui/dom/canvas.hpp index 5d33d67..214aed8 100644 --- a/include/ftxui/dom/canvas.hpp +++ b/include/ftxui/dom/canvas.hpp @@ -12,6 +12,8 @@ #include "ftxui/screen/color.hpp" // for Color #include "ftxui/screen/image.hpp" // for Pixel, Image +#include //for OpenCV + #ifdef DrawText // Workaround for WinUsr.h (via Windows.h) defining macros that break things. // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-drawtext @@ -106,6 +108,10 @@ struct Canvas { // y is considered to be a multiple of 4. void Style(int x, int y, const Stylizer& style); + static void DrawImageOnTerminal(const std::string& image_path, int width = 80, int height = 24); + + + private: bool IsIn(int x, int y) const { return x >= 0 && x < width_ && y >= 0 && y < height_; diff --git a/src/ftxui/dom/canvas.cpp b/src/ftxui/dom/canvas.cpp index a78b894..d2e4b4e 100644 --- a/src/ftxui/dom/canvas.cpp +++ b/src/ftxui/dom/canvas.cpp @@ -20,6 +20,7 @@ #include "ftxui/screen/screen.hpp" // for Pixel, Screen #include "ftxui/screen/string.hpp" // for Utf8ToGlyphs #include "ftxui/util/ref.hpp" // for ConstRef +#include // for OpenCV namespace ftxui { @@ -861,6 +862,45 @@ void Canvas::Style(int x, int y, const Stylizer& style) { } } +/** + * @brief Places Dots on Canvas and prints it on Terminal + * @param image_path absolute path to image + * @param width number of Pixels on x-axis + * @param height number of Pixels on y-axis + */ + +void Canvas::DrawImageOnTerminal(const std::string& image_path, int width, int height) { + using namespace cv; + + // read image via OpenCV + Mat image = imread(image_path, IMREAD_COLOR); + if (image.empty()) { + std::cerr << "Could not read the image: " << image_path << std::endl; + return; + } + + // modify images dimensions + resize(image, image, Size(width, height)); + + Canvas c(width, height); + + // transfer images pixels onto canvas + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + Vec3b color = image.at(y, x); + c.DrawPoint(x, y, true, Color::RGB(color[2], color[1], color[0])); + } + } + + // render canvas as element + auto document = canvas(&c); + auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document)); + Render(screen, document); + screen.Print(); +} + + + namespace { class CanvasNodeBase : public Node {