|
|
@ -1,6 +1,6 @@ |
|
|
|
/*
|
|
|
|
cmake_minimum_required(VERSION 3.28) |
|
|
|
project(codiceps) |
|
|
|
cmake_minimum_required(VERSION 3.27) |
|
|
|
project(cordiceps) |
|
|
|
|
|
|
|
set(CMAKE_CXX_STANDARD 23) |
|
|
|
|
|
|
@ -14,8 +14,8 @@ FetchContent_Declare( |
|
|
|
|
|
|
|
FetchContent_MakeAvailable(raylib) |
|
|
|
|
|
|
|
add_executable(codiceps codiceps.cpp) |
|
|
|
target_link_libraries(codiceps PUBLIC raylib_static) |
|
|
|
add_executable(cordiceps cordiceps.cpp) |
|
|
|
target_link_libraries(cordiceps PUBLIC raylib_static) |
|
|
|
*/ |
|
|
|
|
|
|
|
#include <ranges>
|
|
|
@ -24,6 +24,9 @@ target_link_libraries(codiceps PUBLIC raylib_static) |
|
|
|
#include <sstream>
|
|
|
|
#include <vector>
|
|
|
|
#include <cassert>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <bit>
|
|
|
|
#include <bitset>
|
|
|
|
#include "raylib.h"
|
|
|
|
|
|
|
|
std::string slurp(const char* filename) { |
|
|
@ -50,13 +53,20 @@ std::vector to_bits(std::string str) { |
|
|
|
|
|
|
|
std::string from_bits(std::vector<bool> data) { |
|
|
|
std::string d; |
|
|
|
for(auto composite : data | std::views::chunk(8)) { |
|
|
|
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; |
|
|
|
} |
|
|
@ -64,9 +74,18 @@ std::string from_bits(std::vector data) { |
|
|
|
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)) { |
|
|
@ -74,18 +93,18 @@ void encode(const char* pic, const char* data_source) { |
|
|
|
c.r ^= c.r & 1; |
|
|
|
c.g ^= c.g & 1; |
|
|
|
c.b ^= c.b & 1; |
|
|
|
c.r += idx < raw_bits.size() ? raw_bits[idx] : 0; idx++; |
|
|
|
c.g += idx < raw_bits.size() ? raw_bits[idx] : 0; idx++; |
|
|
|
c.b += idx < raw_bits.size() ? raw_bits[idx] : 0; idx++; |
|
|
|
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: " << raw_bits.size() << "/" << idx << std::endl; |
|
|
|
std::cout << "\x1b[1;31mWritten bits: " << data.size() << "/" << idx << std::endl; |
|
|
|
} else { |
|
|
|
std::cout << "\x1b[1;32mWritten bits: " << raw_bits.size() << "/" << idx << std::endl; |
|
|
|
std::cout << "\x1b[1;32mWritten bits: " << data.size() << "/" << idx << std::endl; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -115,4 +134,4 @@ int main(int argc, char** argv) { |
|
|
|
decode(argv[1]); |
|
|
|
} |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |