A bunch of random code samples
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

137 lignes
3.7 KiB

/*
cmake_minimum_required(VERSION 3.27)
project(cordiceps)
set(CMAKE_CXX_STANDARD 23)
include(FetchContent)
FetchContent_Declare(
raylib
GIT_REPOSITORY https://github.com/raysan5/raylib.git
GIT_TAG 5.0
)
FetchContent_MakeAvailable(raylib)
add_executable(cordiceps cordiceps.cpp)
target_link_libraries(cordiceps PUBLIC raylib_static)
*/
#include <ranges>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <cassert>
#include <cstdint>
#include <bit>
#include <bitset>
#include "raylib.h"
std::string slurp(const char* filename) {
std::ifstream file{filename};
std::stringstream data;
file >> data.rdbuf();
return data.str();
}
std::vector<bool> to_bits(std::string str) {
std::vector<bool> d;
for(char c : str) {
d.push_back(c & 0b10000000);
d.push_back(c & 0b1000000);
d.push_back(c & 0b100000);
d.push_back(c & 0b10000);
d.push_back(c & 0b1000);
d.push_back(c & 0b100);
d.push_back(c & 0b10);
d.push_back(c & 0b1);
}
return d;
}
std::string from_bits(std::vector<bool> data) {
std::string d;
std::bitset<32> size_bits;
for(int idx = 0; idx < 32; ++idx) size_bits[idx] = data[idx];
uint32_t size = size_bits.to_ulong();
if(std::endian::native == std::endian::little) size = std::byteswap(size);
for(auto composite : data | std::views::drop(32) | std::views::chunk(8)) {
char c = 0;
for(auto b : composite) {
c *= 2;
c += b;
}
d.push_back(c);
size--;
if(size == 0) return d;
}
return d;
}
void encode(const char* pic, const char* data_source) {
auto image = LoadImage(pic);
auto raw_data = slurp(data_source);
uint32_t size = raw_data.size();
if(std::endian::native == std::endian::little) size = std::byteswap(size);
std::bitset<32> size_bits;
size_bits = size;
std::vector<bool> raw_bits = to_bits(raw_data);
assert(raw_bits.size() % 8 == 0);
assert(raw_bits.size() / 8 == raw_data.size());
std::vector<bool> data;
for(int idx = 0; idx < 32; ++idx) data.push_back(size_bits[idx]);
data.insert(data.end(), raw_bits.begin(), raw_bits.end());
size_t idx = 0;
for(auto j : std::ranges::iota_view(0, image.height)) {
for(auto i : std::ranges::iota_view(0, image.width)) {
auto c = GetImageColor(image, i, j);
c.r ^= c.r & 1;
c.g ^= c.g & 1;
c.b ^= c.b & 1;
c.r += idx < data.size() ? data[idx] : 0; idx++;
c.g += idx < data.size() ? data[idx] : 0; idx++;
c.b += idx < data.size() ? data[idx] : 0; idx++;
ImageDrawPixel(&image, i, j, c);
}
}
ExportImage(image, pic);
UnloadImage(image);
if(raw_bits.size() > idx) {
std::cout << "\x1b[1;31mWritten bits: " << data.size() << "/" << idx << std::endl;
} else {
std::cout << "\x1b[1;32mWritten bits: " << data.size() << "/" << idx << std::endl;
}
}
void decode(const char* pic) {
auto image = LoadImage(pic);
std::vector<bool> raw_bits;
size_t idx = 0;
for(auto j : std::ranges::iota_view(0, image.height)) {
for(auto i : std::ranges::iota_view(0, image.width)) {
auto c = GetImageColor(image, i, j);
raw_bits.push_back(c.r & 1);
raw_bits.push_back(c.g & 1);
raw_bits.push_back(c.b & 1);
}
}
UnloadImage(image);
std::cout << from_bits(raw_bits);
}
int main(int argc, char** argv) {
if(argc <= 1) {
perror("arguments missing, expected: picture then datafile for coding, picture for decoding");
}
if(argc == 3) {
encode(argv[1], argv[2]);
} else if(argc == 2) {
decode(argv[1]);
}
return 0;
}