diff options
| author | Dylan <boss@tehbox.org> | 2025-08-08 15:22:35 +1200 |
|---|---|---|
| committer | Dylan <boss@tehbox.org> | 2025-08-08 15:38:59 +1200 |
| commit | 41ddbec10d11b01ccc10bf7e1dc862a9f3e4c85f (patch) | |
| tree | c4775a629588419803320818fc1458f6d35e8ae8 | |
| parent | 5823a8dff5c6c565c9b253b122d2baeb767b72e2 (diff) | |
| download | tehimage-41ddbec10d11b01ccc10bf7e1dc862a9f3e4c85f.tar.gz tehimage-41ddbec10d11b01ccc10bf7e1dc862a9f3e4c85f.zip | |
feat: Simplified APIv0.0.1
Had to restrict images to 8 bit depth sadly
This could potentially be changed in the future by setting bit depth
with templates and changing the data to be the specified bit depth
| -rw-r--r-- | GNUmakefile | 12 | ||||
| -rw-r--r-- | src/BMPImage.cpp | 2 | ||||
| -rw-r--r-- | src/PNGImage.cpp | 35 | ||||
| -rw-r--r-- | src/image.cpp | 10 | ||||
| -rw-r--r-- | src/image.h | 44 |
5 files changed, 47 insertions, 56 deletions
diff --git a/GNUmakefile b/GNUmakefile index af8403a..ae7e0db 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -4,12 +4,14 @@ SOURCE_DIR := ./src LIB_DIR := ./lib INCLUDE_DIR := ./include TEST_SRC_DIR := ./test +out ?= +INSTALL_DIR = $(out) # Flags CXX := g++ -CXXFLAGS := -std=c++20 -fsanitize=address -g +CXXFLAGS := -std=c++23 -fsanitize=address -g LINKFLAGS := -static-libasan -TEST_CXXFLAGS := -std=c++20 -I$(INCLUDE_DIR) -fsanitize=address -g +TEST_CXXFLAGS := -std=c++23 -I$(INCLUDE_DIR) -fsanitize=address -g TEST_LINKFLAGS := -L$(LIB_DIR) -ltehimage -static-libasan # Outputs @@ -44,11 +46,15 @@ $(OBJS_DIR)/%.o: $(TEST_SRC_DIR)/%.cpp $(TEST_SOURCE) $(TEST_HEADERS) # Phony -.PHONY: clean test +.PHONY: clean test install clean: rm -f $(LIB) rm -f $(OBJS_DIR)/*.o rm -f $(TEST) +install: $(LIB) + install -D -m 755 $(LIB) $(INSTALL_DIR)/lib/libtehimage.so + install -D -m 644 $(INCLUDE_DIR)/* $(INSTALL_DIR)/include/ + test: $(TEST) diff --git a/src/BMPImage.cpp b/src/BMPImage.cpp index df2c745..b9b2c96 100644 --- a/src/BMPImage.cpp +++ b/src/BMPImage.cpp @@ -39,7 +39,7 @@ int BMPImage::writeToFile(std::string filename) { for(int x = 0; x < width; x++) { - Pixel pixel = getPixel(x, y); + 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); diff --git a/src/PNGImage.cpp b/src/PNGImage.cpp index b6002ca..7df04ad 100644 --- a/src/PNGImage.cpp +++ b/src/PNGImage.cpp @@ -78,9 +78,11 @@ bool PNGImage::readNextChunk() char chunkType[4]; reader->readBytes(chunkType, 4); std::string chunkName(chunkType, 4); - cout << "-------------" << endl; - cout << "|Chunk: " << chunkName << "|" << endl; - cout << "-------------" << endl; + debug( + cout << "-------------" << endl; + cout << "|Chunk: " << chunkName << "|" << endl; + cout << "-------------" << endl; + ); if(chunkReaders.count(chunkName) == 0) { @@ -117,6 +119,9 @@ DEFINE_CHUNK_READER(IHDR) if(colorType != 2 && colorType != 6) throw std::invalid_argument("Only color types 2 and 6 are supported"); + if(bitDepth != 8) + throw std::invalid_argument("Only bit depth of 8 is supported"); + switch(colorType) { case 2: colorValues = 3; break; @@ -126,12 +131,12 @@ DEFINE_CHUNK_READER(IHDR) bpp = colorValues * (bitDepth/8); - unsigned long imageDataSize = width * height * bpp; - //imageDataSize = imageDataSize; + // unsigned long imageDataSize = width * height * bpp; + // imageDataSize = imageDataSize; - cout << "Assigning " << imageDataSize << " bytes for image" << endl; + // cout << "Assigning " << imageDataSize << " bytes for image" << endl; - imageData = std::make_unique<uint8_t[]>(imageDataSize); + pixels = std::make_unique<Pixel[]>(width * height); /* Scanline<RGBPixel<uint8_t>>* lines = new Scanline<RGBPixel<uint8_t>> [height]; @@ -319,11 +324,12 @@ DEFINE_CHUNK_READER(IEND) { unsigned long imageDataSize = height * (width * bpp + 1); uint8_t* pngImageData = new uint8_t[imageDataSize]; + uint8_t* rawImage = new uint8_t[width * height * bpp]; cout << "My inflate " << zlib.decodeData(idatData, idatDataSize, pngImageData, imageDataSize) << endl; end = true; reader->close(); -#define imageDataIndex(x, y) imageData[y*width*bpp + x] +#define imageDataIndex(x, y) rawImage[y*width*bpp + x] #define pngImageDataIndex(x, y) pngImageData[y*(width*bpp + 1) + x + 1] #define filterByte(y) pngImageDataIndex(-1, y) @@ -375,6 +381,19 @@ DEFINE_CHUNK_READER(IEND) #undef imageDataIndex #undef pngImageDataIndex #undef filterByte + + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + (*this)[x, y].r = rawImage[(y*width + x)*colorValues]; + (*this)[x, y].g = rawImage[(y*width + x)*colorValues + 1*bitDepth/8]; + (*this)[x, y].b = rawImage[(y*width + x)*colorValues + 2*bitDepth/8]; + (*this)[x, y].a = (colorValues == 4)?rawImage[(y*width + x)*colorValues]:255; + + } + } delete [] pngImageData; + delete [] rawImage; } diff --git a/src/image.cpp b/src/image.cpp index e23e3f6..77fe63c 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -15,7 +15,11 @@ Image::Image(const Image& other) this->filterMethod = other.filterMethod; this->interlaceMethod = other.interlaceMethod; - unsigned long imageDataSize = width * height * bpp; - imageData = std::make_unique<uint8_t[]>(imageDataSize); - std::copy_n(other.imageData.get(), imageDataSize, imageData.get()); + pixels = std::make_unique<Pixel[]>(width*height); + std::copy_n(other.pixels.get(), width*height, pixels.get()); } + +Pixel& Image::operator[](int x, int y) +{ + return pixels[x + y*width]; +}; diff --git a/src/image.h b/src/image.h index be26437..7a7ba31 100644 --- a/src/image.h +++ b/src/image.h @@ -5,17 +5,15 @@ #include <memory> #include <string> -template <typename T> struct Pixel { - T r, g, b, a; + uint8_t r, g, b, a; }; - class Image { protected: - std::unique_ptr<uint8_t[]> imageData; + std::unique_ptr<Pixel[]> pixels; // uint8_t* imageData; uint8_t colorValues; uint8_t bpp; @@ -28,8 +26,7 @@ public: virtual int readFromFile(std::string filename) = 0; virtual int writeToFile(std::string filename) = 0; - template <typename T = uint8_t> - Pixel<T> getPixel(unsigned int x, unsigned int y); + Pixel& operator[](int x, int y); uint32_t width = 0; uint32_t height = 0; @@ -39,38 +36,3 @@ public: uint8_t filterMethod; uint8_t interlaceMethod; }; - - -template <typename T> -Pixel<T> Image::getPixel(unsigned int x, unsigned int y) -{ - Pixel<T> pixel; - - if(sizeof(T)*8 == bitDepth) - { - unsigned long rIndex = y * width * colorValues + x * colorValues; - pixel.r = ((T*)imageData.get())[rIndex]; - pixel.g = ((T*)imageData.get())[rIndex + 1]; - pixel.b = ((T*)imageData.get())[rIndex + 2]; - - if(colorValues == 4) - pixel.a = ((T*)imageData.get())[rIndex + 3]; - else - pixel.a = 0; - } - else - { - unsigned long startIndex = y * width * colorValues * bitDepth/8 + x * colorValues * bitDepth/8; - - uint32_t pixelData[4]; - int tsize = sizeof(T); - int bytesToTake = std::min(tsize, bitDepth/8); - for(int i = 0; i < colorValues; i++) - { - for(int j = 0; j < bytesToTake; j++) - pixelData[i] += imageData[startIndex++] << (bitDepth - j*8 - 8); - startIndex += bitDepth/8 - bytesToTake; - } - } - return pixel; -} |
