{"id":41725387,"url":"https://github.com/s9w/binary_bakery","last_synced_at":"2026-01-24T23:05:42.978Z","repository":{"id":46055694,"uuid":"415040026","full_name":"s9w/binary_bakery","owner":"s9w","description":"Translates binary information (images, fonts, shaders) into C++ source code.","archived":false,"fork":false,"pushed_at":"2024-02-18T15:45:03.000Z","size":3331,"stargazers_count":130,"open_issues_count":3,"forks_count":9,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-02-19T14:36:27.473Z","etag":null,"topics":["cpp"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/s9w.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-10-08T15:35:11.000Z","updated_at":"2024-02-18T16:03:48.000Z","dependencies_parsed_at":"2022-09-23T07:10:59.417Z","dependency_job_id":null,"html_url":"https://github.com/s9w/binary_bakery","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/s9w/binary_bakery","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/s9w%2Fbinary_bakery","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/s9w%2Fbinary_bakery/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/s9w%2Fbinary_bakery/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/s9w%2Fbinary_bakery/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/s9w","download_url":"https://codeload.github.com/s9w/binary_bakery/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/s9w%2Fbinary_bakery/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28738979,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-24T22:12:27.248Z","status":"ssl_error","status_checked_at":"2026-01-24T22:12:10.529Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cpp"],"created_at":"2026-01-24T23:05:42.060Z","updated_at":"2026-01-24T23:05:42.941Z","avatar_url":"https://github.com/s9w.png","language":"C++","readme":"# Binary bakery :cookie:\nTranslates binary files (images, fonts etc.) into **C++ source code** and gives access to that data at compile- or runtime. There are different reasons why you might want this:\n\n- Avoiding the complexity of loading images or archives with external libraries\n- Compile-time access to meta information and content itself, including pixel colors\n- Faster load times, especially with small files\n- Avoiding to ship files with your application binary or preventing people from grabbing such files\n\nBinary bakery allows the data itself as well as some meta information to be available at compile-time (`constexpr`). Images are also encoded in a special way so that their dimensions as well as their pixel colors are accessible directly - without decoding with image libraries.\n\n[**Basics**](#basics) :cake:  [**Encoding**](#encoding) :cupcake: [**Decoding**](#decoding) :pie: [**Costs and benefits**](#costs-and-benefits) :birthday:\n\n## Basics\nAn executable translates binary file(s) into C++ source code:\n\n![](readme/encoding_video.gif)\n\nInclude the resulting payload header as well as the [decoder header](binary_bakery_decoder.h) into your code:\n```c++\n#include \u003cbinary_bakery_payload.h\u003e\n#define BAKERY_PROVIDE_VECTOR\n#include \u003cbinary_bakery_decoder.h\u003e\n\n// All binary information can just be read as bytes.\nconst std::vector\u003cuint8_t\u003e font_bytes = bb::decode_to_vector\u003cuint8_t\u003e(bb::get_payload(\"fancy_font.ttf\"));\n\n// Images have their pixel information available directly, without third party libraries\nstruct color { uint8_t r, g, b; };\n\nconstexpr const uint64_t* logo_ptr = bb::get_payload(\"logo.png\");\nconst std::vector\u003ccolor\u003e logo_pixels = bb::decode_to_vector\u003ccolor\u003e(logo_ptr);\n\n// Meta information is also available - at compile time!\nconstexpr bb::header meta_information = bb::get_header(logo_ptr);\n\n// For uncompressed payloads, the data can also be accessed at compile time\nconstexpr color first_pixel = bb::get_element\u003ccolor\u003e(logo_ptr, 0);\n\n// If you don't want to use std::vector, the data can just be memcopied\nmy_vec\u003cuint8_t\u003e storage;\nconstexpr const uint64_t* large_data_ptr = bb::get_payload(\"level.bin\");\nstorage.resize(bb::get_element_count\u003cuint8_t\u003e(large_data_ptr));\nbb::decode_into_pointer(large_data_ptr, storage.data(), my_decompression_function);\n```\n\nIf decompression code is available in the target codebase, the payload can be compressed during encoding, resulting in less impact on the [compile metrics](#costs-and-benefits). Currently supported is [zstd](https://github.com/facebook/zstd) and [LZ4](https://github.com/lz4/lz4).\n\n## Encoding\nThe tool is a command line executable that encodes all files from its command line parameters. Dragging files on top of it is the same as calling it from the command line:\n\n```\nbinary_bakery.exe file1 file2 ...\n```\n\n#### Configuration\nThere's a [`binary_bakery.toml`](binary_bakery.toml) configuration file, which documents its options. Most importantly, you can set your compression there.\n\nThe program tries to pick the best available configuration file. In order of priority:\n1. A suitable `.toml` file among one of the parameters (or files dragged onto the executable).\n2. A `binary_bakery.toml` in the directory of the files being encoded.\n3. A `binary_bakery.toml` in the current working directory.\n4. Default settings.\n\nNot all settings have to be set, left out will be defaulted.\n\nCurrently `png`, `tga` and `bmp` images will be read as images and have their pixel information stored directly. Other image formats like `jpg` will be treated as any other generic binary file. It's not recommended to use images without another compression algorithm. `png` files can have a huge memory footprint compared to their filesize when not compressed in another way.\n\n## Decoding\nThe encoder produces a *payload header*, which contains valid C++ and needs to be included in your source code. Make sure to only include it in one translation unit because of its potentially large size. To access the encoded information inside, you also need the [binary_bakery_decoder.h](binary_bakery_decoder.h).\n\nA typical payload header looks like this:\n```c++\nnamespace bb{\n\nstatic constexpr uint64_t bb_bitmap_font_16_png[]{\n   0x0020002003000201, 0x00000bf600000c00, 0x62a1b925fffffff0, 0x97ad5c9db662a1b9, \n   0xc262a3bb65a8bc5b, 0x5b9bb462a3bb6aad, 0x82973f7c944f8ca1, /* ... */\n};\n\n} // namespace bb\n```\n#### Header\nYou can get a `const uint64_t*` pointer to the payloads at compile-time by filename with `bb::get_payload(std::string_view)`. All other functions require that payload pointer.\n\nInside those `uint64` payload arrays is a header with meta information and the data itself. You can access the header with `constexpr get_header(const uint64_t*)`. See [binary_bakery_decoder.h#L16-L34](binary_bakery_decoder.h#L16-L34) for the header members.\n\n#### Decompression\nIf your data was encoded with a compression algorithm, you need to provide a function in your code that does the decompression. All interface functions have such a function pointer parameter. For uncompressed streams, that parameter can be left out as it defaults to `nullptr`. That function should look like this:\n```c++\nauto compression_fun(\n   const void* src,       // Points to the compressed data\n   const size_t src_size, // Size of compressed data in bytes\n   void* dst,             // Pointer to the preallocated decompressed data\n   const size_t dst_size  // Size of decompressed data in bytes\n) -\u003e void;\n```\n\nFor zstd for example, that would typically contain a call to `ZSTD_decompress(dst, dst_size, src, src_size);`. For LZ4, that might look like `LZ4_decompress_safe(src, dst, src_size, dst_size)`.\n\n#### Data interfaces\n|\u003cpre\u003etemplate\u0026lt;typename user_type\u0026gt;\u003cbr\u003estd::vector\u0026lt;user_type\u0026gt; bb::decode_to_vector(const uint64_t* payload, decomp_fun)\u003c/pre\u003e|\n|:---|\n| Returns a vector of your target type. If you want to use this interface, you need to `#define BAKERY_PROVIDE_VECTOR` before you include the decoder header (to prevent the `\u003cvector\u003e` include if you don't). Note that this function requires `user_type` to be default constructible. |\n\n|\u003cpre\u003evoid bb::decode_into_pointer(const uint64_t* payload, void* dst, decomp_fun)\u003c/pre\u003e|\n|:---|\n| Writes into a **preallocated** memory. You can access the required decompressed size in bytes (at compile-time) from `header::decompressed_size`. This function memcopies into the destination. |\n\n|\u003cpre\u003etemplate\u0026lt;typename user_type\u0026gt;\u003cbr\u003econstexpr user_type bb::get_element(const uint64_t* payload, const int index)\u003c/pre\u003e|\n|:---|\n| Compile-time access that only works for **uncompressed** data. For images, it should be `sizeof(user_type)==bpp`. |\n\n\n#### Do your own thing\nIf you want to avoid using the provided decoding header altogether, you can access the information yourself. The first 16 bytes contain the header which is defined at the top of the [`binary_bakery_decoder.h`](binary_bakery_decoder.h#L16-L34). Everything after that is the byte stream.\n\n## Error handling\nIf there's an error in a compile-time context, that always results in a compile error. Runtime behavior is configurable by providing a function that gets called in error cases. You might want to throw an exception, call `std::terminate()`, log some error and continue or whatever you desire.\n\nTo provide a custom error function, set set the function pointer to your function:\n\n```c++\nauto my_error_function(\n   std::string_view msg,\n   const std::source_location\u0026 loc\n) -\u003e void\n{\n   std::cerr \u003c\u003c std::format(\n      \"ERROR: {} in: {}({}:{}) \\\"{}\\\"\\n\",\n      msg, loc.file_name(), loc.line(), loc.column(), loc.function_name()\n      );\n   std::terminate();\n}\n// ...\nbb::error_callback = my_error_function;\n```\n\n:warning: If no `bb::error_callback` is set, default behavior is ignoring errors and returning nulled values. That is almost certainly not what you want. Errors are things like calling image-only functions on non-image payloads and providing `nullptr` parameters. Behavior summary:\n\n|   | Compiletime | Runtime |\n|---|---|---|\n| Default | Compile error | No error, return defaulted types |\n| User-defined error function | Compile error | Call user-defined function |\n\n## Costs and benefits\nThere are two main concerns about embedding non-code data into your source code and resulting binary: Compile times and the size of the resulting binary. On the flipside, there's also the potential of higher decode speed. What follows is an analysis of the pros and cons this method vs file loading in regard to various metrics. To get realistic results, a dataset of different images with common dimension and sizes was created (in [sample_datasets/](sample_datasets)):\n\n|                                              | Dimensions     | Uncompressed size | zstd ratio | LZ4 ratio |\n| -------------------------------------------: | -------------: | ----------------: | ---------: | --------: |\n|      [192.png](sample_datasets/192.png)      |       8×8×3BPP |             192 B |      91.7% |     94.8% |\n|     [3072.png](sample_datasets/3072.png)     |     32×32×3BPP |              3 KB |      88.7% |     99.7% |\n|    [49152.png](sample_datasets/49152.png)    |   128×128×3BPP |             48 KB |      12.0% |     29.1% |\n|   [240000.png](sample_datasets/240000.png)   |   400×200×3BPP |            234 KB |      34.9% |     43.6% |\n|   [480000.png](sample_datasets/480000.png)   |   400×400×3BPP |            468 KB |      22.4% |     31.9% |\n|  [3145728.png](sample_datasets/3145728.png)  | 1024×1024×3BPP |              3 MB |      14.2% |     24.9% |\n| [16777216.png](sample_datasets/16777216.png) | 2048×2048×4BPP |             16 MB |      10.6% |     17.5% |\n\nNote that the compression ratio here refers to **compressed size / uncompressed size** (lower is better).\n\nThe dataset contains various game spritesheets like this:\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"https://github.com/s9w/binary_bakery/raw/master/sample_datasets/240000.png\"\u003e\u003c/p\u003e\n\n### Binary size\n\nThe expected size of the resulting binary is the size without any embedded binary files plus the byte-size of the payload. The following plot shows the resulting binary size relative to that expected size.\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"https://github.com/s9w/binary_bakery/raw/master/readme/binary_size.png\"\u003e\u003c/p\u003e\n\nGood news: the compiler doesn't add overhead beyond the payload size and a small constant size penalty of ~3KB from the decoding header. Compression allows the payload size to decrease, reducing the impact on binary size and -time.\n\nAs an example datapoint, an image with an uncompressed size of 16MB only adds 1.78MB to the resulting binary with zstd compression.\n\n### Compile times\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"https://github.com/s9w/binary_bakery/raw/master/readme/compile_times.png\"\u003e\u003c/p\u003e\n\nThe increase in compile times is linear with the size of the payload (note the log scale). Compression decreases the effective payload size. For the biggest 16 MB data sample, compile time increases by 5 seconds uncompressed and 0.5 seconds with zstd.\n\nThe payload header should only be included in one translation unit (TU). With commonplace parallel compilation, the effective compile time increase should only be 1/n (with n threads) of that number because the other n-1 threads can compile other TUs. So even ignoring compression, a payload size of 16MB only increases compile times by 0.06 seconds (assuming 8 threads and enough TUs to saturate them).\n\n### Decode speed\n\nOf interest is also the loading speed compared to traditional loading from files. Here's the decoding time for png images relative to the decoding speed from a file with [stb_image](https://github.com/nothings/stb) (lower is faster):\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"https://github.com/s9w/binary_bakery/raw/master/readme/decode_speed_analysis.png\"\u003e\u003c/p\u003e\n\nLZ4 performs identical to uncompressed data in decoding speed by being fast enough to not be the bottleneck. zstd is heavier bit also often reduced the compile impact by half compared to LZ4.\n\nBaking performs better than file loading for all sizes and compression types. In particular for small files, which should be the main target demographic for this tool.\n\nAll these numbers were measured in release mode (`/O2`) with Visual Studio 16.11.3, a Ryzen 3800X and a Samsung 970 EVO SSD.\n\n## Summary\nThis is a niche tool. File systems and other means of packing data are a good inventions and the better choice in most cases.\n\nIf this suits your needs however, the tradeoffs are manageable.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fs9w%2Fbinary_bakery","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fs9w%2Fbinary_bakery","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fs9w%2Fbinary_bakery/lists"}