A bunch of random code samples
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

136 行
3.7 KiB

  1. /*
  2. cmake_minimum_required(VERSION 3.27)
  3. project(cordiceps)
  4. set(CMAKE_CXX_STANDARD 23)
  5. include(FetchContent)
  6. FetchContent_Declare(
  7. raylib
  8. GIT_REPOSITORY https://github.com/raysan5/raylib.git
  9. GIT_TAG 5.0
  10. )
  11. FetchContent_MakeAvailable(raylib)
  12. add_executable(cordiceps cordiceps.cpp)
  13. target_link_libraries(cordiceps PUBLIC raylib_static)
  14. */
  15. #include <ranges>
  16. #include <iostream>
  17. #include <fstream>
  18. #include <sstream>
  19. #include <vector>
  20. #include <cassert>
  21. #include <cstdint>
  22. #include <bit>
  23. #include <bitset>
  24. #include "raylib.h"
  25. std::string slurp(const char* filename) {
  26. std::ifstream file{filename};
  27. std::stringstream data;
  28. file >> data.rdbuf();
  29. return data.str();
  30. }
  31. std::vector<bool> to_bits(std::string str) {
  32. std::vector<bool> d;
  33. for(char c : str) {
  34. d.push_back(c & 0b10000000);
  35. d.push_back(c & 0b1000000);
  36. d.push_back(c & 0b100000);
  37. d.push_back(c & 0b10000);
  38. d.push_back(c & 0b1000);
  39. d.push_back(c & 0b100);
  40. d.push_back(c & 0b10);
  41. d.push_back(c & 0b1);
  42. }
  43. return d;
  44. }
  45. std::string from_bits(std::vector<bool> data) {
  46. std::string d;
  47. std::bitset<32> size_bits;
  48. for(int idx = 0; idx < 32; ++idx) size_bits[idx] = data[idx];
  49. uint32_t size = size_bits.to_ulong();
  50. if(std::endian::native == std::endian::little) size = std::byteswap(size);
  51. for(auto composite : data | std::views::drop(32) | std::views::chunk(8)) {
  52. char c = 0;
  53. for(auto b : composite) {
  54. c *= 2;
  55. c += b;
  56. }
  57. d.push_back(c);
  58. size--;
  59. if(size == 0) return d;
  60. }
  61. return d;
  62. }
  63. void encode(const char* pic, const char* data_source) {
  64. auto image = LoadImage(pic);
  65. auto raw_data = slurp(data_source);
  66. uint32_t size = raw_data.size();
  67. if(std::endian::native == std::endian::little) size = std::byteswap(size);
  68. std::bitset<32> size_bits;
  69. size_bits = size;
  70. std::vector<bool> raw_bits = to_bits(raw_data);
  71. assert(raw_bits.size() % 8 == 0);
  72. assert(raw_bits.size() / 8 == raw_data.size());
  73. std::vector<bool> data;
  74. for(int idx = 0; idx < 32; ++idx) data.push_back(size_bits[idx]);
  75. data.insert(data.end(), raw_bits.begin(), raw_bits.end());
  76. size_t idx = 0;
  77. for(auto j : std::ranges::iota_view(0, image.height)) {
  78. for(auto i : std::ranges::iota_view(0, image.width)) {
  79. auto c = GetImageColor(image, i, j);
  80. c.r ^= c.r & 1;
  81. c.g ^= c.g & 1;
  82. c.b ^= c.b & 1;
  83. c.r += idx < data.size() ? data[idx] : 0; idx++;
  84. c.g += idx < data.size() ? data[idx] : 0; idx++;
  85. c.b += idx < data.size() ? data[idx] : 0; idx++;
  86. ImageDrawPixel(&image, i, j, c);
  87. }
  88. }
  89. ExportImage(image, pic);
  90. UnloadImage(image);
  91. if(raw_bits.size() > idx) {
  92. std::cout << "\x1b[1;31mWritten bits: " << data.size() << "/" << idx << std::endl;
  93. } else {
  94. std::cout << "\x1b[1;32mWritten bits: " << data.size() << "/" << idx << std::endl;
  95. }
  96. }
  97. void decode(const char* pic) {
  98. auto image = LoadImage(pic);
  99. std::vector<bool> raw_bits;
  100. size_t idx = 0;
  101. for(auto j : std::ranges::iota_view(0, image.height)) {
  102. for(auto i : std::ranges::iota_view(0, image.width)) {
  103. auto c = GetImageColor(image, i, j);
  104. raw_bits.push_back(c.r & 1);
  105. raw_bits.push_back(c.g & 1);
  106. raw_bits.push_back(c.b & 1);
  107. }
  108. }
  109. UnloadImage(image);
  110. std::cout << from_bits(raw_bits);
  111. }
  112. int main(int argc, char** argv) {
  113. if(argc <= 1) {
  114. perror("arguments missing, expected: picture then datafile for coding, picture for decoding");
  115. }
  116. if(argc == 3) {
  117. encode(argv[1], argv[2]);
  118. } else if(argc == 2) {
  119. decode(argv[1]);
  120. }
  121. return 0;
  122. }