From aa403dd1aa26ea086688428de74aee34d805b4b1 Mon Sep 17 00:00:00 2001 From: Mark Zheleznyakov Date: Tue, 18 Feb 2025 14:19:04 +0300 Subject: [PATCH] feat(01-bmpmafia): threemult --- 01-bmpmafia/Makefile | 15 +++- 01-bmpmafia/README.md | 19 +++++ 01-bmpmafia/src/deepfryer/main.cpp | 4 +- 01-bmpmafia/src/threemult/bad.cpp | 70 ++++++++++++++++++ 01-bmpmafia/src/threemult/main.cpp | 109 +++++++++++++++++++++++++++++ 5 files changed, 215 insertions(+), 2 deletions(-) create mode 100644 01-bmpmafia/src/threemult/bad.cpp create mode 100755 01-bmpmafia/src/threemult/main.cpp diff --git a/01-bmpmafia/Makefile b/01-bmpmafia/Makefile index 19c568b..1eb2cfd 100644 --- a/01-bmpmafia/Makefile +++ b/01-bmpmafia/Makefile @@ -1,11 +1,24 @@ BUILD_DIR = build CXX = g++ +all: nerdybmp deepfryer threemult threemultfr + +clean: + rm -rf $(BUILD_DIR) + rm -rf samples/output/* + 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 + +threemultfr: src/threemult/main.cpp + @mkdir -p $(BUILD_DIR) + $(CXX) -o build/threemultfr src/threemult/main.cpp + +threemult: src/threemult/bad.cpp + @mkdir -p $(BUILD_DIR) + $(CXX) -o build/threemult src/threemult/bad.cpp diff --git a/01-bmpmafia/README.md b/01-bmpmafia/README.md index 814ba12..c7eeffb 100644 --- a/01-bmpmafia/README.md +++ b/01-bmpmafia/README.md @@ -36,3 +36,22 @@ make deepfryer build/deepfryer some/path/to/input.bmp some/path/to/output.bmp 128 ``` +## threemult + +converts 8bit bmp to 24bit + +### build + +```sh +# wrong edition +make threemult + +# fine edition +make threemultfr +``` + +### usage + +```sh +build/threemult(fr) some/path/to/input.bmp some/path/to/output.bmp +``` diff --git a/01-bmpmafia/src/deepfryer/main.cpp b/01-bmpmafia/src/deepfryer/main.cpp index 634bb50..ad70349 100644 --- a/01-bmpmafia/src/deepfryer/main.cpp +++ b/01-bmpmafia/src/deepfryer/main.cpp @@ -1,5 +1,6 @@ #include "../../include/bmp.hpp" #include "../../include/rainbow.hpp" +#include #include #include #include @@ -42,7 +43,8 @@ int main(int argc, char *argv[]) { if (fileHeader.type != 0x4D42) { std::cerr << "๐Ÿ’€ we are not cooking: this is NOT a BMP file...\n"; - return 1; + std::cerr << "โšก so now you get what you really deserve.\n"; + std::raise(SIGSEGV); } bmp::InfoHeader infoHeader; diff --git a/01-bmpmafia/src/threemult/bad.cpp b/01-bmpmafia/src/threemult/bad.cpp new file mode 100644 index 0000000..4ce4a41 --- /dev/null +++ b/01-bmpmafia/src/threemult/bad.cpp @@ -0,0 +1,70 @@ +#include "../../include/bmp.hpp" +#include +#include +#include +#include + +int main(int argc, char *argv[]) { + std::cout << "๐ŸŽฐ threemult\n"; + + if (argc < 3) { + std::cerr << "๐Ÿšฌ " << argc - 1 << " args? we must have more!!\n"; + std::cerr << "usage:\n"; + std::cerr << "threemult \n"; + return 1; + } + + std::ifstream inputFile(argv[1], std::ios::binary); + if (!inputFile) { + std::cerr << "๐Ÿ’€ we are not cooking: the file is cooked or even not a " + "file...\n"; + return 1; + } + + bmp::FileHeader fileHeader; + inputFile.read(reinterpret_cast(&fileHeader), sizeof(fileHeader)); + if (inputFile.gcount() < sizeof(fileHeader)) { + std::cerr << "๐Ÿ’€ we are not cooking: the file header is cursed.."; + return 1; + } + + bmp::InfoHeader infoHeader; + inputFile.read(reinterpret_cast(&infoHeader), sizeof(infoHeader)); + if (inputFile.gcount() < sizeof(infoHeader)) { + std::cerr << "๐Ÿ’€ we are not cooking: the infoheader is cursed.."; + return 1; + } + + if (fileHeader.type != 0x4D42) { + std::cerr << "๐Ÿ’€ we are not cooking: this is NOT a BMP file...\n"; + return 1; + } + + if (infoHeader.bitCount != 8) { + std::cerr << "๐Ÿ’€ we are not cooking: uhm i cannot convert" + << infoHeader.bitCount << "bit to 24bit im soooo sorry..\n"; + return 1; + } + + std::ofstream outputFile(argv[2], std::ios::binary); + if (!outputFile) { + std::cerr << "๐Ÿ’€ we are not cooking: unable to output to sthn...\n"; + return 1; + } + + std::cout << "๐Ÿงข writing headers...\n"; + + infoHeader.bitCount = 24; + infoHeader.colorsImportant = 0; + + fileHeader.offBits = sizeof(fileHeader) + sizeof(infoHeader); + + outputFile.write(reinterpret_cast(&fileHeader), sizeof(fileHeader)); + outputFile.write(reinterpret_cast(&infoHeader), sizeof(infoHeader)); + + outputFile << inputFile.rdbuf(); + + std::cout << "โœ… ur pic is ready... check it out...\n"; + + return 0; +} diff --git a/01-bmpmafia/src/threemult/main.cpp b/01-bmpmafia/src/threemult/main.cpp new file mode 100755 index 0000000..1e8721d --- /dev/null +++ b/01-bmpmafia/src/threemult/main.cpp @@ -0,0 +1,109 @@ +#include "../../include/bmp.hpp" +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) { + std::cout << "๐ŸŽฐ threemult\n"; + + if (argc < 3) { + std::cerr << "๐Ÿšฌ " << argc - 1 << " args? we must have more!!\n"; + std::cerr << "usage:\n"; + std::cerr << "threemult \n"; + return 1; + } + + std::ifstream inputFile(argv[1], std::ios::binary); + if (!inputFile) { + std::cerr << "๐Ÿ’€ we are not cooking: the file is cooked or even not a " + "file...\n"; + return 1; + } + + bmp::FileHeader fileHeader; + inputFile.read(reinterpret_cast(&fileHeader), sizeof(fileHeader)); + if (inputFile.gcount() < sizeof(fileHeader)) { + std::cerr << "๐Ÿ’€ we are not cooking: the file header is cursed.."; + return 1; + } + + bmp::InfoHeader infoHeader; + inputFile.read(reinterpret_cast(&infoHeader), sizeof(infoHeader)); + if (inputFile.gcount() < sizeof(infoHeader)) { + std::cerr << "๐Ÿ’€ we are not cooking: the infoheader is cursed.."; + return 1; + } + + if (fileHeader.type != 0x4D42) { + std::cerr << "๐Ÿ’€ we are not cooking: this is NOT a BMP file...\n"; + return 1; + } + + if (infoHeader.bitCount != 8) { + std::cerr << "๐Ÿ’€ we are not cooking: uhm i cannot convert" + << infoHeader.bitCount << "bit to 24bit im soooo sorry..\n"; + return 1; + } + + std::ofstream outputFile(argv[2], std::ios::binary); + if (!outputFile) { + std::cerr << "๐Ÿ’€ we are not cooking: unable to output to sthn...\n"; + return 1; + } + + // here's the side order + // some header stuff nvm + std::cout << "๐Ÿงข writing headers...\n"; + + infoHeader.bitCount = 24; + infoHeader.colorsImportant = 0; + + fileHeader.offBits = sizeof(fileHeader) + sizeof(infoHeader); + + outputFile.write(reinterpret_cast(&fileHeader), sizeof(fileHeader)); + outputFile.write(reinterpret_cast(&infoHeader), sizeof(infoHeader)); + + // 8bit bmps got 256 colors + // every color got 4bytes - rgba + std::vector palette(256 * 4); + inputFile.read(reinterpret_cast(palette.data()), palette.size()); + + // calculating lines realign + int width = std::abs(infoHeader.width); + int height = std::abs(infoHeader.height); + int row_padded_input = (width + 3) & ~3; + int row_padded_output = (width * 3 + 3) & ~3; + int padding_input = row_padded_input - width; + int padding_output = row_padded_output - width * 3; + + std::cout << "๐Ÿ–ผ๏ธ ok so now we're doin the pixels part\n"; + for (int i = 0; i < height; ++i) { + std::vector row(width); + inputFile.read(reinterpret_cast(row.data()), width); + inputFile.ignore(padding_input); + + // and here's the main course + std::vector new_row; + for (size_t j = 0; j < row.size(); ++j) { + uint8_t index = row[j]; // getting the color index + + // setting values for each channel + uint8_t r = palette[index * 4 + 2]; + uint8_t g = palette[index * 4 + 1]; + uint8_t b = palette[index * 4 + 0]; + + new_row.push_back(b); + new_row.push_back(g); + new_row.push_back(r); + } + + outputFile.write(reinterpret_cast(new_row.data()), new_row.size()); + outputFile.write("\x00\x00\x00", padding_output); + } + + std::cout << "โœ… i guess we're done for now\n"; + + return 0; +}