Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c1ca09d
Add initial project structure and stb_image_data_view wrapper.
ariyapour Apr 15, 2024
ceb8a8a
Add stb_image_data_view class and definitions
ariyapour Apr 16, 2024
182f80e
Add drawer and image classes. Now we can load an image and draw it in…
ariyapour Apr 19, 2024
01f381c
Add the pixelation functionality.
ariyapour Apr 19, 2024
ddf503c
Clean up debug code. Minor style changes.
ariyapour Apr 19, 2024
cb170ad
Add test for pixelate_image.
ariyapour Apr 19, 2024
4a75d00
Add fixed size drawer test for pixelate_image_test.
ariyapour Apr 19, 2024
a1522e5
Add tests for image_tests stb_image_data_view_test and modify drawer_…
ariyapour Apr 19, 2024
d017a7c
Add grumpy.png image to the repository in test_data.
ariyapour Apr 19, 2024
0d6d152
Create a new test data.
ariyapour Apr 19, 2024
23dc26f
Update git ignore.
ariyapour Apr 19, 2024
2e717f6
Remove test data. Issue in pixelator test when running tests in pull …
ariyapour Apr 20, 2024
06d28c5
Add new test data. Move global test variables to a header file.
ariyapour Apr 20, 2024
f474ac9
Add debug info to pixelator tests.
ariyapour Apr 21, 2024
e194f33
Use drawer.Draw() i pixelator test to see if the issue fixes.
ariyapour Apr 21, 2024
3a588f9
Cast to integer in pixelator to see the failing test in github action…
ariyapour Apr 21, 2024
7b94994
Add more debug option for pixelator test.
ariyapour Apr 21, 2024
3da0d50
Add more debug infor to fix github pixelator fix
ariyapour Apr 21, 2024
ef0bd25
Debug info
ariyapour Apr 21, 2024
5d3e91b
Change the pixelator test.
ariyapour Apr 21, 2024
76621cf
Change pixelator test so that it does not use a drawer but compares i…
ariyapour Apr 21, 2024
0fc4bef
Add some of the missing functionalities in drawer and image.
ariyapour Apr 21, 2024
29c38d4
Fix an issue in naming of Color struct
ariyapour Apr 21, 2024
ff0d01e
Chenge algorithms to make tests work. Initial implementation was to a…
ariyapour Apr 21, 2024
d07ae9d
Fix a size problem. Add clang-format
ariyapour Apr 21, 2024
78fa91e
Add clean ups
ariyapour Apr 21, 2024
195ed10
Change Image initialization
ariyapour Apr 21, 2024
b1bac13
Remove new line characters from end of the drawer.ToString() strings.
ariyapour Apr 22, 2024
ec617e9
Add space to the list of characters to be removed from drawer.ToStrin…
ariyapour Apr 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
[submodule "homeworks/homework_4/no_strings_attached/external/googletest"]
path = homeworks/homework_4/no_strings_attached/external/googletest
url = https://github.com/google/googletest.git
[submodule "homeworks/homework_5/pixelator/external/ftxui"]
path = homeworks/homework_5/pixelator/external/ftxui
url = https://github.com/ArthurSonzogni/FTXUI.git
[submodule "homeworks/homework_5/pixelator/external/googletest"]
path = homeworks/homework_5/pixelator/external/googletest
url = https://github.com/google/googletest.git
[submodule "homeworks/homework_5/pixelator/external/stb"]
path = homeworks/homework_5/pixelator/external/stb
url = https://github.com/nothings/stb.git
27 changes: 27 additions & 0 deletions homeworks/homework_5/pixelator/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
cmake_minimum_required(VERSION 3.16..3.24)
project(pixelator VERSION 1
DESCRIPTION "Pixelate images in terminal"
LANGUAGES CXX)

if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING "" FORCE)
endif()

message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")

# Create a pseudo-library to propagate the needed flags.
add_library(cxx_setup INTERFACE)
target_compile_options(cxx_setup INTERFACE -Wall -Wpedantic -Wextra)
target_compile_features(cxx_setup INTERFACE cxx_std_17)
target_include_directories(cxx_setup INTERFACE ${PROJECT_SOURCE_DIR})

