aviwriter has been wrong this whole time. fixed it. also fixed lack of alpha. and broke ratio. its decent now.

This commit is contained in:
Yggdrasil75
2025-11-18 14:07:10 -05:00
parent 7a4f200b9d
commit 4b978bfd6a
7 changed files with 250 additions and 176 deletions

View File

@@ -91,7 +91,9 @@
"__split_buffer": "cpp", "__split_buffer": "cpp",
"__tree": "cpp", "__tree": "cpp",
"stack": "cpp", "stack": "cpp",
"future": "cpp" "future": "cpp",
"coroutine": "cpp",
"resumable": "cpp"
}, },
"files.exclude": { "files.exclude": {
"**/*.rpyc": true, "**/*.rpyc": true,

View File

@@ -40,10 +40,13 @@ void Preview(Grid2 grid) {
TIME_FUNCTION; TIME_FUNCTION;
int width; int width;
int height; int height;
std::vector<uint8_t> rgbData; //std::vector<uint8_t> rgbData;
grid.getGridAsRGB(width,height,rgbData); frame rgbData = grid.getGridAsFrame(frame::colormap::RGB);
bool success = BMPWriter::saveBMP("output/grayscalesource.bmp", rgbData, width, height); bool success = BMPWriter::saveBMP("output/grayscalesource.bmp", rgbData);
if (!success) {
std::cout << "yo! this failed in Preview" << std::endl;
}
} }
std::vector<std::tuple<size_t, Vec2, Vec4>> pickSeeds(Grid2 grid, AnimationConfig config) { std::vector<std::tuple<size_t, Vec2, Vec4>> pickSeeds(Grid2 grid, AnimationConfig config) {
@@ -58,7 +61,7 @@ std::vector<std::tuple<size_t, Vec2, Vec4>> pickSeeds(Grid2 grid, AnimationConfi
for (int i = 0; i < config.numSeeds; ++i) { for (int i = 0; i < config.numSeeds; ++i) {
Vec2 point(xDist(gen), yDist(gen)); Vec2 point(xDist(gen), yDist(gen));
Vec4 color(colorDist(gen), colorDist(gen), colorDist(gen), 1.0f); Vec4 color(colorDist(gen), colorDist(gen), colorDist(gen), 255);
size_t id = grid.getPositionVec(point); size_t id = grid.getPositionVec(point);
grid.setColor(id, color); grid.setColor(id, color);
seeds.push_back(std::make_tuple(id,point, color)); seeds.push_back(std::make_tuple(id,point, color));
@@ -172,8 +175,10 @@ bool exportavi(std::vector<frame> frames, AnimationConfig config) {
int main() { int main() {
AnimationConfig config; AnimationConfig config;
// std::cout << "g2c2175" << std::endl;
Grid2 grid = setup(config); Grid2 grid = setup(config);
// std::cout << "g2c2178" << std::endl;
Preview(grid); Preview(grid);
std::vector<std::tuple<size_t, Vec2, Vec4>> seeds = pickSeeds(grid,config); std::vector<std::tuple<size_t, Vec2, Vec4>> seeds = pickSeeds(grid,config);
std::vector<frame> frames; std::vector<frame> frames;
@@ -189,6 +194,9 @@ int main() {
bgrframe.printCompressionStats(); bgrframe.printCompressionStats();
//(bgrframe, i + 1); //(bgrframe, i + 1);
frames.push_back(bgrframe); frames.push_back(bgrframe);
//bgrframe.decompress();
//BMPWriter::saveBMP(std::format("output/grayscalesource.{}.bmp", i), bgrframe);
bgrframe.compressFrameLZ78();
} }
} }

View File

@@ -480,6 +480,7 @@ public:
void getGridRegionAsRGB(const Vec2& minCorner, const Vec2& maxCorner, void getGridRegionAsRGB(const Vec2& minCorner, const Vec2& maxCorner,
int& width, int& height, std::vector<uint8_t>& rgbData) const { int& width, int& height, std::vector<uint8_t>& rgbData) const {
TIME_FUNCTION; TIME_FUNCTION;
// std::cout << "excessdebug g2.483" << std::endl;
// Calculate dimensions // Calculate dimensions
width = static_cast<int>(maxCorner.x - minCorner.x); width = static_cast<int>(maxCorner.x - minCorner.x);
height = static_cast<int>(maxCorner.y - minCorner.y); height = static_cast<int>(maxCorner.y - minCorner.y);
@@ -490,99 +491,133 @@ public:
rgbData.shrink_to_fit(); rgbData.shrink_to_fit();
return; return;
} }
// std::cout << "excessdebug g2.494" << std::endl;
// Initialize RGB data (3 bytes per pixel: R, G, B) // Initialize RGB data (3 bytes per pixel: R, G, B)
rgbData.resize(width * height * 3, 0); std::vector<Vec4> rgbaBuffer(width * height, Vec4(0.0f, 0.0f, 0.0f, 0.0f));
// For each position in the grid, find the corresponding pixel // For each position in the grid, find the corresponding pixel
//#pragma omp parallel for
for (const auto& [id, pos] : Positions) { for (const auto& [id, pos] : Positions) {
// std::cout << "excessdebug g2.501." << id << std::endl;
size_t size = Sizes.at(id); size_t size = Sizes.at(id);
// if (pos.x >= minCorner.x && pos.x < maxCorner.x &&
// pos.y >= minCorner.y && pos.y < maxCorner.y) {
// Calculate pixel coordinates // Calculate pixel coordinates
int pixelXm = static_cast<int>(pos.x - size/2 - minCorner.x); int pixelXm = static_cast<int>(pos.x - size/2 - minCorner.x);
int pixelXM = static_cast<int>(pos.x + size/2 - minCorner.x); int pixelXM = static_cast<int>(pos.x + size/2 - minCorner.x);
int pixelYm = static_cast<int>(pos.y - size/2 - minCorner.y); int pixelYm = static_cast<int>(pos.y - size/2 - minCorner.y);
int pixelYM = static_cast<int>(pos.y + size/2 - minCorner.y); int pixelYM = static_cast<int>(pos.y + size/2 - minCorner.y);
pixelXm = std::max(0, pixelXm); pixelXm = std::max(0, pixelXm);
pixelXM = std::min(width - 1, pixelXM); pixelXM = std::min(width - 1, pixelXM);
pixelYm = std::max(0, pixelYm); pixelYm = std::max(0, pixelYm);
pixelYM = std::min(height - 1, pixelYM); pixelYM = std::min(height - 1, pixelYM);
// std::cout << "excessdebug g2.514." << id << std::endl;
// Ensure within bounds // Ensure within bounds
if (pixelXM >= minCorner.x && pixelXm < width && pixelYM >= minCorner.y && pixelYm < height) { if (pixelXM >= minCorner.x && pixelXm < width && pixelYM >= minCorner.y && pixelYm < height) {
const Vec4& color = Colors.at(id); // std::cout << "excessdebug g2.518." << id << " - (" << pixelXm << "," << pixelYM << ")" << std::endl;
for (int py = pixelYm; py <= pixelYM; ++py){ const Vec4& color = Colors.at(id);
for (int px = pixelXm; px <= pixelXM; ++px){ float srcAlpha = color.a;
// Get color and convert to RGB float invSrcAlpha = 1.0f - srcAlpha;
int index = (py * width + px) * 3; for (int py = pixelYm; py <= pixelYM; ++py){
for (int px = pixelXm; px <= pixelXM; ++px){
// std::cout << "excessdebug g2.524." << id << " - (" << py << "," << px << ")" << std::endl;
int index = (py * width + px);
Vec4 dest = rgbaBuffer[index];
// Convert from [0,1] to [0,255] and store as RGB dest.r = color.r * srcAlpha + dest.r; // * invSrcAlpha;
rgbData[index] = static_cast<unsigned char>(color.r * 255); dest.g = color.g * srcAlpha + dest.g; // * invSrcAlpha;
rgbData[index + 1] = static_cast<unsigned char>(color.g * 255); dest.b = color.b * srcAlpha + dest.b; // * invSrcAlpha;
rgbData[index + 2] = static_cast<unsigned char>(color.b * 255); dest.a = srcAlpha + dest.a; // * invSrcAlpha;
} rgbaBuffer[index] = dest;
} }
} }
//} }
}
rgbData.resize(rgbaBuffer.size() * 3);
for (int i = 0; i < rgbaBuffer.size(); ++i) {
const Vec4& color = rgbaBuffer[i];
int bgrIndex = i * 3;
// Convert from [0,1] to [0,255] and store as RGB
rgbData[bgrIndex + 0] = static_cast<unsigned char>(color.r * 255);
rgbData[bgrIndex + 1] = static_cast<unsigned char>(color.g * 255);
rgbData[bgrIndex + 2] = static_cast<unsigned char>(color.b * 255);
} }
} }
// Get region as BGR // Get region as BGR
void getGridRegionAsBGR(const Vec2& minCorner, const Vec2& maxCorner, void getGridRegionAsBGR(const Vec2& minCorner, const Vec2& maxCorner,
int& width, int& height, std::vector<uint8_t>& bgrData) const { int& width, int& height, std::vector<uint8_t>& rgbData) const {
TIME_FUNCTION; TIME_FUNCTION;
// std::cout << "excessdebug g2.483" << std::endl;
// Calculate dimensions // Calculate dimensions
width = static_cast<int>(maxCorner.x - minCorner.x); width = static_cast<int>(maxCorner.x - minCorner.x);
height = static_cast<int>(maxCorner.y - minCorner.y); height = static_cast<int>(maxCorner.y - minCorner.y);
if (width <= 0 || height <= 0) { if (width <= 0 || height <= 0) {
width = height = 0; width = height = 0;
bgrData.clear(); rgbData.clear();
bgrData.shrink_to_fit(); rgbData.shrink_to_fit();
return; return;
} }
// std::cout << "excessdebug g2.494" << std::endl;
// Initialize RGB data (3 bytes per pixel: R, G, B) // Initialize RGB data (3 bytes per pixel: R, G, B)
bgrData.resize(width * height * 3, 0); std::vector<Vec4> rgbaBuffer(width * height, Vec4(0.0f, 0.0f, 0.0f, 0.0f));
// For each position in the grid, find the corresponding pixel // For each position in the grid, find the corresponding pixel
//#pragma omp parallel for
for (const auto& [id, pos] : Positions) { for (const auto& [id, pos] : Positions) {
// std::cout << "excessdebug g2.501." << id << std::endl;
size_t size = Sizes.at(id); size_t size = Sizes.at(id);
// if (pos.x >= minCorner.x && pos.x < maxCorner.x &&
// pos.y >= minCorner.y && pos.y < maxCorner.y) {
// Calculate pixel coordinates // Calculate pixel coordinates
int pixelXm = static_cast<int>(pos.x - size/2 - minCorner.x); int pixelXm = static_cast<int>(pos.x - size/2 - minCorner.x);
int pixelXM = static_cast<int>(pos.x + size/2 - minCorner.x); int pixelXM = static_cast<int>(pos.x + size/2 - minCorner.x);
int pixelYm = static_cast<int>(pos.y - size/2 - minCorner.y); int pixelYm = static_cast<int>(pos.y - size/2 - minCorner.y);
int pixelYM = static_cast<int>(pos.y + size/2 - minCorner.y); int pixelYM = static_cast<int>(pos.y + size/2 - minCorner.y);
pixelXm = std::max(0, pixelXm); pixelXm = std::max(0, pixelXm);
pixelXM = std::min(width - 1, pixelXM); pixelXM = std::min(width - 1, pixelXM);
pixelYm = std::max(0, pixelYm); pixelYm = std::max(0, pixelYm);
pixelYM = std::min(height - 1, pixelYM); pixelYM = std::min(height - 1, pixelYM);
// std::cout << "excessdebug g2.514." << id << std::endl;
// Ensure within bounds // Ensure within bounds
if (pixelXM >= minCorner.x && pixelXm < width && pixelYM >= minCorner.y && pixelYm < height) { if (pixelXM >= minCorner.x && pixelXm < width && pixelYM >= minCorner.y && pixelYm < height) {
const Vec4& color = Colors.at(id); // std::cout << "excessdebug g2.518." << id << " - (" << pixelXm << "," << pixelYM << ")" << std::endl;
for (int py = pixelYm; py <= pixelYM; ++py){ const Vec4& color = Colors.at(id);
for (int px = pixelXm; px <= pixelXM; ++px){ float srcAlpha = color.a;
// Get color and convert to RGB float invSrcAlpha = 1.0f - srcAlpha;
int index = (py * width + px) * 3; for (int py = pixelYm; py <= pixelYM; ++py){
for (int px = pixelXm; px <= pixelXM; ++px){
// std::cout << "excessdebug g2.524." << id << " - (" << py << "," << px << ")" << std::endl;
int index = (py * width + px);
Vec4 dest = rgbaBuffer[index];
// Convert from [0,1] to [0,255] and store as RGB dest.r = color.r * srcAlpha + dest.r; // * invSrcAlpha;
bgrData[index + 2] = static_cast<unsigned char>(color.r * 255); dest.g = color.g * srcAlpha + dest.g; // * invSrcAlpha;
bgrData[index + 1] = static_cast<unsigned char>(color.g * 255); dest.b = color.b * srcAlpha + dest.b; // * invSrcAlpha;
bgrData[index] = static_cast<unsigned char>(color.b * 255); dest.a = srcAlpha + dest.a; // * invSrcAlpha;
} rgbaBuffer[index] = dest;
} }
} }
//} }
}
rgbData.resize(rgbaBuffer.size() * 3);
for (int i = 0; i < rgbaBuffer.size(); ++i) {
const Vec4& color = rgbaBuffer[i];
int bgrIndex = i * 3;
// Convert from [0,1] to [0,255] and store as RGB
// rgbData.push_back(color.r);
// rgbData.push_back(color.g);
// rgbData.push_back(color.b);
rgbData[bgrIndex + 2] = static_cast<unsigned char>(color.r * 255);
rgbData[bgrIndex + 1] = static_cast<unsigned char>(color.g * 255);
rgbData[bgrIndex + 0] = static_cast<unsigned char>(color.b * 255);
} }
} }
@@ -599,7 +634,6 @@ public:
getGridRegionAsBGR(minCorner, maxCorner, width, height, bgrData); getGridRegionAsBGR(minCorner, maxCorner, width, height, bgrData);
} }
//frame stuff //frame stuff
frame getGridRegionAsFrameRGB(const Vec2& minCorner, const Vec2& maxCorner) const { frame getGridRegionAsFrameRGB(const Vec2& minCorner, const Vec2& maxCorner) const {
TIME_FUNCTION; TIME_FUNCTION;
@@ -624,79 +658,6 @@ public:
return resultFrame; return resultFrame;
} }
// Get region as frame (RGBA format)
frame getGridRegionAsFrameRGBA(const Vec2& minCorner, const Vec2& maxCorner) const {
TIME_FUNCTION;
int width, height;
std::vector<uint8_t> rgbData;
getGridRegionAsRGB(minCorner, maxCorner, width, height, rgbData);
// Convert RGB to RGBA
std::vector<uint8_t> rgbaData;
rgbaData.reserve(width * height * 4);
//#pragma omp parallel for
for (size_t i = 0; i < rgbData.size(); i += 3) {
rgbaData.push_back(rgbData[i]); // R
rgbaData.push_back(rgbData[i + 1]); // G
rgbaData.push_back(rgbData[i + 2]); // B
rgbaData.push_back(255); // A (fully opaque)
}
frame resultFrame(width, height, frame::colormap::RGBA);
resultFrame.setData(rgbaData);
return resultFrame;
}
// Get region as frame (BGRA format)
frame getGridRegionAsFrameBGRA(const Vec2& minCorner, const Vec2& maxCorner) const {
TIME_FUNCTION;
int width, height;
std::vector<uint8_t> bgrData;
getGridRegionAsBGR(minCorner, maxCorner, width, height, bgrData);
// Convert BGR to BGRA
std::vector<uint8_t> bgraData;
bgraData.reserve(width * height * 4);
//#pragma omp parallel for
for (size_t i = 0; i < bgrData.size(); i += 3) {
bgraData.push_back(bgrData[i]); // B
bgraData.push_back(bgrData[i + 1]); // G
bgraData.push_back(bgrData[i + 2]); // R
bgraData.push_back(255); // A (fully opaque)
}
frame resultFrame(width, height, frame::colormap::BGRA);
resultFrame.setData(bgraData);
return resultFrame;
}
// Get region as frame (Grayscale format)
frame getGridRegionAsFrameGrayscale(const Vec2& minCorner, const Vec2& maxCorner) const {
int width, height;
std::vector<uint8_t> rgbData;
getGridRegionAsRGB(minCorner, maxCorner, width, height, rgbData);
// Convert RGB to grayscale
std::vector<uint8_t> grayData;
grayData.reserve(width * height);
//#pragma omp parallel for
for (size_t i = 0; i < rgbData.size(); i += 3) {
uint8_t r = rgbData[i];
uint8_t g = rgbData[i + 1];
uint8_t b = rgbData[i + 2];
// Standard grayscale conversion formula
uint8_t gray = static_cast<uint8_t>(0.299 * r + 0.587 * g + 0.114 * b);
grayData.push_back(gray);
}
frame resultFrame(width, height, frame::colormap::B); // B for single channel/grayscale
resultFrame.setData(grayData);
return resultFrame;
}
// Get entire grid as frame with specified format // Get entire grid as frame with specified format
frame getGridAsFrame(frame::colormap format = frame::colormap::RGB) { frame getGridAsFrame(frame::colormap format = frame::colormap::RGB) {
TIME_FUNCTION; TIME_FUNCTION;
@@ -711,22 +672,13 @@ public:
case frame::colormap::BGR: case frame::colormap::BGR:
Frame = std::move(getGridRegionAsFrameBGR(minCorner, maxCorner)); Frame = std::move(getGridRegionAsFrameBGR(minCorner, maxCorner));
break; break;
case frame::colormap::RGBA:
Frame = std::move(getGridRegionAsFrameRGBA(minCorner, maxCorner));
break;
case frame::colormap::BGRA:
Frame = std::move(getGridRegionAsFrameBGRA(minCorner, maxCorner));
break;
case frame::colormap::B:
Frame = std::move(getGridRegionAsFrameGrayscale(minCorner, maxCorner));
break;
default: default:
Frame = std::move(getGridRegionAsFrameRGB(minCorner, maxCorner)); Frame = std::move(getGridRegionAsFrameRGB(minCorner, maxCorner));
break; break;
} }
//Frame.compressFrameDiff(); //Frame.compressFrameDiff();
//Frame.compressFrameRLE(); //Frame.compressFrameRLE();
Frame.compressFrameLZ78(); //Frame.compressFrameLZ78();
return Frame; return Frame;
} }
@@ -755,7 +707,6 @@ public:
} }
} }
//get bounding box //get bounding box
void getBoundingBox(Vec2& minCorner, Vec2& maxCorner) { void getBoundingBox(Vec2& minCorner, Vec2& maxCorner) {
TIME_FUNCTION; TIME_FUNCTION;

View File

@@ -8,7 +8,6 @@ class SpriteMap2 : public Grid2 {
private: private:
// id, sprite // id, sprite
//std::unordered_map<size_t, std::shared_ptr<Grid2>> Sprites;
std::unordered_map<size_t, frame> spritesComped; std::unordered_map<size_t, frame> spritesComped;
std::unordered_map<size_t, int> Layers; std::unordered_map<size_t, int> Layers;
std::unordered_map<size_t, float> Orientations; std::unordered_map<size_t, float> Orientations;
@@ -27,7 +26,124 @@ public:
return spritesComped.at(id); return spritesComped.at(id);
} }
void setSprite(size_t id, const frame& sprite) {
spritesComped[id] = sprite;
}
int getLayer(size_t id) {
return Layers.at(id);
}
size_t setLayer(size_t id, int layer) {
Layers[id] = layer;
return id;
}
float getOrientation(size_t id) {
return Orientations.at(id);
}
size_t setOrientation(size_t id, float orientation) {
Orientations[id] = orientation;
}
void getGridRegionAsBGR(const Vec2& minCorner, const Vec2& maxCorner, int& width, int& height, std::vector<uint8_t>& bgrData) const {
TIME_FUNCTION;
// Calculate dimensions
width = static_cast<int>(maxCorner.x - minCorner.x);
height = static_cast<int>(maxCorner.y - minCorner.y);
if (width <= 0 || height <= 0) {
width = height = 0;
bgrData.clear();
bgrData.shrink_to_fit();
return;
}
// Initialize RGB data (3 bytes per pixel: R, G, B)
std::vector<Vec4> rgbaBuffer(width * height, Vec4(0.0f, 0.0f, 0.0f, 0.0f));
// For each position in the grid, find the corresponding pixel
for (const auto& [id, pos] : Positions) {
size_t size = Sizes.at(id);
// Calculate pixel coordinates
int pixelXm = static_cast<int>(pos.x - size/2 - minCorner.x);
int pixelXM = static_cast<int>(pos.x + size/2 - minCorner.x);
int pixelYm = static_cast<int>(pos.y - size/2 - minCorner.y);
int pixelYM = static_cast<int>(pos.y + size/2 - minCorner.y);
pixelXm = std::max(0, pixelXm);
pixelXM = std::min(width - 1, pixelXM);
pixelYm = std::max(0, pixelYm);
pixelYM = std::min(height - 1, pixelYM);
// Ensure within bounds
if (pixelXM >= minCorner.x && pixelXm < width && pixelYM >= minCorner.y && pixelYm < height) {
const Vec4& color = Colors.at(id);
float srcAlpha = color.a;
float invSrcAlpha = 1.0f - srcAlpha;
for (int py = pixelYm; py <= pixelYM; ++py){
for (int px = pixelXm; px <= pixelXM; ++px){
int index = (py * width + px) * 3;
Vec4& dest = rgbaBuffer[index];
dest.r = color.r * srcAlpha + dest.r * invSrcAlpha;
dest.g = color.g * srcAlpha + dest.g * invSrcAlpha;
dest.b = color.b * srcAlpha + dest.b * invSrcAlpha;
dest.a = srcAlpha + dest.a * invSrcAlpha;
}
}
}
}
bgrData.resize(dest.size() * 4);
for (int i = 0; i < width * height; ++i) {
const Vec4& color = rgbaBuffer[i];
int bgrIndex = i * 3;
// Convert from [0,1] to [0,255] and store as BGR
bgrData[bgrIndex + 0] = static_cast<uint8_t>(color.b * 255); // Blue
bgrData[bgrIndex + 1] = static_cast<uint8_t>(color.g * 255); // Green
bgrData[bgrIndex + 2] = static_cast<uint8_t>(color.r * 255); // Red
}
}
size_t removeSprite(size_t id) {
spritesComped.erase(id);
Layers.erase(id);
Orientations.erase(id);
return removeID(id);
}
// Remove sprite by position
size_t removeSprite(const Vec2& pos) {
size_t id = getPositionVec(pos);
return removeSprite(id);
}
void clear() {
Grid2::clear();
spritesComped.clear();
Layers.clear();
Orientations.clear();
spritesComped.rehash(0);
Layers.rehash(0);
Orientations.rehash(0);
}
// Get all sprite IDs
std::vector<size_t> getAllSpriteIDs() {
return getAllIDs();
}
// Check if ID has a sprite
bool hasSprite(size_t id) const {
return spritesComped.find(id) != spritesComped.end();
}
// Get number of sprites
size_t getSpriteCount() const {
return spritesComped.size();
}
}; };

