diff options
| -rw-r--r-- | src/PNGImage.cpp | 94 | ||||
| -rw-r--r-- | src/debug.h | 2 | ||||
| -rw-r--r-- | src/zlib.cpp | 40 | ||||
| -rw-r--r-- | test/main.cpp | 17 |
4 files changed, 107 insertions, 46 deletions
diff --git a/src/PNGImage.cpp b/src/PNGImage.cpp index 1e46f22..22a6218 100644 --- a/src/PNGImage.cpp +++ b/src/PNGImage.cpp @@ -77,7 +77,10 @@ namespace TehImage writer->writeBytes((char*)signature, 8); writeIHDR(); + writeIDAT(); writeIEND(); + + writer->close(); return 2; }; @@ -88,18 +91,21 @@ namespace TehImage return false; uint32_t chunkSize = reader->readData<uint32_t>(); - char chunkType[4]; + char chunkType[5]; reader->readBytes(chunkType, 4); + chunkType[4] = 0; std::string chunkName(chunkType, 4); - debug( - cout << "-------------" << endl; - cout << "|Chunk: " << chunkName << "|" << endl; - cout << "-------------" << endl; - ); + cout << "-------------" << endl; + cout << "|Chunk: " << chunkName << "|" << endl; + cout << "-------------" << endl; if(chunkReaders.count(chunkName) == 0) { - cout << "Chunk reader not found!!!" << endl; + cout << "Chunk reader not found!!! " << chunkName << endl; + // for(int i = 0; i < 4; i++) + // cout << 0+chunkType[i] << ' '; + // cout << endl; + reader->skipBytes(chunkSize + 4); if(islower(chunkType[0])) { @@ -150,15 +156,6 @@ namespace TehImage // cout << "Assigning " << imageDataSize << " bytes for image" << endl; pixels = std::make_unique<Pixel[]>(width * height); - -/* - Scanline<RGBPixel<uint8_t>>* lines = new Scanline<RGBPixel<uint8_t>> [height]; - for(int i = 0; i < height; i++) - { - lines[i].pixels = new RGBPixel<uint8_t>[width]; - } - imageData = (uint8_t*)lines; -*/ } DEFINE_CHUNK_READER(iCCP) @@ -172,7 +169,7 @@ namespace TehImage c = reader->readByte(); chunkSize--; } - cout << profileName << endl; + // cout << profileName << endl; uint8_t compresssionMethod = reader->readByte(); chunkSize--; cout << 0+compresssionMethod << endl; @@ -187,7 +184,7 @@ namespace TehImage chunkSize--; if(CM != 8) cout << "Invalid CM: " << 0+CM << endl; - cout << 0+CM << ", " << 0+CINFO << ", " << (check?"Valid":"Failed checksum") << ", " << (FDICT?"Dict is present":"No dict present") << ", " << 0+FLEVEL << endl; + // cout << 0+CM << ", " << 0+CINFO << ", " << (check?"Valid":"Failed checksum") << ", " << (FDICT?"Dict is present":"No dict present") << ", " << 0+FLEVEL << endl; char compressedData[chunkSize - 4]; reader->readBytes(compressedData, chunkSize - 4); @@ -215,21 +212,21 @@ namespace TehImage reader->readBytes(endian, 4); for(int i = 0; i < 2; i++) { - cout << endian[i]; + // cout << endian[i]; } for(int i = 2; i < 4; i++) { - cout << " " << 0+endian[i]; + // cout << " " << 0+endian[i]; } - cout << endl; + // cout << endl; char rest[chunkSize - 4]; reader->readBytes(rest, chunkSize - 4); - cout << std::hex; + // cout << std::hex; for(int i = 0; i < chunkSize - 4; i++) { - cout << 0+rest[i] << " "; + // cout << 0+rest[i] << " "; } - cout << std::dec << endl; + // cout << std::dec << endl; } DEFINE_CHUNK_READER(iDOT) @@ -299,6 +296,7 @@ namespace TehImage if(CM != 8) cout << "Invalid CM: " << 0+CM << endl; cout << 0+CM << ", " << 0+CINFO << ", " << (check?"Valid":"Failed checksum") << ", " << (FDICT?"Dict is present":"No dict present") << ", " << 0+FLEVEL << endl; + // cout << 0 + CMF << " " << 0 + FLG << endl; idatData = (uint8_t*)malloc(0); } @@ -453,25 +451,66 @@ namespace TehImage writer->writeData(width); writer->writeData(height); - writer->writeData(bpp); + writer->writeData<uint8_t>(8); // bpp writer->writeData<uint8_t>(ColorTypes::TRUECOLOR | ColorTypes::ALPHA); writer->writeData<uint8_t>(0); // Compression method writer->writeData<uint8_t>(0); // Filter method writer->writeData<uint8_t>(0); // Interlace method uint32_t CRC = calculateCRC((uint8_t*)writer->buffer, writer->pos); - // cout << CRC << endl; writer->writeData(CRC); } DEFINE_CHUNK_WRITER(IDAT) { - uint32_t chunkSize = 0; + unsigned long imageDataSize = height * (width * 4 + 1); + uint8_t* pngImageData = new uint8_t[imageDataSize]; + + for(int y = 0; y < height; y++) + { + pngImageData[y*(width*4 + 1)] = 0; + for(int x = 0; x < width; x++) + { + pngImageData[y*(width*4 + 1) + 1 + x*4 + 0] = (*this)[x, y].r; + pngImageData[y*(width*4 + 1) + 1 + x*4 + 1] = (*this)[x, y].g; + pngImageData[y*(width*4 + 1) + 1 + x*4 + 2] = (*this)[x, y].b; + pngImageData[y*(width*4 + 1) + 1 + x*4 + 3] = (*this)[x, y].a; + } + } + + ZLib encoder; + uint8_t compressed[WRITER_BUFFER_SIZE]; + + size_t encodedSize = encoder.encodeData(pngImageData, imageDataSize, compressed, WRITER_BUFFER_SIZE); + + // uint8_t *test = new uint8_t[imageDataSize]; + // ZLib decoder; + // size_t decodeSize = decoder.decodeData(compressed, encodedSize, test, imageDataSize); + // if(decodeSize != imageDataSize) + // cout << "Wrong size" << endl; + // if(memcmp(pngImageData, test, imageDataSize) != 0) + // cout << "Wrong data" << endl; + + // encoder.decodeData(compressed, encodedSize, pngImageData, imageDataSize); + + uint32_t chunkSize = encodedSize + 2; + + delete[] pngImageData; writer->writeData(chunkSize); writer->flushBuffer(); char header[] = "IDAT"; writer->writeBytes(header, 4); + + writer->writeByte(120); + writer->writeByte(1); + + writer->writeBytes((char*)compressed, encodedSize); + + // writer->zeroBytes(4); + + uint32_t CRC = calculateCRC((uint8_t*)writer->buffer, writer->pos); + writer->writeData(CRC); } DEFINE_CHUNK_WRITER(IEND) @@ -484,7 +523,6 @@ namespace TehImage writer->writeBytes(header, 4); uint32_t CRC = calculateCRC((uint8_t*)writer->buffer, writer->pos); - // cout << CRC << endl; writer->writeData(CRC); } } diff --git a/src/debug.h b/src/debug.h index 907498b..75726a0 100644 --- a/src/debug.h +++ b/src/debug.h @@ -1,7 +1,7 @@ #pragma once // Toggles global debug -// #define ENABLE_DEBUG +/* #define ENABLE_DEBUG */ #ifdef ENABLE_DEBUG #define debug(x) (x) diff --git a/src/zlib.cpp b/src/zlib.cpp index 022b2fc..221137c 100644 --- a/src/zlib.cpp +++ b/src/zlib.cpp @@ -5,6 +5,7 @@ #include <bitset> #include <cstdint> #include <cstring> +#include <exception> #include <iomanip> #include <iostream> #include <stdexcept> @@ -274,7 +275,6 @@ namespace TehImage long byte = stream->pos / 8; if(byte >= stream->length) { - cout << byte << " " << stream->length << endl; throw std::out_of_range("Ran out of compressed data"); } stream->pos++; @@ -334,7 +334,6 @@ namespace TehImage bool final; do { - final = nextBit(&stream); CompressionType method = (CompressionType)nextBits(&stream, 2); @@ -368,6 +367,8 @@ namespace TehImage do { code = getNextCode(&stream); + + // cout << 'a' << endl; if(outPos > outLength && code != 256) { throw std::out_of_range("No more space left in image (normal)"); @@ -376,10 +377,14 @@ namespace TehImage out[outPos++] = (uint8_t)code; else if(code > 256) { + // cout << 'b' << endl; unsigned int len = lenStart[code-257] + (int)nextBits(&stream, lenExtra[code-257]); + // cout << 'c' << endl; unsigned int distCode = getNextCode(&stream, &distTree); + // cout << 'd' << endl; unsigned int dist = distStart[distCode] + (int)nextBits(&stream, distExtra[distCode]); + // cout << 'e' << endl; if(outPos + len > outLength) { throw std::out_of_range("No more space left in image (RLE error)"); @@ -389,7 +394,9 @@ namespace TehImage out[outPos] = out[outPos - dist]; outPos++; } + // cout << 'f' << endl; } + // cout << 'z' << endl; } while(code != 256); } @@ -440,7 +447,7 @@ namespace TehImage getStaticHuffmanCodes(codes, codeLens, distCodes, distCodeLens); // cout << inPos << " " << length << endl; - HashTable hashTable(255); + HashTable hashTable(256); while(inPos < length) { if(inPos + 2 >= length) @@ -451,22 +458,26 @@ namespace TehImage } char curr[3]; - memcpy(curr, &data[inPos], 3); - if(hashTable.contains(curr)) + memcpy(curr, &(data[inPos]), 3); + if(hashTable.contains(curr) && inPos - hashTable.get(curr) < 32768) { unsigned long pos = hashTable.get(curr); int length = 3; - while(data[pos + length] == data[inPos + length]) + while(data[pos + length] == data[inPos + length] + && pos + length < inPos && length < 258) length++; + // length--; - + bool lFound = false, dFound = false; uint16_t lenCode, lenExtraBits; - for(uint16_t i = 0; i < 30; i++) + for(uint16_t i = 0; i < 29; i++) { if(lenStart[i] <= length && lenStart[i] + (0b1 << lenExtra[i]) - 1 >= length) { lenCode = i; lenExtraBits = length - lenStart[i]; + lFound = true; + break; } } unsigned long dist = inPos - pos; @@ -476,10 +487,19 @@ namespace TehImage if(distStart[i] <= dist && distStart[i] + (0b1 << distExtra[i]) - 1 >= dist) { distCode = i; - distExtraBits = dist - distCodes[i]; + distExtraBits = dist - distStart[i]; + dFound = true; + break; } } + if(!(lFound && dFound)) + { + cout << ((lFound)?'y':'n') << " " << ((dFound)?'y':'n') << endl; + cout << length << " " << dist << endl; + throw std::runtime_error("UH OH"); + } + writeCode(&outStream, codes[lenCode + 257], codeLens[lenCode + 257]); writeBits(&outStream, lenExtra[lenCode], lenExtraBits); writeCode(&outStream, distCodes[distCode], distCodeLens[distCode]); @@ -494,6 +514,8 @@ namespace TehImage inPos++; } } + + writeCode(&outStream, codes[256], codeLens[256]); return (outStream.pos / 8) + ((outStream.pos % 8 == 0)?0:1); } diff --git a/test/main.cpp b/test/main.cpp index 5a2525b..b7ae2ea 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -42,9 +42,9 @@ int main(int argc, char* argv[]) // return 0; - if(argc < 3) + if(argc < 4) { - cout << "usage: " << argv[0] << " <in file> <out file>" << endl; + cout << "usage: " << argv[0] << " <in file> <tmpfile> <outfile>" << endl; return 1; } @@ -83,18 +83,19 @@ int main(int argc, char* argv[]) // return 0; std::string infile = argv[1]; - std::string outfile = argv[2]; + std::string tmpfile = argv[2]; + std::string outfile = argv[3]; TehImage::BMPImage bmp; bmp.readFromFile(infile); TehImage::PNGImage png(bmp); - png.writeToFile(outfile); + png.writeToFile(tmpfile); - // TehImage::PNGImage png; - // png.readFromFile(infile); + TehImage::PNGImage png2; + png2.readFromFile(tmpfile); - // TehImage::BMPImage bmp(png); - // bmp.writeToFile(outfile); + TehImage::BMPImage bmp2(png2); + bmp.writeToFile(outfile); } |
