feat(01-bmpmafia): threemult

This commit is contained in:
2025-02-18 14:19:04 +03:00
parent e110d9afe2
commit aa403dd1aa
5 changed files with 215 additions and 2 deletions

View File

@ -1,11 +1,24 @@
BUILD_DIR = build BUILD_DIR = build
CXX = g++ CXX = g++
all: nerdybmp deepfryer threemult threemultfr
clean:
rm -rf $(BUILD_DIR)
rm -rf samples/output/*
nerdybmp: src/nerdybmp/main.cpp nerdybmp: src/nerdybmp/main.cpp
@mkdir -p $(BUILD_DIR) @mkdir -p $(BUILD_DIR)
$(CXX) -o build/nerdybmp src/nerdybmp/main.cpp $(CXX) -o build/nerdybmp src/nerdybmp/main.cpp
deepfryer: src/deepfryer/main.cpp deepfryer: src/deepfryer/main.cpp
@mkdir -p $(BUILD_DIR) @mkdir -p $(BUILD_DIR)
$(CXX) -o build/deepfryer src/deepfryer/main.cpp $(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

View File

@ -36,3 +36,22 @@ make deepfryer
build/deepfryer some/path/to/input.bmp some/path/to/output.bmp 128 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
```

View File

@ -1,5 +1,6 @@
#include "../../include/bmp.hpp" #include "../../include/bmp.hpp"
#include "../../include/rainbow.hpp" #include "../../include/rainbow.hpp"
#include <csignal>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <string> #include <string>
@ -42,7 +43,8 @@ int main(int argc, char *argv[]) {
if (fileHeader.type != 0x4D42) { if (fileHeader.type != 0x4D42) {
std::cerr << "💀 we are not cooking: this is NOT a BMP file...\n"; 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; bmp::InfoHeader infoHeader;

View File

@ -0,0 +1,70 @@
#include "../../include/bmp.hpp"
#include <cstdint>
#include <cstring>
#include <fstream>
#include <iostream>
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 <input_bmp_file> <output_bmp_file>\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<char *>(&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<char *>(&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<char *>(&fileHeader), sizeof(fileHeader));
outputFile.write(reinterpret_cast<char *>(&infoHeader), sizeof(infoHeader));
outputFile << inputFile.rdbuf();
std::cout << "✅ ur pic is ready... check it out...\n";
return 0;
}

View File

@ -0,0 +1,109 @@
#include "../../include/bmp.hpp"
#include <cstdint>
#include <cstring>
#include <fstream>
#include <iostream>
#include <vector>
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 <input_bmp_file> <output_bmp_file>\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<char *>(&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<char *>(&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<char *>(&fileHeader), sizeof(fileHeader));
outputFile.write(reinterpret_cast<char *>(&infoHeader), sizeof(infoHeader));
// 8bit bmps got 256 colors
// every color got 4bytes - rgba
std::vector<uint8_t> palette(256 * 4);
inputFile.read(reinterpret_cast<char *>(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<uint8_t> row(width);
inputFile.read(reinterpret_cast<char *>(row.data()), width);
inputFile.ignore(padding_input);
// and here's the main course
std::vector<uint8_t> 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<char *>(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;
}