View File

@@ -157,29 +157,29 @@ private:
break; break;
case frame::colormap::RGBA: case frame::colormap::RGBA:
for (uint32_t x = 0; x < width; ++x) { for (uint32_t x = 0; x < width; ++x) {
dstRow[x * 3] = srcRow[x * 4]; // R dstRow[x * 3 + 2] = srcRow[x * 4 + 0]; // R
dstRow[x * 3 + 1] = srcRow[x * 4 + 1]; // G dstRow[x * 3 + 1] = srcRow[x * 4 + 1]; // G
dstRow[x * 3 + 2] = srcRow[x * 4 + 2]; // B dstRow[x * 3 + 0] = srcRow[x * 4 + 2]; // B
} }
break; break;
case frame::colormap::BGR: case frame::colormap::BGR:
for (uint32_t x = 0; x < width; ++x) { for (uint32_t x = 0; x < width; ++x) {
dstRow[x * 3] = srcRow[x * 3 + 2]; // R dstRow[x * 3 + 2] = srcRow[x * 3 + 2]; // R
dstRow[x * 3 + 1] = srcRow[x * 3 + 1]; // G dstRow[x * 3 + 1] = srcRow[x * 3 + 1]; // G
dstRow[x * 3 + 2] = srcRow[x * 3]; // B dstRow[x * 3 + 0] = srcRow[x * 3 + 0]; // B
} }
break; break;
case frame::colormap::BGRA: case frame::colormap::BGRA:
for (uint32_t x = 0; x < width; ++x) { for (uint32_t x = 0; x < width; ++x) {
dstRow[x * 3] = srcRow[x * 4 + 2]; // R dstRow[x * 3 + 2] = srcRow[x * 4 + 2]; // R
dstRow[x * 3 + 1] = srcRow[x * 4 + 1]; // G dstRow[x * 3 + 1] = srcRow[x * 4 + 1]; // G
dstRow[x * 3 + 2] = srcRow[x * 4]; // B dstRow[x * 3 + 0] = srcRow[x * 4 + 0]; // B
} }
break; break;
case frame::colormap::B: case frame::colormap::B:
for (uint32_t x = 0; x < width; ++x) { for (uint32_t x = 0; x < width; ++x) {
uint8_t gray = srcRow[x]; uint8_t gray = srcRow[x];
dstRow[x * 3] = gray; // R dstRow[x * 3 + 0] = gray; // R
dstRow[x * 3 + 1] = gray; // G dstRow[x * 3 + 1] = gray; // G
dstRow[x * 3 + 2] = gray; // B dstRow[x * 3 + 2] = gray; // B
} }