# Update the submodules here
include(external/UpdateSubmodules.cmake)

# Enable testing for this project
include(CTest)

# Add code in subdirectories
add_subdirectory(external)
add_subdirectory(${PROJECT_NAME})
add_subdirectory(examples)
11 changes: 11 additions & 0 deletions homeworks/homework_5/pixelator/examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
add_executable(use_ftxui use_ftxui.cpp)
target_link_libraries(use_ftxui PRIVATE cxx_setup ftxui::screen)

add_executable(use_stb_image use_stb_image.cpp)
target_link_libraries(use_stb_image PRIVATE cxx_setup stb::stb)

add_executable(pixelate pixelate.cpp)
target_link_libraries(pixelate PRIVATE cxx_setup stb_image_data_view drawer pixelate_image)

# TODO: Add your binaries here
# There must be a binary `pixelate` here
28 changes: 28 additions & 0 deletions homeworks/homework_5/pixelator/examples/pixelate.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include "pixelator/drawer.hpp"
#include "pixelator/pixelate_image.hpp"
#include "pixelator/stb_image_data_view.hpp"

#include <cstddef>
#include <filesystem>
#include <utility>
namespace {
using pixelator::Drawer;
using pixelator::PixelateImage;
using pixelator::StbImageDataView;
} // namespace

int main(int argc, char **argv) {
if (argc < 2) { std::cerr << "No image provided." << std::endl; }

StbImageDataView image{argv[1]};
if (image.empty()) {
std::cerr << "Image could not be loaded" << std::endl;
exit(1);
}

Drawer drawer{ftxui::Dimension::Full()};

drawer.Set(PixelateImage(image, drawer.size()));
drawer.Draw();
return 0;
}
19 changes: 19 additions & 0 deletions homeworks/homework_5/pixelator/examples/use_ftxui.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include "ftxui/screen/color.hpp"
#include "ftxui/screen/screen.hpp"

namespace {
const ftxui::Color kYellowishColor = ftxui::Color::RGB(255, 200, 100);
}

int main() {
const ftxui::Dimensions dimensions{ftxui::Dimension::Full()};
ftxui::Screen screen{ftxui::Screen::Create(dimensions)};
auto &pixel_left = screen.PixelAt(10, 10);
pixel_left.background_color = kYellowishColor;
pixel_left.character = ' ';
auto &pixel_right = screen.PixelAt(11, 10);
pixel_right.background_color = kYellowishColor;
pixel_right.character = ' ';
screen.Print();
return 0;
}
64 changes: 64 additions & 0 deletions homeworks/homework_5/pixelator/examples/use_stb_image.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Make sure to have this in EXACTLY one cpp file
// The best place for this is the cpp file of your library
// that holds a class that wraps around the stb_image data
// For more see here: https://github.com/nothings/stb#faq
#define STB_IMAGE_IMPLEMENTATION
#include "stb/stb_image.h"

#include <filesystem>
#include <iostream>

namespace {
static constexpr auto kLoadAllChannels{0};

// A dummy color structure. Use ftxui::Color in actual code.
struct Color {
int red;
int green;
int blue;
};

} // namespace

