diff options
| author | Dylan <boss@tehbox.org> | 2026-05-04 18:36:15 +1200 |
|---|---|---|
| committer | Dylan <boss@tehbox.org> | 2026-05-04 18:36:15 +1200 |
| commit | a75bdd0e167140eeb4afb091c9dedd84474c8531 (patch) | |
| tree | 9c94262edc1c1eea4bd4977f76c7cd8ec6a43da1 /src | |
| parent | 500151be4794923cee6034c26881effeb1bb056d (diff) | |
| download | tehimage-a75bdd0e167140eeb4afb091c9dedd84474c8531.tar.gz tehimage-a75bdd0e167140eeb4afb091c9dedd84474c8531.zip | |
feat: Added a writer class
Also moved both the reader and writer class to the same files, named
files.{cpp,h}
Diffstat (limited to 'src')
| -rw-r--r-- | src/BMPImage.cpp | 38 | ||||
| -rw-r--r-- | src/PNGImage.cpp | 2 | ||||
| -rw-r--r-- | src/PNGImage.h | 2 | ||||
| -rw-r--r-- | src/files.cpp | 160 | ||||
| -rw-r--r-- | src/files.h | 87 | ||||
| -rw-r--r-- | src/reader.cpp | 137 | ||||
| -rw-r--r-- | src/reader.h | 53 |
7 files changed, 268 insertions, 211 deletions
diff --git a/src/BMPImage.cpp b/src/BMPImage.cpp index b79bc0c..a22e65d 100644 --- a/src/BMPImage.cpp +++ b/src/BMPImage.cpp @@ -1,5 +1,5 @@ #include "BMPImage.h" -#include "reader.h" +#include "files.h" #include <cstdint> #include <iostream> @@ -92,42 +92,42 @@ namespace TehImage int BMPImage::writeToFile(std::string filename) { - FILE* fd = fopen(filename.c_str(), "w"); + Writer writer(filename, LITTLE); char magic[] = "BM"; uint32_t rowSize = (bpp * width + 31)/32; uint32_t fileSize = 14 + 12 + rowSize*height*/*(bitDepth/8)*/8*3; - char zero[] = "\0\0\0\0"; + // char zero[] = "\0\0\0\0"; uint32_t offset = 26; uint32_t headerSize = 12; uint16_t width = this->width; uint16_t height = this->height; uint16_t colorPlanes = 1; - uint16_t bitsPerPixel = /*bitDepth*/8*3; - - fwrite(magic, sizeof(char), 2, fd); - fwrite(&fileSize, sizeof(uint32_t), 1, fd); - fwrite(zero, sizeof(char), 4, fd); - fwrite(&offset, sizeof(uint32_t), 1, fd); - fwrite(&headerSize, sizeof(uint32_t), 1, fd); + uint16_t bitsPerPixel = /*bpp*/8*3; + + writer.writeBytes(magic, 2); + writer.writeData(fileSize); + writer.zeroBytes(4); + writer.writeData(offset); + writer.writeData(headerSize); - fwrite(&width, sizeof(uint16_t), 1, fd); - fwrite(&height, sizeof(uint16_t), 1, fd); - fwrite(&colorPlanes, sizeof(uint16_t), 1, fd); - fwrite(&bitsPerPixel, sizeof(uint16_t), 1, fd); + writer.writeData(width); + writer.writeData(height); + writer.writeData(colorPlanes); + writer.writeData(bitsPerPixel); for(int y = height-1; y >= 0; y--) { for(int x = 0; x < width; x++) { Pixel& pixel = (*this)[x,y]; - fwrite(&pixel.b, sizeof(uint8_t), 1, fd); - fwrite(&pixel.g, sizeof(uint8_t), 1, fd); - fwrite(&pixel.r, sizeof(uint8_t), 1, fd); + writer.writeData(pixel.b); + writer.writeData(pixel.g); + writer.writeData(pixel.r); } - fwrite(zero, sizeof(char), (4-((width * 3)%4))%4, fd); + writer.zeroBytes((4-((width * 3)%4))%4); } - fclose(fd); + writer.close(); return 0; }; diff --git a/src/PNGImage.cpp b/src/PNGImage.cpp index 677c811..b9f956f 100644 --- a/src/PNGImage.cpp +++ b/src/PNGImage.cpp @@ -1,5 +1,5 @@ #include "PNGImage.h" -#include "reader.h" +#include "files.h" #include "zlib.h" #include "debug.h" diff --git a/src/PNGImage.h b/src/PNGImage.h index fa78e0e..1ed1be5 100644 --- a/src/PNGImage.h +++ b/src/PNGImage.h @@ -1,6 +1,6 @@ #pragma once -#include "reader.h" +#include "files.h" #include "image.h" #include "zlib.h" #include <cstddef> diff --git a/src/files.cpp b/src/files.cpp new file mode 100644 index 0000000..b757811 --- /dev/null +++ b/src/files.cpp @@ -0,0 +1,160 @@ +#include "files.h" + +#include <bit> +#include <cstddef> +#include <cstdint> +#include <cstdio> +#include <cstring> +#include <iostream> + + +using std::cout, std::endl; + +namespace TehImage +{ + // HELPERS + void convertEndian(uint8_t* in, uint8_t* out, std::size_t bytes, FileEndianness target) + { + constexpr bool LE = std::endian::native == std::endian::little; + constexpr bool BE = !LE; + if(target == NO_CONVERT || (target == BIG && BE) || (target == LITTLE && LE)) + { + for(int i = 0; i < bytes; i++) + { + out[i] = in[i]; + } + return; + } + // std::cout << "Converting" << std::endl; + for(int i = 0; i < bytes; i++) + { + out[bytes - 1 - i] = in[i]; + } + } + + + // READER + Reader::Reader(std::string filename, FileEndianness fileEndianness) + :fileEndianness(fileEndianness) + { + file = fopen(filename.c_str(), "rb"); + refreshBuffer(); + ready = true; + } + Reader::~Reader() + { + if(ready) + fclose(file); + } + + char Reader::readByte() + { + if(pos == READER_BUFFER_SIZE) + refreshBuffer(); + return buffer[pos++]; + } + + void Reader::refreshBuffer() + { + fread(buffer, sizeof(buffer), 1, file); + pos = 0; + } + + template<> uint8_t Reader::readData<uint8_t>() + { + return readByte(); + } + + DEFINE_INT_READER(uint16_t); + DEFINE_INT_READER(uint32_t); + DEFINE_INT_READER(uint64_t); + + + void Reader::readBytes(char* out, size_t len) + { + while(len > 0) + { + size_t bytesToRead = std::min(len, READER_BUFFER_SIZE - pos); + if(bytesToRead == 0) + { + refreshBuffer(); + continue; + } + memcpy(out, buffer + pos, bytesToRead); + out += bytesToRead; + len -= bytesToRead; + pos += bytesToRead; + } + } + + void Reader::skipBytes(size_t len) + { + while(len > 0) + { + size_t bytesToRead = std::min(len, READER_BUFFER_SIZE - pos); + if(bytesToRead == 0) + { + refreshBuffer(); + continue; + } + len -= bytesToRead; + pos += bytesToRead; + } + } + + void Reader::close() + { + fclose(file); + ready = false; + } + + + // WRITER + Writer::Writer(std::string filename, FileEndianness fileEndianness) + :fileEndianness(fileEndianness) + { + file = fopen(filename.c_str(), "w"); + ready = true; + } + + Writer::~Writer() + { + close(); + } + + void Writer::writeByte(char toWrite) + { + fwrite(&toWrite, sizeof(char), 1, file); + } + + void Writer::writeBytes(char toWrite[], std::size_t len) + { + // for(int i = 0; i < len; i++) + // cout << toWrite[i] << endl; + fwrite(toWrite, sizeof(char), len, file); + } + + void Writer::zeroBytes(std::size_t len) + { + char *zeroes = new char[len]; + memset(zeroes, 0, len); + writeBytes(zeroes, len); + delete[] zeroes; + } + + void Writer::close() + { + if(ready) + fclose(file); + ready = false; + } + + template <> void Writer::writeData(uint8_t toWrite) + { + writeByte(toWrite); + } + + DEFINE_INT_WRITER(uint16_t); + DEFINE_INT_WRITER(uint32_t); + DEFINE_INT_WRITER(uint64_t); +} diff --git a/src/files.h b/src/files.h new file mode 100644 index 0000000..fbbe8b7 --- /dev/null +++ b/src/files.h @@ -0,0 +1,87 @@ +#pragma once + +#include <cstdint> +#include <string> + +#define READER_BUFFER_SIZE 4096 + +#define DEFINE_INT_READER(TYPE) \ + template<> TYPE Reader::readData<TYPE>() \ + { \ + TYPE in, out; \ + readBytes((char*)&in, sizeof(TYPE)); \ + convertEndian((uint8_t*)&in, (uint8_t*)&out, sizeof(TYPE), fileEndianness); \ + return out; \ + } \ + + +#define DEFINE_INT_WRITER(TYPE) \ + template <> void Writer::writeData(TYPE toWrite) \ + { \ + TYPE converted; \ + convertEndian((uint8_t*)&toWrite, (uint8_t*)&converted, sizeof(TYPE), fileEndianness); \ + writeBytes((char*)&converted, sizeof(TYPE)); \ + } \ + +namespace TehImage +{ + enum FileEndianness + { + NO_CONVERT, + LITTLE, + BIG + }; + + void convertEndian(uint8_t* in, uint8_t* out, std::size_t bytes, FileEndianness target); + + class Reader + { + public: + //Bytes are big endian + Reader(std::string file, FileEndianness fileEndianness); + ~Reader(); + + template <typename T> + T readData(); + + char readByte(); + + void readBytes(char* out, std::size_t len); + + void skipBytes(std::size_t len); + + void close(); + private: + char buffer[READER_BUFFER_SIZE]; + std::size_t pos; + FILE* file; + bool ready = false; + FileEndianness fileEndianness; + + void refreshBuffer(); + }; + + class Writer + { + public: + //Bytes are big endian + Writer(std::string filename, FileEndianness fileEndianness); + ~Writer(); + + template <typename T> + void writeData(T toWrite); + + void writeByte(char toWrite); + + void writeBytes(char toWrite[], std::size_t len); + + void zeroBytes(std::size_t len); + + void close(); + private: + /* std::size_t pos; */ + FILE* file; + bool ready = false; + FileEndianness fileEndianness; + }; +} diff --git a/src/reader.cpp b/src/reader.cpp deleted file mode 100644 index f0b19ae..0000000 --- a/src/reader.cpp +++ /dev/null @@ -1,137 +0,0 @@ -#include "reader.h" - -#include "debug.h" - -#include <algorithm> -#include <cstddef> -#include <cstdint> -#include <cstring> -#include <iostream> - -namespace TehImage -{ - - Reader::Reader(std::string filename, FileEndianness fileEndianness) - { - file = fopen(filename.c_str(), "rb"); - refreshBuffer(); - ready = true; - this->fileEndianness = fileEndianness; - } - Reader::~Reader() - { - if(ready) - fclose(file); - } - - char Reader::readByte() - { - if(pos == BUFFER_SIZE) - refreshBuffer(); - return buffer[pos++]; - } - - void Reader::refreshBuffer() - { - fread(buffer, sizeof(buffer), 1, file); - pos = 0; - } - - void Reader::convertEndian(uint8_t* out, size_t bytes) - { - constexpr bool LE = std::endian::native == std::endian::little; - constexpr bool BE = !LE; - if(fileEndianness == NO_CONVERT || (fileEndianness == BIG && BE) || (fileEndianness == LITTLE && LE)) - { - for(int i = 0; i < bytes; i++) - { - out[i] = readByte(); - } - return; - } - for(int i = 0; i < bytes; i++) - { - out[bytes - 1 - i] = readByte(); - } - } - - template<> uint8_t Reader::readData<uint8_t>() - { - return readByte(); - } - - template<> uint16_t Reader::readData<uint16_t>() - { - uint16_t num = 0; - convertEndian((uint8_t*)&num, 2); - // for(int i = 0; i < 2; i++) - // { - // num += readByte() << (8 * (1-i)); - // } - return num; - } - - template<> uint32_t Reader::readData<uint32_t>() - { - uint32_t num = 0; - convertEndian((uint8_t*)&num, 4); - // for(int i = 0; i < 4; i++) - // { - // // uint8_t byte = readByte(); - // // debug(std::cout << std::hex << 0+byte << " "); - // num += ((uint8_t) readByte()) << (8 * (3-i)); - // } - // // debug(std::cout << std::dec << std::endl); - return num; - } - - template<> uint64_t Reader::readData<uint64_t>() - { - uint64_t num = 0; - convertEndian((uint8_t*)&num, 8); - // for(int i = 0; i < 8; i++) - // { - // num += readByte() << (8 * (7-i)); - // } - return num; - } - - void Reader::readBytes(char* out, size_t len) - { - while(len > 0) - { - size_t bytesToRead = std::min(len, BUFFER_SIZE - pos); - if(bytesToRead == 0) - { - refreshBuffer(); - continue; - } - memcpy(out, buffer + pos, bytesToRead); - out += bytesToRead; - len -= bytesToRead; - pos += bytesToRead; - } - } - - void Reader::skipBytes(size_t len) - { - while(len > 0) - { - size_t bytesToRead = std::min(len, BUFFER_SIZE - pos); - if(bytesToRead == 0) - { - refreshBuffer(); - continue; - } - len -= bytesToRead; - pos += bytesToRead; - } - } - - void Reader::close() - { - fclose(file); - ready = false; - } - -} diff --git a/src/reader.h b/src/reader.h deleted file mode 100644 index bb181e6..0000000 --- a/src/reader.h +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once - -#include <cstddef> -#include <cstdint> -#include <cstdio> -#include <string> - -#define BUFFER_SIZE 4096 - -namespace TehImage -{ - enum FileEndianness - { - NO_CONVERT, - LITTLE, - BIG - }; - - class Reader - { - public: - //Bytes are big endian - Reader(std::string file, FileEndianness fileEndianness); - ~Reader(); - - template <typename T> - T readData(); - - char readByte(); - - void readBytes(char* out, size_t len); - - void skipBytes(size_t len); - - void close(); - private: - char buffer[BUFFER_SIZE]; - size_t pos; - FILE* file; - bool ready = false; - FileEndianness fileEndianness; - - void refreshBuffer(); - void convertEndian(uint8_t* out, size_t bytes); - }; - - // template <typename T> - // T Reader::readData() - // { - // T num = 0; - // convertEndian((uint8_t*)&num, sizeof(T)); - // } -} |
