|
| 1 | +// |
| 2 | +// Created by Ole on 10.09.2017. |
| 3 | +// |
| 4 | + |
| 5 | +#include "image.h" |
| 6 | + |
| 7 | +unsigned char reversed(unsigned char value) { |
| 8 | + unsigned char t = value; |
| 9 | + for (int i = sizeof(value) * 8-1; i; i--) |
| 10 | + { |
| 11 | + value >>= 1; |
| 12 | + t <<= 1; |
| 13 | + t |= value & 1; |
| 14 | + } |
| 15 | + return t; |
| 16 | +} |
| 17 | + |
| 18 | +Image::Image(const std::string& path) { |
| 19 | + init(path); |
| 20 | +} |
| 21 | + |
| 22 | +void Image::init(const std::string& path) { |
| 23 | + std::ifstream stream(path, std::ifstream::in | std::ifstream::ate | std::ifstream::binary); |
| 24 | + auto size = (unsigned int) stream.tellg(); |
| 25 | + if (!stream.good()) { |
| 26 | + LOG("FAILED TO OPEN FILE: " << path); |
| 27 | + size = 0; |
| 28 | + } |
| 29 | + stream.seekg(0, std::ifstream::beg); |
| 30 | + |
| 31 | + unsigned char data[size]; |
| 32 | + |
| 33 | + unsigned int position = 0; |
| 34 | + char in; |
| 35 | + while (stream.get(in)) |
| 36 | + data[position++] = (unsigned char) in; |
| 37 | + |
| 38 | + loadChunks(data, size); |
| 39 | + formatIHDR(); |
| 40 | + |
| 41 | + stream.close(); |
| 42 | +} |
| 43 | + |
| 44 | +void Image::formatIHDR() { |
| 45 | + auto& data = chunks[0]->data; |
| 46 | + |
| 47 | + format.width = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | (data[3]); |
| 48 | + format.height = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | (data[7]); |
| 49 | + format.bitDepth = data[8]; |
| 50 | + format.colorType = data[9]; |
| 51 | + format.compressionMethod = data[10]; |
| 52 | + format.filterMethod = data[11]; |
| 53 | + format.interlaceMethod = data[12]; |
| 54 | +} |
| 55 | + |
| 56 | +std::vector<unsigned char> Image::extractCompressedPixelData(const Chunk& chunk) { |
| 57 | + std::vector<unsigned char> compressedData; |
| 58 | + compressedData.reserve(chunk.length); |
| 59 | + for(int i = 0; i < chunk.length; i++) { |
| 60 | + compressedData.push_back(chunk.data[i]); |
| 61 | + } |
| 62 | + return compressedData; |
| 63 | +} |
| 64 | + |
| 65 | +void Image::loadChunks(const unsigned char* data, unsigned int size) { |
| 66 | + unsigned int offset = 8; |
| 67 | + while(offset < size) { |
| 68 | + chunks.push_back(loadChunk(data, offset)); |
| 69 | + } |
| 70 | +} |
| 71 | + |
| 72 | +Chunk* Image::loadChunk(const unsigned char* data, unsigned int& offset) { |
| 73 | + unsigned int chunkLength = (data[offset + 0] << 24) | (data[offset + 1] << 16) | (data[offset + 2] << 8) | (data[offset + 3]); |
| 74 | + offset += 4; |
| 75 | + |
| 76 | + char s[5]; |
| 77 | + s[0] = data[offset + 0]; |
| 78 | + s[1] = data[offset + 1]; |
| 79 | + s[2] = data[offset + 2]; |
| 80 | + s[3] = data[offset + 3]; |
| 81 | + s[4] = 0; |
| 82 | + std::string chunkType(s); |
| 83 | + offset += 4; |
| 84 | + |
| 85 | + std::vector<unsigned char> chunkData; |
| 86 | + chunkData.reserve(chunkLength); |
| 87 | + |
| 88 | + for (int p = 0; p < chunkLength; p++) { |
| 89 | + chunkData.push_back(data[offset + p]); |
| 90 | + } |
| 91 | + offset += chunkLength; |
| 92 | + |
| 93 | + unsigned int chunkCRC = (data[offset + 0] << 24) | (data[offset + 1] << 16) | (data[offset + 2] << 8) | (data[offset + 3]); |
| 94 | + offset += 4; |
| 95 | + |
| 96 | + return new Chunk(chunkLength, chunkType, chunkData, chunkCRC); |
| 97 | +} |
0 commit comments