int main(int argc, char **argv) {
if (argc < 2) { std::cerr << "No image provided.\n"; }
const std::filesystem::path image_path{argv[1]};
if (!std::filesystem::exists(image_path)) {
std::cerr << "No image file: " << image_path << std::endl;
std::exit(1);
}

// Load the data
int rows{};
int cols{};
int channels{};
// This call also populates rows, cols, channels.
auto image_data{
stbi_load(image_path.c_str(), &cols, &rows, &channels, kLoadAllChannels)};
std::cout << "Loaded image of size: [" << rows << ", " << cols << "] with "
<< channels << " channels\n";
if (!image_data) {
std::cerr << "Failed to load image data from file: " << image_path
<< std::endl;
std::exit(1);
}

// The data is stored sequentially, in this order per pixel: red, green, blue,
// alpha This patterns repeats for every pixel of the image, so the resulting
// data layout is: [rgbargbargba...]
int query_row = 10;
int query_col = 15;
const auto index{channels * (query_row * cols + query_col)};
const Color color{
image_data[index], image_data[index + 1], image_data[index + 2]};
std::cout << "Color at pixel: [" << query_row << ", " << query_col
<< "] = RGB: (" << color.red << ", " << color.green << ", "
<< color.blue << ")\n";

// We must explicitly free the memory allocated for this image.
// The reason for this is that stb_image is a C library,
// which has no classes and no RAII in the form about which we talked before.
// Now you see why people want to write C++ and not C? ;)
stbi_image_free(image_data);
return 0;
}
3 changes: 3 additions & 0 deletions homeworks/homework_5/pixelator/external/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
include(gtest.cmake)
include(ftxui.cmake)
include(stb.cmake)
27 changes: 27 additions & 0 deletions homeworks/homework_5/pixelator/external/UpdateSubmodules.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
find_package(Git QUIET)

if(GIT_FOUND)
option(UPDATE_SUBMODULES "Check submodules during build" ON)

if(NOT UPDATE_SUBMODULES)
return()
endif()

execute_process(COMMAND ${GIT_EXECUTABLE} submodule
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE EXISTING_SUBMODULES
RESULT_VARIABLE RETURN_CODE)

message(STATUS "Updating git submodules:\n${EXISTING_SUBMODULES}")

execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
RESULT_VARIABLE RETURN_CODE)

if(NOT RETURN_CODE EQUAL "0")
message(WARNING "Cannot update submodules. Git command failed with ${RETURN_CODE}.")
return()
endif()

message(STATUS "Git submodules updated successfully.")
endif()
1 change: 1 addition & 0 deletions homeworks/homework_5/pixelator/external/ftxui
Submodule ftxui added at e03a07
4 changes: 4 additions & 0 deletions homeworks/homework_5/pixelator/external/ftxui.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
add_subdirectory(ftxui)
1 change: 1 addition & 0 deletions homeworks/homework_5/pixelator/external/googletest
Submodule googletest added at 5197b1
5 changes: 5 additions & 0 deletions homeworks/homework_5/pixelator/external/gtest.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(INSTALL_GTEST OFF)
add_subdirectory(googletest)
1 change: 1 addition & 0 deletions homeworks/homework_5/pixelator/external/stb
Submodule stb added at ae721c
5 changes: 5 additions & 0 deletions homeworks/homework_5/pixelator/external/stb.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
add_library(stb INTERFACE)
target_include_directories(stb INTERFACE ${PROJECT_SOURCE_DIR}/external/)
if (NOT TARGET stb::stb)
add_library(stb::stb ALIAS stb)
endif()
46 changes: 46 additions & 0 deletions homeworks/homework_5/pixelator/pixelator/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# TODO: Add your libraries here
# You must have the following libraries:
# - stb_image_data_view
# - drawer
# - image
# - pixelate_image

add_library(stb_image_data_view stb_image_data_view.cpp)
target_link_libraries(stb_image_data_view PUBLIC cxx_setup stb::stb ftxui::screen)

add_library(image image.cpp)
target_link_libraries(image PUBLIC cxx_setup ftxui::screen stb_image_data_view)

add_library(drawer drawer.cpp)
target_link_libraries(drawer PUBLIC cxx_setup ftxui::screen image)

add_library(pixelate_image INTERFACE)
target_link_libraries(pixelate_image INTERFACE image stb_image_data_view)

add_library(test_global_variables INTERFACE)
target_link_libraries(test_global_variables INTERFACE image)


if(BUILD_TESTING)
# TODO: Add your tests executable with all your tests here
# Name it pixelator_tests.
# Also use gtest_discover_tests(pixelator_tests)
# to register them with CTest
add_executable(pixelate_image_test pixelate_image_test.cpp)
target_link_libraries(pixelate_image_test PRIVATE pixelate_image test_global_variables GTest::gtest_main)

