aboutsummaryrefslogtreecommitdiff
path: root/src/PNGImage.cpp
diff options
context:
space:
mode:
authorBossCode45 <boss@tehbox.org>2025-06-27 17:58:36 +1200
committerBossCode45 <boss@tehbox.org>2025-07-24 12:48:21 +1200
commit078b4e08fe3bccb7424dac76e158bf8bf48a182d (patch)
treea4f84f3fc346053c1c41990be4cc0867ab206cf5 /src/PNGImage.cpp
parenteed164fa72297efb69b624f3c58cb5deb339a974 (diff)
downloadtehimage-078b4e08fe3bccb7424dac76e158bf8bf48a182d.tar.gz
tehimage-078b4e08fe3bccb7424dac76e158bf8bf48a182d.zip
feat: Made it so that you can now convert between image subclasses
Also added the bitmap image subclass note: this is pretty hacky in how it works
Diffstat (limited to 'src/PNGImage.cpp')
-rw-r--r--src/PNGImage.cpp148
1 files changed, 67 insertions, 81 deletions
diff --git a/src/PNGImage.cpp b/src/PNGImage.cpp
index b7f28ce..50df7c6 100644
--- a/src/PNGImage.cpp
+++ b/src/PNGImage.cpp
@@ -14,9 +14,7 @@
using std::cout, std::endl;
-PNGImage::PNGImage(std::string filename)
- :reader(filename)
- ,idatData()
+PNGImage::PNGImage()
{
//cout << "Reader good" << endl;
REGISTER_CHUNK_READER(IHDR);
@@ -32,11 +30,6 @@ PNGImage::PNGImage(std::string filename)
//cout << "Chunk readers loaded" << endl;
- char signature[8];
- uint8_t expected[] = {137, 80, 78, 71, 13, 10, 26, 10};
- reader.readBytes(signature, 8);
- if(strncmp(signature, (char*)expected, 8) != 0)
- cout << "UH OH" << endl;
idatData = nullptr;
idatDataSize = 0;
@@ -50,14 +43,39 @@ PNGImage::~PNGImage()
idatDataSize = 0;
}
+int PNGImage::readFromFile(std::string filename)
+{
+ std::unique_ptr<Reader> readerMem(new Reader(filename));
+ reader = readerMem.get();
+
+ char signature[8];
+ uint8_t expected[] = {137, 80, 78, 71, 13, 10, 26, 10};
+ reader->readBytes(signature, 8);
+ if(strncmp(signature, (char*)expected, 8) != 0)
+ {
+ cout << "Not a PNG" << endl;
+ return 1;
+ }
+
+ while (readNextChunk()) {}
+
+ return 0;
+};
+
+int PNGImage::writeToFile(std::string filename)
+{
+ cout << "Not implemented" << endl;
+ return 2;
+};
+
bool PNGImage::readNextChunk()
{
if(end)
return false;
- uint32_t chunkSize = reader.readData<uint32_t>();
+ uint32_t chunkSize = reader->readData<uint32_t>();
char chunkType[4];
- reader.readBytes(chunkType, 4);
+ reader->readBytes(chunkType, 4);
std::string chunkName(chunkType, 4);
cout << "-------------" << endl;
cout << "|Chunk: " << chunkName << "|" << endl;
@@ -66,7 +84,7 @@ bool PNGImage::readNextChunk()
if(chunkReaders.count(chunkName) == 0)
{
cout << "Chunk reader not found!!!" << endl;
- reader.skipBytes(chunkSize + 4);
+ reader->skipBytes(chunkSize + 4);
if(islower(chunkType[0]))
{
cout << "\tAble to skip chunk" << endl;
@@ -79,20 +97,20 @@ bool PNGImage::readNextChunk()
void(PNGImage::*chunkReader)(uint32_t chunkSize) = chunkReaders.find(chunkName)->second;
(this->*chunkReader)(chunkSize);
- reader.skipBytes(4); // CRC
+ reader->skipBytes(4); // CRC
return true;
}
DEFINE_CHUNK_READER(IHDR)
{
- width = reader.readData<uint32_t>();
- height = reader.readData<uint32_t>();
- bitDepth = reader.readData<uint8_t>();
- colorType = reader.readData<uint8_t>();
- compressionMethod = reader.readData<uint8_t>();
- filterMethod = reader.readData<uint8_t>();
- interlaceMethod = reader.readData<uint8_t>();
+ width = reader->readData<uint32_t>();
+ height = reader->readData<uint32_t>();
+ bitDepth = reader->readData<uint8_t>();
+ colorType = reader->readData<uint8_t>();
+ compressionMethod = reader->readData<uint8_t>();
+ filterMethod = reader->readData<uint8_t>();
+ interlaceMethod = reader->readData<uint8_t>();
cout << "Width: " << width << ", Height: " << height << ", Bit depth: " << 0+bitDepth << ", Color type: " << 0+colorType << ", Compression method: " << 0+compressionMethod << ", Filter method: " << 0+filterMethod << ", Interlace method: " << 0+interlaceMethod << endl;
if(colorType != 2 && colorType != 6)
@@ -108,6 +126,7 @@ DEFINE_CHUNK_READER(IHDR)
bpp = colorValues * (bitDepth/8);
unsigned long imageDataSize = width * height * bpp;
+ //imageDataSize = imageDataSize;
cout << "Assigning " << imageDataSize << " bytes for image" << endl;
@@ -127,48 +146,48 @@ DEFINE_CHUNK_READER(iCCP)
{
cout << "!!! iCCP chunk reader not finished !!!" << endl;
std::string profileName;
- char c = reader.readByte();
+ char c = reader->readByte();
chunkSize--;
while(c != 0)
{
profileName.push_back(c);
- c = reader.readByte();
+ c = reader->readByte();
chunkSize--;
}
cout << profileName << endl;
- uint8_t compresssionMethod = reader.readByte();
+ uint8_t compresssionMethod = reader->readByte();
chunkSize--;
cout << 0+compresssionMethod << endl;
- uint8_t CMF = reader.readByte();
+ uint8_t CMF = reader->readByte();
uint8_t CM = CMF & 0b00001111;
uint8_t CINFO = (CMF & 0b11110000) >> 4;
chunkSize--;
- uint8_t FLG = reader.readByte();
+ uint8_t FLG = reader->readByte();
bool check = (CMF * 256 + FLG)%31 == 0;
bool FDICT = FLG & 0b00100000;
uint8_t FLEVEL = FLG & 0b11000000;
chunkSize--;
cout << std::bitset<4>(CM) << ", " << std::bitset<4>(CINFO) << ", " << (check?"Valid":"Failed checksum") << ", " << (FDICT?"Dict is present":"No dict present") << ", " << std::bitset<2>(FLEVEL) << endl;
char compressedData[chunkSize - 4];
- reader.readBytes(compressedData, chunkSize - 4);
+ reader->readBytes(compressedData, chunkSize - 4);
const int compressedSize = chunkSize - 4;
- uint32_t checkValue = reader.readData<uint32_t>();
+ uint32_t checkValue = reader->readData<uint32_t>();
//end = true;
}
DEFINE_CHUNK_READER(sRGB)
{
- renderingIntent = reader.readData<uint8_t>();
+ renderingIntent = reader->readData<uint8_t>();
cout << "Rendering intent: " << 0+renderingIntent << endl;
}
DEFINE_CHUNK_READER(eXIf)
{
char endian[4];
- reader.readBytes(endian, 4);
+ reader->readBytes(endian, 4);
for(int i = 0; i < 2; i++)
{
cout << endian[i];
@@ -179,7 +198,7 @@ DEFINE_CHUNK_READER(eXIf)
}
cout << endl;
char rest[chunkSize - 4];
- reader.readBytes(rest, chunkSize - 4);
+ reader->readBytes(rest, chunkSize - 4);
cout << std::hex;
for(int i = 0; i < chunkSize - 4; i++)
{
@@ -191,25 +210,25 @@ DEFINE_CHUNK_READER(eXIf)
DEFINE_CHUNK_READER(iDOT)
{
cout << "!!! Ignoring iDOT !!!" << endl;
- reader.skipBytes(chunkSize);
+ reader->skipBytes(chunkSize);
}
DEFINE_CHUNK_READER(pHYs)
{
- pixelsPerX = reader.readData<uint32_t>();
- pixelsPerY = reader.readData<uint32_t>();
- unit = reader.readData<uint8_t>();
+ pixelsPerX = reader->readData<uint32_t>();
+ pixelsPerY = reader->readData<uint32_t>();
+ unit = reader->readData<uint8_t>();
cout << "Pixels per unit (x): " << pixelsPerX << ", Pixels per unit (y): " << pixelsPerY << ", unit: " << 0+unit << endl;
}
DEFINE_CHUNK_READER(tIME)
{
- year = reader.readData<uint16_t>();
- month = reader.readData<uint8_t>();
- day = reader.readData<uint8_t>();
- hour = reader.readData<uint8_t>();
- minute = reader.readData<uint8_t>();
- second = reader.readData<uint8_t>();
+ year = reader->readData<uint16_t>();
+ month = reader->readData<uint8_t>();
+ day = reader->readData<uint8_t>();
+ hour = reader->readData<uint8_t>();
+ minute = reader->readData<uint8_t>();
+ second = reader->readData<uint8_t>();
cout << "Image last modified: " << 0+hour << ":" << 0+minute << ":" << 0+second << " " << 0+day << "-" << 0+month << "-" << 0+year << endl;
}
@@ -217,22 +236,22 @@ DEFINE_CHUNK_READER(tEXt)
{
std::string keyword;
- char c = reader.readByte();
+ char c = reader->readByte();
chunkSize--;
while(c != 0)
{
keyword.push_back(c);
- c = reader.readByte();
+ c = reader->readByte();
chunkSize--;
}
cout << keyword << endl;
std::string textString;
- c = reader.readByte();
+ c = reader->readByte();
chunkSize--;
while(chunkSize > 0)
{
textString.push_back(c);
- c = reader.readByte();
+ c = reader->readByte();
chunkSize--;
}
textString.push_back(c);
@@ -243,11 +262,11 @@ DEFINE_CHUNK_READER(IDAT)
{
if(idatDataSize == 0)
{
- uint8_t CMF = reader.readByte();
+ uint8_t CMF = reader->readByte();
uint8_t CM = (CMF & 0b11110000) >> 4;
uint8_t CINFO = CMF & 0b00001111;
chunkSize--;
- uint8_t FLG = reader.readByte();
+ uint8_t FLG = reader->readByte();
bool check = (CMF * 256 + FLG)%31 == 0;
bool FDICT = FLG & 0b00000100;
uint8_t FLEVEL = FLG & 0b00000011;
@@ -257,7 +276,7 @@ DEFINE_CHUNK_READER(IDAT)
}
idatData = (uint8_t *)realloc(idatData, idatDataSize + chunkSize);
- reader.readBytes((char *)&idatData[idatDataSize], chunkSize);
+ reader->readBytes((char *)&idatData[idatDataSize], chunkSize);
idatDataSize += chunkSize;
/*
@@ -268,7 +287,7 @@ DEFINE_CHUNK_READER(IDAT)
//cout << (int)puff((unsigned char*)imageData, &imageDataSize, (const unsigned char*)compressedData, &compressedSize) << endl;
*/
- //uint32_t checkValue = reader.readData<uint32_t>();
+ //uint32_t checkValue = reader->readData<uint32_t>();
//end = true;
}
@@ -293,28 +312,7 @@ DEFINE_CHUNK_READER(IEND)
uint8_t* pngImageData = new uint8_t[imageDataSize];
cout << "My inflate " << zlib.decodeData(idatData, idatDataSize, pngImageData, imageDataSize) << endl;
end = true;
- reader.close();
-
-
- FILE* fd = fopen("tmp.bmp", "w");
- char magic[] = "BM";
- fwrite(magic, sizeof(char), 2, fd);
- uint32_t fileSize = 14 + 12 + width*height*/*(bitDepth/8)*/8*3;
- fwrite(&fileSize, sizeof(uint32_t), 1, fd);
- char zero[] = "\0\0\0\0";
- fwrite(zero, sizeof(char), 4, fd);
- uint32_t offset = 26;
- fwrite(&offset, sizeof(uint32_t), 1, fd);
- uint32_t headerSize = 12;
- fwrite(&headerSize, sizeof(uint32_t), 1, fd);
- uint16_t width = this->width;
- uint16_t height = this->height;
- uint16_t colorPlanes = 1;
- uint16_t bitsPerPixel = /*bitDepth*/8*3;
- 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);
+ reader->close();
#define imageDataIndex(x, y) imageData[y*width*bpp + x]
#define pngImageDataIndex(x, y) pngImageData[y*(width*bpp + 1) + x + 1]
@@ -361,17 +359,5 @@ DEFINE_CHUNK_READER(IEND)
#undef pngImageDataIndex
#undef filterByte
- for(int y = height-1; y >= 0; y--)
- {
- for(int x = 0; x < width; x++)
- {
- Pixel<uint8_t> pixel = getPixel<uint8_t>(x, y);
- fwrite(&pixel.b, bitDepth/8, 1, fd);
- fwrite(&pixel.g, bitDepth/8, 1, fd);
- fwrite(&pixel.r, bitDepth/8, 1, fd);
- }
- }
-
delete [] pngImageData;
- fclose(fd);
}