-
-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This homework is about pixelating images
- Loading branch information
Showing
18 changed files
with
708 additions
and
0 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
--- | ||
Language: Cpp | ||
BasedOnStyle: Google | ||
AllowShortBlocksOnASingleLine: true | ||
AllowShortCaseLabelsOnASingleLine: true | ||
AllowShortFunctionsOnASingleLine: All | ||
AllowShortLoopsOnASingleLine: true | ||
AllowShortIfStatementsOnASingleLine: true | ||
BinPackArguments: false | ||
BinPackParameters: false | ||
IncludeBlocks: Preserve | ||
SortIncludes: true | ||
... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
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) | ||
|
||
# TODO: Add your binaries here | ||
# There must be a binary `pixelate` here |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
#include "pixelator/drawer.hpp" | ||
#include "pixelator/pixelate_image.hpp" | ||
#include "pixelator/stb_image_data_view.hpp" | ||
|
||
#include <cstddef> | ||
#include <filesystem> | ||
#include <iostream> | ||
#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; } | ||
|
||
const 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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 = 3; | ||
int query_col = 2; | ||
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
27
homeworks/homework_5/pixelator/external/UpdateSubmodules.cmake
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# TODO: Add your libraries here | ||
# You must have the following libraries: | ||
# - stb_image_data_view | ||
# - drawer | ||
# - image | ||
# - pixelate_image | ||
|
||
if(BUILD_TESTING) | ||
include(GoogleTest) | ||
# 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 | ||
endif() |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Video script | ||
Hey everyone! In this video I want to introduce a project that we (and by "we" I mean "you") will implement to solidify everything that we've learned until this point. | ||
|
||
Here is what it'll do. It will turn a normal picture, like this one, into its pixelated form, like that one. | ||
|
||
And not only that, but it will also do all of this in the terminal! | ||
|
||
<!-- Intro --> | ||
|
||
|
||
Before we go into details, I hope that by now you know that you can find the full homework description below this video under a link to the course GitHub repository. I also provide an empty project skeleton with some boilerplate code for you to get started in an easier way. | ||
|
||
Now, let's talk details, shall we? | ||
|
||
In order to perform the pixelation we have to perform a number of actions. | ||
|
||
1. First we have to load the image from disk. We do this using an external library `stb`, or, more concretely a couple of functions from its header `stb_image.h`. In order to use this library, you will have to add it as a submodule. We already talked about submodules before, but I also provide the necessary command in the homework description file I mentioned before. | ||
2. Unfortunately, `stb` is a C library, so memory management is not its strongest side. That means we have to store the data that the `stb` library gave us in a safe way. How lucky for us that we learned about raw pointers and proper move semantics already! So we can implement a class, say `StbImageDataView` that will manage the memory allocated by the `stb` library for us! We should be able to move the objects of this class around and they should free the memory upon destruction. Again, I have an example to ease your way into this in the homework description. | ||
3. Eventually, we will also need a way to manipulate the colors in an image, so we will implement a class `Image` that will allow us to directly access and manipulate the RGB pixels in it. We can represent the colors as a vector of `ftxui::Color` which comes from an awesome library FTXUI, which we will also have to add as a submodule to our code. Once again, I provide an example of how this library can be used in the project skeleton. | ||
4. At this point we should be ready to implement the `PixelateImage` function that would take our `StbImageDataView`, pixelate it and return it as and `Image` instance. This is the most algorithmically intense part of the project but fear not, I'm sure you can manage! | ||
5. Finally, once we have the pixelated image at hand, we would like to show it in the terminal. We will again use the FTXUI library for that. The way we can do it is we wrap the `ftxui::Screen` instance into a class `Drawer`, that takes an `Image` instance and can `Draw()` it to the terminal. And, you guessed it, you'll find an example to guide you through this in the project skeleton. | ||
|
||
Oh, and of course we have to test all of this, so we add Googletest as a submodule to the project, write tests for all of the stuff I just talked about and test away! | ||
|
||
And that's it! That's all the functionality that you have to implement here. Now, I know it sounds like a lot and, if I'm honest, it might be. But it is still a good project to take on in order to get comfortable with coding in C++. | ||
|
||
Once again, all the needed details are in the repo linked in the description below. | ||
|
||
And at this, I wish you good luck, have lots of fun implementing it and _do_ take your time on this project. It sure took me a long time to prepare everything. It probably will take you multiple hours (or maybe even days) but there are no shortcuts in learning! If something is really confusing, do start a discussion in the GitHub organization linked under the video. | ||
|
||
Thanks again for watching and have fun implementing it all! And if you want a refresher on the move semantics or testing your code, do click on the thumbnails that have just appeared on your screen! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters