120 lines
2.4 KiB
C++
120 lines
2.4 KiB
C++
#
|
|
#include <vector>
|
|
#include <cmath>
|
|
#include <iostream>
|
|
|
|
#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<int> &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<unsigned char> Decompressor::predictInvers(std::vector<int> &E, int width, int hight)
|
|
{
|
|
std::vector<unsigned char> 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<unsigned char> Decompressor::decompress()
|
|
{
|
|
|
|
int hight = reader.readShort();
|
|
int first = reader.readByte();
|
|
int last = reader.readInt();
|
|
int size = reader.readInt();
|
|
int width = size / hight;
|
|
|
|
std::vector<int> C(size, 0);
|
|
C[0] = first;
|
|
C[size - 1] = last;
|
|
DEIC(C, 0, size - 1);
|
|
|
|
std::vector<int> N(size, 0);
|
|
N[0] = C[0];
|
|
for (size_t i = 1; i < size; i++)
|
|
{
|
|
N[i] = C[i] - C[i - 1];
|
|
}
|
|
|
|
std::vector<int> 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);
|
|
}
|