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.

147 lignes
4.2 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::ios_base::binary};
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);
std::cerr << "Decoded expected " << size << " bytes" << std::endl;
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();
std::cerr << "Writing expected " << size << " bytes" << std::endl;
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);
auto data = from_bits(raw_bits);
std::cerr << "Printing expected " << data.size() << " bytes" << std::endl;
std::ofstream{"cordiceps.out", std::ios_base::binary} << data;
}
void CustomLog(int msgType, const char *text, va_list args)
{
fprintf(stderr, text, args);
}
int main(int argc, char** argv) {
SetTraceLogLevel(LOG_ERROR);
SetTraceLogCallback(CustomLog);
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;
}