diff --git a/01-bmpmafia/Makefile b/01-bmpmafia/Makefile index e8a2cc4..19c568b 100644 --- a/01-bmpmafia/Makefile +++ b/01-bmpmafia/Makefile @@ -4,3 +4,8 @@ CXX = g++ nerdybmp: src/nerdybmp/main.cpp @mkdir -p $(BUILD_DIR) $(CXX) -o build/nerdybmp src/nerdybmp/main.cpp + + +deepfryer: src/deepfryer/main.cpp + @mkdir -p $(BUILD_DIR) + $(CXX) -o build/deepfryer src/deepfryer/main.cpp diff --git a/01-bmpmafia/README.md b/01-bmpmafia/README.md index 694a78c..814ba12 100644 --- a/01-bmpmafia/README.md +++ b/01-bmpmafia/README.md @@ -17,3 +17,22 @@ make nerdybmp ```sh build/nerdybmp some/path/to/file.bmp ``` + +## ๐Ÿณ `deepfryer` + +![catstare](assets/catstare.jpg) + +image binarification program + +### build + +```sh +make deepfryer +``` + +### usage + +```sh +build/deepfryer some/path/to/input.bmp some/path/to/output.bmp 128 +``` + diff --git a/01-bmpmafia/assets/catstare.jpg b/01-bmpmafia/assets/catstare.jpg new file mode 100644 index 0000000..5513155 Binary files /dev/null and b/01-bmpmafia/assets/catstare.jpg differ diff --git a/01-bmpmafia/include/bmp.hpp b/01-bmpmafia/include/bmp.hpp index be62045..8ee6daf 100644 --- a/01-bmpmafia/include/bmp.hpp +++ b/01-bmpmafia/include/bmp.hpp @@ -25,7 +25,15 @@ namespace bmp { uint32_t colorsUsed; uint32_t colorsImportant; }; + + struct BMPColorHeader { + uint32_t red; + uint32_t green; + uint32_t blue; + uint32_t alpha; + uint32_t colorSpaceType; + uint32_t unused[16]; +}; } #pragma pack(pop) #endif - diff --git a/01-bmpmafia/include/rainbow.hpp b/01-bmpmafia/include/rainbow.hpp new file mode 100644 index 0000000..7dcfdf5 --- /dev/null +++ b/01-bmpmafia/include/rainbow.hpp @@ -0,0 +1,24 @@ +#ifndef RAINBOW_HPP +#define RAINBOW_HPP +#include + +namespace rainbow { + void print(std::ostream & out, std::string s) { + std::string colors[7] = { + "\033[38;2;210;15;57m", + "\033[38;2;254;100;11m", + "\033[38;2;223;142;29m", + "\033[38;2;64;160;43m", + "\033[38;2;4;165;229m", + "\033[38;2;30;102;245m", + "\033[38;2;136;57;239m" + }; + + for (int i = 0; i < s.length(); i++) + { + out << colors[i % 7] << s[i] << "\033[0m"; + } + } +} +#endif + diff --git a/01-bmpmafia/src/deepfryer/main.cpp b/01-bmpmafia/src/deepfryer/main.cpp new file mode 100644 index 0000000..634bb50 --- /dev/null +++ b/01-bmpmafia/src/deepfryer/main.cpp @@ -0,0 +1,117 @@ +#include "../../include/bmp.hpp" +#include "../../include/rainbow.hpp" +#include +#include +#include +#include + +int main(int argc, char *argv[]) { + std::cout << "๐Ÿณ "; + rainbow::print(std::cout, "deepfryer"); + std::cout << "\n"; + + if (argc < 4) { + std::cerr << "๐Ÿšฌ " << argc << " args? we must have more!!\n"; + std::cerr << "usage:\n"; + std::cerr << "nerdybmp \n"; + return 1; + } + + int threshold = 127; + + try { + threshold = std::stoi(argv[3]); + } catch (std::invalid_argument const &ex) { + std::cerr << "๐Ÿ’€ thats not the threshold.. even not a number.... ok bye\n"; + return 1; + } + + if (threshold > 256 || threshold < 0) { + std::cerr << "๐Ÿ’€ thats not a valid threshold.. ok bye\n"; + return 1; + } + + std::ifstream inputFile(argv[1], std::ios_base::binary); + if (!inputFile) { + std::cerr << "๐Ÿ’€ unable to read the file.. ok bye\n"; + return 1; + } + + bmp::FileHeader fileHeader; + inputFile.read((char *)&fileHeader, sizeof(fileHeader)); + + if (fileHeader.type != 0x4D42) { + std::cerr << "๐Ÿ’€ we are not cooking: this is NOT a BMP file...\n"; + return 1; + } + + bmp::InfoHeader infoHeader; + inputFile.read((char *)&infoHeader, sizeof(infoHeader)); + + std::cout << "๐Ÿ“‚ opened " << argv[1] << '\n'; + + std::ofstream outputFile(argv[2], std::ios_base::binary); + if (!outputFile) { + std::cerr << "๐Ÿ’€ unable to create the output file.. ok bye\n"; + return 1; + } + + std::cout << "๐Ÿงจ heating up the "; + rainbow::print(std::cout, "fryer"); + std::cout << " up to " << threshold << "ยฐ...\n"; + + inputFile.seekg(infoHeader.size + sizeof(bmp::FileHeader), std::ios::beg); + + int rowSize = (infoHeader.width * infoHeader.bitCount / 8 + 3) & ~3; + int paddingSize = rowSize - (infoHeader.width * infoHeader.bitCount / 8); + std::vector row(rowSize); + + bmp::FileHeader outFileHeader; + outFileHeader.type = 0x4D42; + outFileHeader.size = sizeof(bmp::FileHeader) + sizeof(bmp::InfoHeader) + + rowSize * infoHeader.height; + outFileHeader.reserved1 = 0; + outFileHeader.reserved2 = 0; + outFileHeader.offBits = sizeof(bmp::FileHeader) + sizeof(bmp::InfoHeader); + + outputFile.write((char *)&fileHeader, sizeof(fileHeader)); + outputFile.write((char *)&infoHeader, sizeof(infoHeader)); + + std::cout << "๐Ÿพ THE "; + rainbow::print(std::cout, "DEEPFRYER"); + std::cout << " IS READY FOR COOKING ๐Ÿ”ฅ\n"; + + for (int y = 0; y < infoHeader.height; ++y) { + inputFile.read((char *)row.data(), rowSize); + + for (int x = 0; x < infoHeader.width; ++x) { + uint8_t blue = row[x * 3]; + uint8_t green = row[x * 3 + 1]; + uint8_t red = row[x * 3 + 2]; + + uint8_t gray = + static_cast(0.299 * red + 0.587 * green + 0.114 * blue); + + uint8_t binaryColor = (gray < threshold) ? 0 : 255; + + row[x * 3] = binaryColor; + row[x * 3 + 1] = binaryColor; + row[x * 3 + 2] = binaryColor; + } + + outputFile.write((char *)row.data(), rowSize); + } + + std::cout << "๐Ÿ— your pic is ready, turning off the "; + rainbow::print(std::cout, "fryer"); + std::cout << "...\n"; + + std::vector padding(paddingSize, 0); + outputFile.write((char *)padding.data(), paddingSize); + + std::cout << "โœ… take your " << argv[2] << " .. bone apple teeth\n"; + + inputFile.close(); + outputFile.close(); + return 0; +}