commit b63a1e993c7d3f6346b69cc8f709835e1035c1e5
parent a0715f6de63b1242af01eb5640248bc06496475f
Author: Andrew Laack <andrew@laack.co>
Date: Fri, 11 Jul 2025 12:28:44 -0500
Refactored project structure, updated reading header info from image, verified both sides work as expected.
Diffstat:
6 files changed, 166 insertions(+), 56 deletions(-)
diff --git a/Makefile b/Makefile
@@ -0,0 +1,8 @@
+debug:
+ g++ -Wall -oO src/chunk.cpp src/encode.cpp -o build/debug.out -DDEBUG
+
+release:
+ g++ -Wall -O2 src/chunk.cpp src/encode.cpp -o build/release.out -DRELEASE
+
+clean:
+ rm -rf build/*
diff --git a/include/chunk.h b/include/chunk.h
@@ -0,0 +1,38 @@
+#include <iostream>
+#include <memory>
+#include <vector>
+
+
+// HEADER (this data is encoded in the image itself):
+// chunk number 4 bytes
+// characters 4 bytes
+// fnamelen 4 bytes
+// filename fnamelen
+
+struct Header {
+ uint chunkNumber;
+ uint characters;
+ uint fnameLength;
+ std::string filename;
+};
+
+class Chunk{
+
+private:
+ std::vector<char> chunk;
+ std::string extractEncodedSection(const std::string& fileString, uint& itr, int count);
+ std::string binaryToAscii(const std::string& binaryStr);
+
+public:
+ Chunk(std::string filename, uint start, uint size);
+ Chunk(std::vector<char> chunkData);
+ // read in the written chunk from tga format.
+ Chunk(std::string filename);
+ std::vector<char> getChunk();
+ void writeChunk(std::string filename);
+ void writeVideo(std::string filename);
+ void writeImage(std::string filename, uint chunkNumber, std::string originalFilename, uint x, uint y);
+ void print();
+ std::string toString();
+};
+
diff --git a/include/debug.h b/include/debug.h
@@ -0,0 +1,5 @@
+#ifdef DEBUG
+ #define LOG(x) std::cout << x << std::endl;
+#else
+ #define LOG(x)
+#endif
diff --git a/src/chunk.cpp b/src/chunk.cpp
@@ -1,8 +1,8 @@
-# include "chunk.h"
+# include "../include/chunk.h"
# include <iostream>
# include <fstream>
# include <bitset>
-# include <sstream>
+# include "../include/debug.h"
// read in saved chunk from file
@@ -22,14 +22,13 @@ Chunk::Chunk(std::string filename){
file.close();
- // header, comment, dims
+ // header (.tga header), comment (.tga comment), dims (.tga spec)
-
std::string header = "";
std::string comment = "";
std::string dims = "";
- int itr = 0;
+ uint itr = 0;
while (fileString[itr] != '\n'){
header += fileString[itr];
itr += 1;
@@ -42,16 +41,6 @@ Chunk::Chunk(std::string filename){
itr += 1;
}
- std::stringstream ss(comment);
- std::string token;
- std::vector<std::string> parts;
-
- while (ss >> token) {
- parts.push_back(token);
- }
-
- std::string last_part = parts.back();
- int characters = std::stoi(last_part);
itr += 1;
@@ -65,6 +54,45 @@ Chunk::Chunk(std::string filename){
std::string content = "";
+ // ENCODED HEADER (this data is encoded in the image itself):
+ // chunk number 4 bytes
+ // characters 4 bytes
+ // fnamelen 4 bytes
+ // filename fnamelen
+
+
+
+ Header head;
+
+ head.chunkNumber = 0;
+ head.characters = 0;
+ head.fnameLength = 0;
+ head.filename = "";
+
+ std::string encodedCNum = extractEncodedSection(fileString, itr, 4 * 8);
+ std::string encodedCharacters = extractEncodedSection(fileString, itr, 4 * 8);
+ std::string encodedFnameLength = extractEncodedSection(fileString, itr, 4 * 8);
+
+ head.characters = std::bitset<4*8>(encodedCharacters).to_ullong();
+ head.chunkNumber = std::bitset<4*8>(encodedCNum).to_ullong();
+ head.fnameLength = std::bitset<4*8>(encodedFnameLength).to_ullong();
+
+ std::string encodedFname = extractEncodedSection(fileString, itr, head.fnameLength);
+ head.filename = binaryToAscii(encodedFname);
+
+ LOG("ENCODED CNUM: " << encodedCNum)
+ LOG("CNUM: " << head.chunkNumber)
+
+ LOG("ENCODED CHARACTERS: " << encodedCharacters)
+ LOG("CHARACTERS: " << head.characters)
+
+ LOG("ENCODED FNAMELENGTH: " << encodedFnameLength)
+ LOG("FNAMELENGTH: " << head.fnameLength)
+
+
+ LOG("ENCODED FNAME: " << encodedFname)
+ LOG("FNAME: " << head.filename)
+
while(itr < fileString.size()){
if (fileString[itr] != ' ' && fileString[itr] != '\n'){
content += fileString[itr];
@@ -72,11 +100,10 @@ Chunk::Chunk(std::string filename){
itr += 1;
}
-
std::vector<char> bytes;
- for (int i = 0 ; i < characters; ++i){
+ for (int i = 0 ; i < head.characters; ++i){
std::string current = "";
@@ -130,7 +157,7 @@ void Chunk::writeChunk(std::string filename){
outFile.open(filename, std::ios::binary | std::ios::out);
- for(int i = 0 ; i < bytes.size(); ++i){
+ for(uint i = 0 ; i < bytes.size(); ++i){
outFile.write(&bytes[i], 1);
}
}
@@ -140,8 +167,6 @@ void Chunk::writeVideo(std::string filename){
std::cout << "NOT IMPLEMENTED" << std::endl;
}
-
-
// HEADER:
// - chunk number 4 bytes
// - characters 4 bytes
@@ -161,7 +186,8 @@ void Chunk::writeImage(std::string filename, uint chunkNumber, std::string origi
std::string chunkNumberEncoded = std::bitset<8*4>(chunkNumber).to_string();
std::string charactersEncoded = std::bitset<8*4>(data.size()).to_string();
- std::cout << data.size() << std::endl;
+
+ LOG(data.size())
std::string dims = std::to_string(x);
@@ -176,7 +202,7 @@ void Chunk::writeImage(std::string filename, uint chunkNumber, std::string origi
filenameEncoded += std::bitset<8>(filename.c_str()[i]).to_string();
}
- std::cout << filenameEncoded << std::endl;
+ LOG(filenameEncoded)
dims += " ";
dims += std::to_string(y);
@@ -190,14 +216,16 @@ void Chunk::writeImage(std::string filename, uint chunkNumber, std::string origi
std::string header = chunkNumberEncoded + charactersEncoded + filenameLengthEncoded + filenameEncoded;
- std::cout << chunkNumberEncoded.size() << " - " << chunkNumberEncoded << std::endl;
- std::cout << charactersEncoded.size() << " - " << charactersEncoded << std::endl;
- std::cout << filenameLengthEncoded.size() << " - " << filenameLengthEncoded << std::endl;
- std::cout << filenameEncoded.size() << " - " << filenameEncoded << std::endl;
- std::cout << "HEADER: " << header << std::endl;
+ LOG(chunkNumberEncoded.size() + " - " + chunkNumberEncoded)
+ LOG(charactersEncoded.size() + " - " + charactersEncoded)
+ LOG(filenameLengthEncoded.size() + " - " + filenameLengthEncoded)
+ LOG(filenameEncoded.size() + " - " + filenameEncoded)
+
+ LOG("HEADER: " + header)
if (x * y < (data.size() * 8) + header.size()){
+ LOG(data.size() * 8 + header.size())
throw std::invalid_argument("x and y dimensions are too small for the chunk.");
}
@@ -213,7 +241,7 @@ void Chunk::writeImage(std::string filename, uint chunkNumber, std::string origi
xPos += 1;
}
- std::cout << image << std::endl;
+ LOG(image)
int target = x * y;
int added = 0;
@@ -246,11 +274,54 @@ void Chunk::writeImage(std::string filename, uint chunkNumber, std::string origi
std::ofstream file = std::ofstream(filename);
file << image;
+}
+
+std::string Chunk::toString(){
+
+ std::string str = "";
+
+ for(uint i = 0 ; i < this->chunk.size(); ++i){
+ str += chunk[i];
+ }
+ return str;
}
void Chunk::print(){
- for(int i = 0 ; i < this->chunk.size(); ++i){
+ for(uint i = 0 ; i < this->chunk.size(); ++i){
std::cout << chunk[i];
}
}
+
+std::string Chunk::extractEncodedSection(const std::string& fileString, uint& itr, int count) {
+ std::string result;
+ int collected = 0;
+
+ while (collected < count && itr < fileString.size()) {
+ char ch = fileString[itr];
+
+ if (!std::isspace(static_cast<unsigned char>(ch))) {
+ result += ch;
+ collected += 1;
+ }
+ itr += 1;
+ }
+
+ return result;
+}
+
+std::string Chunk::binaryToAscii(const std::string& binaryStr) {
+ std::string asciiStr;
+
+ if (binaryStr.size() % 8 != 0) {
+ throw std::invalid_argument("Length must be multiple of 8");
+ }
+
+ for (size_t i = 0; i < binaryStr.size(); i += 8) {
+ std::string byteString = binaryStr.substr(i, 8);
+ char c = static_cast<char>(std::stoi(byteString, nullptr, 2));
+ asciiStr += c;
+ }
+
+ return asciiStr;
+}
diff --git a/src/chunk.h b/src/chunk.h
@@ -1,19 +0,0 @@
-#include <iostream>
-#include <memory>
-#include <vector>
-
-class Chunk{
-
-private:
- std::vector<char> chunk;
-public:
- Chunk(std::string filename, uint start, uint size);
- Chunk(std::vector<char> chunkData);
- // read in the written chunk from tga format.
- Chunk(std::string filename);
- std::vector<char> getChunk();
- void writeChunk(std::string filename);
- void writeVideo(std::string filename);
- void writeImage(std::string filename, uint chunkNumber, std::string originalFilename, uint x, uint y);
- void print();
-};
diff --git a/src/encode.cpp b/src/encode.cpp
@@ -1,6 +1,9 @@
#include <vector>
#include <fstream>
-#include "chunk.h"
+#include "../include/chunk.h"
+#include "iostream"
+#include "../include/debug.h"
+
int main(int argc, char* argv[]){
@@ -11,19 +14,23 @@ int main(int argc, char* argv[]){
std::string source = argv[1];
std::string destination = argv[2];
- Chunk chunk = Chunk(source, 0, 100000000);
+ Chunk chunk = Chunk(source, 0, 1000000000);
std::vector<char> bytes = chunk.getChunk();
std::ofstream outFile;
Chunk outChunk = Chunk(bytes);
outChunk.writeImage(destination, 1, source, 1920, 1080);
- std::cout << "BEFORE: " << std::endl;
- // outChunk.print();
- std::cout << std::endl;
Chunk readChunk = Chunk(destination);
- std::cout << "AFTER: " << std::endl;
- // readChunk.print();
- std::cout << std::endl;
+
+ std::string beforeChunk = readChunk.toString();
+ std::string afterChunk = outChunk.toString();
+
+ if (beforeChunk == afterChunk){
+ LOG("CHUNKS MATCH")
+ }
+ else{
+ LOG("CHUNKS DON'T MATCH")
+ }
return 0;
}