actually using lzw this time I think.

This commit is contained in:
Yggdrasil75
2025-11-18 08:22:16 -05:00
parent 8bd8df8e46
commit 315f64aa9c
2 changed files with 47 additions and 89 deletions

View File

@@ -81,7 +81,7 @@ void expandPixel(Grid2& grid, AnimationConfig config, std::vector<std::tuple<siz
Vec2 seedPOS = std::get<1>(seed); Vec2 seedPOS = std::get<1>(seed);
Vec4 seedColor = std::get<2>(seed); Vec4 seedColor = std::get<2>(seed);
std::vector<size_t> neighbors = grid.getNeighbors(id); std::vector<size_t> neighbors = grid.getNeighbors(id);
grid.setSize(id, grid.getSize(id)+4); //grid.setSize(id, grid.getSize(id)+4);
for (size_t neighbor : neighbors) { for (size_t neighbor : neighbors) {
if (visitedThisFrame.count(neighbor)) { if (visitedThisFrame.count(neighbor)) {
continue; continue;
@@ -107,12 +107,12 @@ void expandPixel(Grid2& grid, AnimationConfig config, std::vector<std::tuple<siz
newcolor = newcolor.clamp(0.0f, 1.0f); newcolor = newcolor.clamp(0.0f, 1.0f);
grid.setColor(neighbor, newcolor); grid.setColor(neighbor, newcolor);
//newseeds.emplace_back(neighbor, neipos, newcolor); newseeds.emplace_back(neighbor, neipos, newcolor);
} }
} }
//seeds.clear(); seeds.clear();
//seeds.shrink_to_fit(); seeds.shrink_to_fit();
//seeds = std::move(newseeds); seeds = std::move(newseeds);
} }
//bool exportavi(std::vector<std::vector<uint8_t>> frames, AnimationConfig config) { //bool exportavi(std::vector<std::vector<uint8_t>> frames, AnimationConfig config) {

View File

@@ -124,69 +124,40 @@ public:
throw std::runtime_error("LZ78 compression can only be applied to raw data"); throw std::runtime_error("LZ78 compression can only be applied to raw data");
} }
std::vector<std::vector<uint8_t>> repeats = getRepeats(); std::unordered_map<uint16_t, uint16_t> dict;
repeats = sortvecs(repeats); for (uint16_t i = 0; i < 256; i++) {
uint16_t nextDict = 1; dict[i] = i;
}
//std::vector<std::vector<uint8_t>> repeats = getRepeats();
//repeats = sortvecs(repeats);
std::vector<uint16_t> compressed; std::vector<uint16_t> compressed;
size_t cpos = 0; uint16_t nextDict = 256;
uint16_t cpos = 0;
for (const auto& rseq : repeats) { for (uint8_t byte : _data) {
if (!rseq.empty() && rseq.size() > 1 && overheadmap.size() < 65535) { uint16_t newval = cpos << 8 | byte;
overheadmap[nextDict] = rseq; if (dict.find(newval) != dict.end()) {
nextDict++; cpos = dict[newval];
}
}
while (cpos < _data.size()) {
bool found_match = false;
uint16_t best_dict_index = 0;
size_t best_match_length = 0;
// Iterate through dictionary in priority order (longest patterns first)
for (uint16_t dict_idx = 1; dict_idx <= overheadmap.size(); dict_idx++) {
const auto& dict_seq = overheadmap[dict_idx];
// Quick length check - if remaining data is shorter than pattern, skip
if (dict_seq.size() > (_data.size() - cpos)) {
continue;
}
// Check if this pattern matches at current position
bool match = true;
for (size_t i = 0; i < dict_seq.size(); ++i) {
if (_data[cpos + i] != dict_seq[i]) {
match = false;
break;
}
}
if (match) {
// Found a match - use it immediately (first match is best due to sorting)
best_dict_index = dict_idx;
best_match_length = dict_seq.size();
found_match = true;
break; // Stop searching - we found our match
}
}
if (found_match && best_match_length > 1) {
// Write dictionary reference
compressed.push_back(best_dict_index);
cpos += best_match_length;
} else { } else {
// Write literal: 0 followed by the literal byte _compressedData.push_back(cpos);
compressed.push_back(0); _compressedData.push_back(byte);
compressed.push_back(_data[cpos]); if (nextDict < 65535) {
cpos++; dict[newval] = nextDict++;
}
} }
cpos = 0;
}
if (cpos != 0) {
_compressedData.push_back(cpos);
_compressedData.push_back(0);
} }
ratio = compressed.size() / _data.size(); ratio = compressed.size() / _data.size();
sourceSize = _data.size(); sourceSize = _data.size();
_compressedData = std::move(compressed); // _compressedData = std::move(compressed);
_compressedData.shrink_to_fit(); // _compressedData.shrink_to_fit();
// Clear uncompressed data // Clear uncompressed data
_data.clear(); _data.clear();
@@ -367,42 +338,29 @@ private:
if (cformat != compresstype::LZ78) { if (cformat != compresstype::LZ78) {
throw std::runtime_error("Data is not LZ78 compressed"); throw std::runtime_error("Data is not LZ78 compressed");
} }
//std::cout << "why is this breaking? breakpoint f366" << std::endl;
std::vector<uint8_t> decompressedData;
decompressedData.reserve(sourceSize);
size_t cpos = 0; std::unordered_map<uint16_t, std::vector<uint8_t>> dict;
for (uint16_t i = 0; i < 256; i++) {
while (cpos < _compressedData.size()) { dict[i] = {static_cast<uint8_t>(i)};
uint16_t token = _compressedData[cpos++];
//std::cout << "why is this breaking? breakpoint f374." << cpos << std::endl;
if (token != 0) {
// Dictionary reference
auto it = overheadmap.find(token);
if (it != overheadmap.end()) {
const std::vector<uint8_t>& dict_entry = it->second;
decompressedData.insert(decompressedData.end(), dict_entry.begin(), dict_entry.end());
} else {
throw std::runtime_error("Invalid dictionary reference in compressed data");
}
} else {
// Literal byte
if (cpos < _compressedData.size()) {
decompressedData.push_back(static_cast<uint8_t>(_compressedData[cpos++]));
}
}
} }
_data = std::move(decompressedData); uint16_t nextdict = 256;
_compressedData.clear();
_compressedData.shrink_to_fit(); for (size_t i = 0; i < _compressedData.size(); i+=2) {
overheadmap.clear(); uint16_t cpos = _compressedData[i];
cformat = compresstype::RAW; uint8_t byte = _compressedData[i+1];
std::vector<uint8_t> seq = dict[cpos];
seq.push_back(byte);
_data.insert(_data.end(), seq.begin(), seq.end());
if (nextdict < 65535 && cpos != 0) {
dict[nextdict++] = seq;
}
}
cformat == compresstype::RAW;
return *this; return *this;
} }
frame& decompressFrameRLE() { frame& decompressFrameRLE() {
TIME_FUNCTION; TIME_FUNCTION;
std::vector<uint8_t> decompressed; std::vector<uint8_t> decompressed;