# #include #include #include #include "decompressor.h" #include "BitReader.h" int Decompressor::decode(int g) { int v = 0; for (int i = 0; i < g; i++) { bool bit = reader.readBit(); v |= bit << i; } return v; } void Decompressor::DEIC(std::vector &C, int L, int H) { if (H - L <= 1) return; if (C[L] == C[H]) { for (size_t i = L + 1; i < H; i++) { C[i] = C[L]; } } else { int M = (L + H) / 2; int G = std::ceil(std::log2(C[H] - C[L] + 1)); C[M] = C[L] + decode(G); if (L < M) DEIC(C, L, M); if (M < H) DEIC(C, M, H); } } std::vector Decompressor::predictInvers(std::vector &E, int width, int hight) { std::vector matrix1(width * hight, 0); matrix1[0] = E[0]; for (size_t i = 1; i < width; i++) { matrix1[i] = matrix1[i - 1] - E[i]; } for (size_t i = 1; i < hight; i++) { matrix1[i * width] = matrix1[(i - 1) * width] - E[i * width]; } for (size_t i = 1; i < hight; i++) { for (size_t j = 1; j < width; j++) { if (matrix1[(i - 1) * width + j - 1] >= std::max(matrix1[i * width + j - 1], matrix1[(i - 1) * width + j])) { matrix1[i * width + j] = std::min(matrix1[i * width + j - 1], matrix1[(i - 1) * width + j]) - E[i * width + j]; } else if (matrix1[(i - 1) * width + j - 1] <= std::min(matrix1[i * width + j - 1], matrix1[(i - 1) * width + j])) { matrix1[i * width + j] = std::max(matrix1[i * width + j - 1], matrix1[(i - 1) * width + j]) - E[i * width + j]; } else { matrix1[i * width + j] = matrix1[i * width + j - 1] + matrix1[(i - 1) * width + j] - matrix1[(i - 1) * width + j - 1] - E[i * width + j]; } } } return matrix1; } std::vector Decompressor::decompress() { int hight = reader.readShort(); int first = reader.readByte(); int last = reader.readInt(); int size = reader.readInt(); int width = size / hight; std::vector C(size, 0); C[0] = first; C[size - 1] = last; DEIC(C, 0, size - 1); std::vector N(size, 0); N[0] = C[0]; for (size_t i = 1; i < size; i++) { N[i] = C[i] - C[i - 1]; } std::vector E(size, 0); E[0] = N[0]; for (size_t i = 1; i < size; i++) { if (N[i] % 2 == 0) { E[i] = N[i] / 2; } else { E[i] = -((N[i] + 1) / 2); } } return predictInvers(E, width, hight); }