View File

@@ -8,6 +8,7 @@
#include <algorithm> #include <algorithm>
#include <filesystem> #include <filesystem>
#include "../vectorlogic/vec3.hpp" #include "../vectorlogic/vec3.hpp"
#include "frame.hpp"
class BMPWriter { class BMPWriter {
private: private:
@@ -137,6 +138,10 @@ public:
return true; return true;
} }
static bool saveBMP(const std::string& filename, frame& frame) {
return saveBMP(filename, frame.getData(), frame.getWidth(), frame.getHeight());
}
private: private:
static bool saveBMP(const std::string& filename, const std::vector<std::vector<Vec3>>& pixels, int width, int height) { static bool saveBMP(const std::string& filename, const std::vector<std::vector<Vec3>>& pixels, int width, int height) {
// Create directory if needed // Create directory if needed

View File

@@ -15,6 +15,7 @@
#include <future> #include <future>
#include <mutex> #include <mutex>
#include <atomic> #include <atomic>
#include "../timing_decorator.hpp"
class frame { class frame {
private: private:
@@ -47,10 +48,11 @@ public:
colormap colorFormat = colormap::RGB; colormap colorFormat = colormap::RGB;
compresstype cformat = compresstype::RAW; compresstype cformat = compresstype::RAW;
size_t getWidth() { const size_t& getWidth() {
return width; return width;
} }
size_t getHeight() {
const size_t& getHeight() {
return height; return height;
} }
frame() {}; frame() {};
@@ -73,6 +75,8 @@ public:
_compressedData.clear(); _compressedData.clear();
_compressedData.shrink_to_fit(); _compressedData.shrink_to_fit();
overheadmap.clear(); overheadmap.clear();
sourceSize = data.size();
} }
const std::vector<uint8_t>& getData() const { const std::vector<uint8_t>& getData() const {
@@ -221,9 +225,6 @@ public:
// Get compressed size including dictionary overhead // Get compressed size including dictionary overhead
size_t getTotalCompressedSize() const { size_t getTotalCompressedSize() const {
size_t baseSize = getCompressedDataSize(); size_t baseSize = getCompressedDataSize();
if (cformat == compresstype::LZ78) {
baseSize += getDictionarySize();
}
return baseSize; return baseSize;
} }
@@ -237,7 +238,7 @@ public:
} }
size_t getCompressedDataSize() const { size_t getCompressedDataSize() const {
return _compressedData.size(); return _compressedData.size() * 2;
} }
void printCompressionInfo() const { void printCompressionInfo() const {
@@ -274,16 +275,9 @@ public:
} }
void printCompressionStats() const { void printCompressionStats() const {
if (cformat == compresstype::LZ78) { std::cout << "[" << getCompressionTypeString() << "] "
std::cout << "[" << getCompressionTypeString() << "] " << getSourceSize() << "B -> " << getTotalCompressedSize() << "B "
<< "Source Size: " << getSourceSize() << " bytes" << "(ratio: " << getCompressionRatio() << ":1)" << std::endl;
<< getTotalCompressedSize() << "B "
<< "(ratio: " << getCompressionRatio() << ":1)" << std::endl;
} else {
std::cout << "[" << getCompressionTypeString() << "] "
<< getSourceSize() << "B -> " << getTotalCompressedSize() << "B "
<< "(ratio: " << getCompressionRatio() << ":1)" << std::endl;
}
} }
// Get compression type as string // Get compression type as string
@@ -318,8 +312,6 @@ public:
} }
private: private:
//moving decompression to private to prevent breaking stuff from external calls
std::vector<std::vector<uint8_t>> sortvecs(std::vector<std::vector<uint8_t>> source) { std::vector<std::vector<uint8_t>> sortvecs(std::vector<std::vector<uint8_t>> source) {
std::sort(source.begin(), source.end(), [](const std::vector<uint8_t> & a, const std::vector<uint8_t> & b) {return a.size() > b.size();}); std::sort(source.begin(), source.end(), [](const std::vector<uint8_t> & a, const std::vector<uint8_t> & b) {return a.size() > b.size();});
return source; return source;