add_executable(drawer_test drawer_test.cpp)
target_link_libraries(drawer_test PRIVATE drawer GTest::gtest_main)

add_executable(image_test image_test.cpp)
target_link_libraries(image_test PRIVATE image GTest::gtest_main)

add_executable(stb_image_data_view_test stb_image_data_view_test.cpp)
target_link_libraries(stb_image_data_view_test PRIVATE stb_image_data_view test_global_variables GTest::gtest_main)

include(GoogleTest)
gtest_discover_tests(pixelate_image_test)
gtest_discover_tests(drawer_test)
gtest_discover_tests(image_test)
gtest_discover_tests(stb_image_data_view_test)
endif()
60 changes: 60 additions & 0 deletions homeworks/homework_5/pixelator/pixelator/drawer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include "pixelator/drawer.hpp"
#include <algorithm>
#include <iostream>

pixelator::Drawer::Drawer(const ftxui::Dimensions dimensions) {
if (dimensions.dimx == ftxui::Dimension::Full().dimx &&
dimensions.dimy == ftxui::Dimension::Full().dimy) {
rows_ = ftxui::Dimension::Full().dimx;
cols_ = ftxui::Dimension::Full().dimy;
} else {
rows_ = dimensions.dimx;
cols_ = rows_ * 2;
}
screen_ = ftxui::Screen::Create({rows_, cols_});
}

int pixelator::Drawer::rows() const { return rows_; }

int pixelator::Drawer::cols() const { return cols_; }

const pixelator::Size pixelator::Drawer::size() const {
return pixelator::Size{rows_, cols_};
}

void pixelator::Drawer::Set(pixelator::Image image) {
for (int i = 0; i < image.rows(); i++) {
for (int j = 0; j < image.cols(); j++) {
auto &pixel_left = screen_.PixelAt(j * 2, i);
pixel_left.background_color = image.at(i, j);
pixel_left.character = ' ';
auto &pixel_right = screen_.PixelAt(j * 2 + 1, i);
pixel_right.background_color = image.at(i, j);
pixel_right.character = ' ';
}
}

return;
}

void pixelator::Drawer::Draw() const {
screen_.Print();
return;
}

std::string pixelator::Drawer::ToString() const {
std::string string_image = screen_.ToString();

// Remove new line characters from the end of the string
// TODO: I added removing of the new line characters here since I was getting
// testing errors in github but not on local machine. I did not perform
// extensive test when I added this.
while (!string_image.empty() &&
(string_image[string_image.size() - 1] == '\r' ||
string_image[string_image.size() - 1] == '\n' ||
string_image[string_image.size() - 1] == ' ')) {
string_image.erase(string_image.size() - 1);
}

return string_image;
}
22 changes: 22 additions & 0 deletions homeworks/homework_5/pixelator/pixelator/drawer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once
#include "ftxui/screen/color.hpp"
#include "ftxui/screen/screen.hpp"
#include "pixelator/image.hpp"
namespace pixelator {
class Drawer {
private:
ftxui::Screen screen_{0, 0};
int rows_{};
int cols_{};

public:
Drawer() = default;
Drawer(const ftxui::Dimensions dimensions);
int rows() const;
int cols() const;
const Size size() const;
void Set(pixelator::Image image);
void Draw() const;
std::string ToString() const;
};
} // namespace pixelator
13 changes: 13 additions & 0 deletions homeworks/homework_5/pixelator/pixelator/drawer_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include "pixelator/drawer.hpp"
#include <gtest/gtest.h>

TEST(drawer_tests, test2) {
pixelator::Drawer full_screen_drawer{ftxui::Dimension::Full()};
pixelator::Drawer fixed_screen_drawer{ftxui::Dimension::Fixed(42)};

EXPECT_EQ(ftxui::Terminal::Size().dimx, full_screen_drawer.size().rows);
EXPECT_EQ(ftxui::Terminal::Size().dimy, full_screen_drawer.size().cols);

EXPECT_EQ(42, fixed_screen_drawer.size().rows);
EXPECT_EQ(84, fixed_screen_drawer.size().cols);
}
Loading