Skip to content

Commit 3f0fe49

Browse files
committed
Major changes. Struct realignment, future-proofed, spec changes.
1 parent 1e7d76e commit 3f0fe49

4 files changed

Lines changed: 127 additions & 16 deletions

File tree

.gitignore

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,15 @@
1-
.vscode/
1+
.vscode/
2+
CMakeLists.txt.user
3+
CMakeCache.txt
4+
CMakeFiles
5+
CMakeScripts
6+
Testing
7+
Makefile
8+
cmake_install.cmake
9+
install_manifest.txt
10+
compile_commands.json
11+
CTestTestfile.cmake
12+
_deps
13+
CMakeUserPresets.json
14+
/build
15+
CMakeLists.txt

src/bbfenc.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#define NOMINMAX
2+
13
#include "libbbf.h"
24
#include "xxhash.h"
35
#include <iostream>
@@ -133,13 +135,23 @@ class BBFReader
133135
{
134136
if (!mmap.map(path))
135137
return false;
138+
139+
// Basic size check
136140
if (mmap.size < sizeof(BBFHeader) + sizeof(BBFFooter))
137141
return false;
138142

143+
// Read the fixed-size part of the header first
139144
std::memcpy(&header, mmap.data, sizeof(BBFHeader));
145+
140146
if (std::memcmp(header.magic, "BBF1", 4) != 0)
141147
return false;
142148

149+
// FUTURE PROOFING:
150+
// If header.headerLen > sizeof(BBFHeader), we know there is extra data
151+
// in the header we should ignore. We don't need to do anything right now
152+
// because we read assets via absolute offsets, but it's good to know.
153+
154+
// Read Footer
143155
std::memcpy(&footer, (uint8_t *)mmap.data + mmap.size - sizeof(BBFFooter), sizeof(BBFFooter));
144156
if (std::memcmp(footer.magic, "BBF1", 4) != 0)
145157
return false;
@@ -574,9 +586,13 @@ int main(int argc, char *argv[])
574586
for (uint32_t i = start; i < end; ++i)
575587
{
576588
const auto &asset = assets[pages[i].assetIndex];
577-
std::string outPath = (fs::path(outDir) / ("p" + std::to_string(i + 1) + ((asset.type == 1) ? ".avif" : ".png"))).string();
578589

579-
// Optimized: Direct write from mapped memory
590+
// FIX: Use the library function to get the extension
591+
// This automatically handles PNG, JPG, AVIF, JXL, etc.
592+
std::string ext = MediaTypeToStr(asset.type);
593+
594+
std::string outPath = (fs::path(outDir) / ("p" + std::to_string(i + 1) + ext)).string();
595+
580596
std::ofstream ofs(outPath, std::ios::binary);
581597
ofs.write((const char *)reader.mmap.data + asset.offset, asset.length);
582598
}
@@ -686,7 +702,8 @@ int main(int argc, char *argv[])
686702
for (uint32_t i = 0; i < manifest.size(); ++i)
687703
{
688704
std::string ext = fs::path(manifest[i].path).extension().string();
689-
uint8_t type = (ext == ".avif" || ext == ".AVIF") ? 1 : 2;
705+
BBFMediaType mediaType = detectTypeFromExtension(ext);
706+
uint8_t type = static_cast<uint8_t>(mediaType);
690707
builder.addPage(manifest[i].path, type);
691708
fileToPage[manifest[i].filename] = i;
692709
}

src/libbbf.cpp

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
#include <iostream>
55
#include <vector>
6+
#include <algorithm>
7+
#include <string>
8+
#include <cctype>
69

710
BBFBuilder::BBFBuilder(const std::string& outputFilename) : currentOffset(0)
811
{
@@ -22,7 +25,9 @@ BBFBuilder::BBFBuilder(const std::string& outputFilename) : currentOffset(0)
2225
header.magic[1] = 'B';
2326
header.magic[2] = 'F';
2427
header.magic[3] = '1';
25-
header.version = 1;
28+
header.version = 2;
29+
header.flags = 0; // reserved for now as well.
30+
header.headerLen = sizeof(BBFHeader);
2631
header.reserved = 0; // Reserved for future expansions
2732

2833
// Write the header
@@ -92,16 +97,19 @@ bool BBFBuilder::addPage(const std::string& imagePath, uint8_t type, uint32_t fl
9297
// No dupe found. create a new asset.
9398
alignPadding(); // start by allocating necessary padding.
9499

95-
BBFAssetEntry newAsset;
100+
BBFAssetEntry newAsset = {0};
96101
newAsset.offset = currentOffset;
97102
newAsset.length = size;
103+
newAsset.decodedLength = size;
98104
newAsset.xxh3Hash = hash;
99105
newAsset.type = type;
106+
newAsset.flags = 0; // no flags yet.
100107

101-
for ( int i = 0; i < 7; i++ )
102-
{
103-
newAsset.reserved[i] = 0; // Add in the reserved bytes.
104-
}
108+
// set reserved equal to zero
109+
//newAsset.reserved[4] = {0};
110+
111+
// same for padding
112+
//newAsset.padding[7] = {0};
105113

106114
fileStream.write(buffer.data(), size);
107115
currentOffset += size;
@@ -160,8 +168,6 @@ bool BBFBuilder::addMetadata(const std::string& key, const std::string& value)
160168

161169
bool BBFBuilder::finalize()
162170
{
163-
uint64_t indexStart = currentOffset;
164-
165171
// Initialize XXH3 State
166172
XXH3_state_t* const state = XXH3_createState();
167173
if (state == nullptr) return false;
@@ -178,6 +184,7 @@ bool BBFBuilder::finalize()
178184
//write footer
179185
BBFFooter footer;
180186
footer.stringPoolOffset = currentOffset;
187+
footer.extraOffset = 0; // set the extraOffset to 0 since we aren't using it.
181188

182189
//fileStream.write(stringPool.data(), stringPool.size());
183190
//currentOffset += stringPool.size();
@@ -230,4 +237,42 @@ bool BBFBuilder::finalize()
230237
fileStream.write(reinterpret_cast<char*>(&footer), sizeof(BBFFooter));
231238
fileStream.close();
232239
return true;
240+
}
241+
242+
BBFMediaType detectTypeFromExtension(const std::string &extension)
243+
{
244+
std::string ext = extension;
245+
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
246+
247+
if (ext == ".png") return BBFMediaType::PNG;
248+
if (ext == ".jpg" || ext == ".jpeg") return BBFMediaType::JPG;
249+
if (ext == ".avif") return BBFMediaType::AVIF;
250+
if (ext == ".webp") return BBFMediaType::WEBP;
251+
if (ext == ".jxl") return BBFMediaType::JXL;
252+
if (ext == ".bmp") return BBFMediaType::BMP;
253+
if (ext == ".gif") return BBFMediaType::GIF;
254+
if (ext == ".tiff") return BBFMediaType::TIFF;
255+
256+
return BBFMediaType::UNKNOWN;
257+
}
258+
259+
std::string MediaTypeToStr(uint8_t type)
260+
{
261+
BBFMediaType mediaType = static_cast<BBFMediaType>(type);
262+
263+
switch (mediaType)
264+
{
265+
case BBFMediaType::AVIF: return ".avif";
266+
case BBFMediaType::PNG: return ".png";
267+
case BBFMediaType::JPG: return ".jpg";
268+
case BBFMediaType::WEBP: return ".webp";
269+
case BBFMediaType::JXL: return ".jxl";
270+
case BBFMediaType::BMP: return ".bmp";
271+
case BBFMediaType::GIF: return ".gif";
272+
case BBFMediaType::TIFF: return ".tiff";
273+
274+
case BBFMediaType::UNKNOWN:
275+
default:
276+
return ".png";
277+
}
233278
}

src/libbbf.h

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,31 @@
77
#include <fstream>
88
#include <unordered_map>
99

10-
#pragma pack(push, 1)
10+
// ENUM for filetypes
11+
enum class BBFMediaType: uint8_t
12+
{
13+
UNKNOWN = 0x00,
14+
AVIF = 0x01,
15+
PNG = 0x02,
16+
WEBP = 0x03,
17+
JXL = 0x04,
18+
BMP = 0x05,
19+
GIF = 0x07,
20+
TIFF = 0x08,
21+
JPG = 0x09
22+
};
1123

24+
BBFMediaType detectTypeFromExtension(const std::string &extension);
25+
std::string MediaTypeToStr(uint8_t type);
26+
27+
#pragma pack(push, 1)
1228

1329
struct BBFHeader
1430
{
1531
uint8_t magic[4]; // 0x42424631 (BBF1)
16-
uint8_t version; // 1
32+
uint8_t version; // Major version, 1
33+
uint32_t flags; // Reserved for now
34+
uint16_t headerLen; // Size of header
1735
uint64_t reserved; // set to 0
1836
};
1937

@@ -22,9 +40,14 @@ struct BBFAssetEntry
2240
{
2341
uint64_t offset; // Offset of the page
2442
uint64_t length; // length of the file
43+
uint64_t decodedLength;
2544
uint64_t xxh3Hash; // Hash of image
45+
2646
uint8_t type; // 0x01 - AVIF, 0x02 PNG, 0x03 JPG ... etc.
27-
uint8_t reserved[7]; // padding. Could use this in the future.
47+
uint8_t flags; // i.e. encryped or compressed
48+
49+
uint8_t padding[6]; // 64 BYTE struct
50+
uint64_t reserved[3]; // Reserved. Future proofing.
2851
};
2952

3053
// Create reading order
@@ -49,6 +72,16 @@ struct BBFMetadata
4972
uint32_t valOffset; // offset into String pool
5073
};
5174

75+
// BBF Extension table (Generic, not used)
76+
struct BBFExpansionHeader
77+
{
78+
uint32_t extensionType;
79+
uint32_t padding;
80+
uint64_t offset;
81+
uint64_t flags;
82+
uint64_t length;
83+
};
84+
5285
// Create the footer
5386
struct BBFFooter
5487
{
@@ -65,6 +98,8 @@ struct BBFFooter
6598
uint64_t metaTableOffset;
6699
uint32_t keyCount;
67100

101+
uint64_t extraOffset; // Point to an extra table in the future if we need.
102+
68103
uint64_t indexHash; // Integrity check, hash of everything between index start and the current position.
69104
uint8_t magic[4]; // 0x42424631 (BBF1) (Verification)
70105
};
@@ -74,7 +109,7 @@ struct BBFFooter
74109
class BBFBuilder
75110
{
76111
public:
77-
BBFBuilder(const std::string &outputFilemame);
112+
BBFBuilder(const std::string &outputFilename);
78113
~BBFBuilder();
79114

80115
bool addPage(const std::string& imagePath, uint8_t type, uint32_t flags = 0);

0 commit comments

Comments
 (0)