consolidate all repos to one for archive
This commit is contained in:
162
projektna_naloga/compression/src/Buffer.cpp
Normal file
162
projektna_naloga/compression/src/Buffer.cpp
Normal file
@@ -0,0 +1,162 @@
|
||||
#include "Buffer.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
|
||||
Buffer::Buffer()
|
||||
{
|
||||
buffer = nullptr;
|
||||
size = 0;
|
||||
taken = 0;
|
||||
}
|
||||
|
||||
Buffer::Buffer(size_t size)
|
||||
{
|
||||
this->size = size;
|
||||
this->buffer = new uint8_t[size];
|
||||
}
|
||||
|
||||
Buffer::~Buffer()
|
||||
{
|
||||
if (buffer)
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
bool Buffer::resize(size_t new_size)
|
||||
{
|
||||
if (size >= new_size)
|
||||
return true;
|
||||
if (new_size < size * 2)
|
||||
new_size = size * 2;
|
||||
uint8_t *new_buffer = (uint8_t *)realloc(buffer, new_size);
|
||||
if (!new_buffer)
|
||||
{
|
||||
printf("Error resizing buffer\n");
|
||||
return false;
|
||||
}
|
||||
buffer = new_buffer;
|
||||
size = new_size;
|
||||
return true;
|
||||
}
|
||||
|
||||
int Buffer::add_end(uint8_t *data, size_t data_size)
|
||||
{
|
||||
if (taken + data_size > size)
|
||||
if (!resize(size + data_size))
|
||||
return -1;
|
||||
|
||||
memcpy(buffer + taken, data, data_size);
|
||||
taken += data_size;
|
||||
return taken - data_size;
|
||||
}
|
||||
|
||||
int Buffer::add_middle(uint8_t *data, size_t data_size, size_t index)
|
||||
{
|
||||
if (taken + data_size > size)
|
||||
if (!resize(size + data_size))
|
||||
return -1;
|
||||
memmove(buffer + index + data_size, buffer + index, taken - index);
|
||||
memcpy(buffer + index, data, data_size);
|
||||
taken += data_size;
|
||||
return index;
|
||||
}
|
||||
|
||||
void Buffer::copy(Buffer &other)
|
||||
{
|
||||
if (other.size > size)
|
||||
if (!resize(other.size))
|
||||
return;
|
||||
memcpy(buffer, other.buffer, other.taken);
|
||||
taken = other.taken;
|
||||
}
|
||||
|
||||
void Buffer::remove_fast(uint8_t *data, size_t data_size)
|
||||
{
|
||||
int64_t index = data - buffer;
|
||||
if (index < 0 || index > taken || index + data_size > taken)
|
||||
{
|
||||
printf("Error removing from buffer\n");
|
||||
return;
|
||||
}
|
||||
memmove(buffer + index, buffer + index + data_size, taken - index - data_size);
|
||||
taken -= data_size;
|
||||
}
|
||||
|
||||
void Buffer::remove(size_t index, size_t data_size)
|
||||
{
|
||||
if (index + data_size > taken)
|
||||
{
|
||||
printf("Error removing from buffer\n");
|
||||
return;
|
||||
}
|
||||
memmove(buffer + index, buffer + index + data_size, taken - index - data_size);
|
||||
taken -= data_size;
|
||||
}
|
||||
|
||||
int Buffer::find(uint8_t *data, size_t data_size)
|
||||
{
|
||||
for (int i = 0; i < taken; i++)
|
||||
if (memcmp(buffer + i, data, data_size) == 0)
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Buffer::remove(uint8_t *data, size_t data_size)
|
||||
{
|
||||
int index = find(data, data_size);
|
||||
if (index == -1)
|
||||
{
|
||||
printf("Error removing from buffer\n");
|
||||
return;
|
||||
}
|
||||
remove(index, data_size);
|
||||
}
|
||||
|
||||
bool Buffer::save_to_file()
|
||||
{
|
||||
std::ofstream file(this->file_path, std::ios::binary | std::ios::out);
|
||||
if (!file.is_open())
|
||||
{
|
||||
printf("Error saving file\n");
|
||||
return false;
|
||||
}
|
||||
file.write((char *)this->buffer, this->taken);
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Buffer::save_to_file(std::string file_path)
|
||||
{
|
||||
this->file_path = file_path;
|
||||
return save_to_file();
|
||||
}
|
||||
|
||||
bool Buffer::load_from_file()
|
||||
{
|
||||
std::ifstream file(this->file_path, std::ios::binary | std::ios::in);
|
||||
if (!file.is_open())
|
||||
return false;
|
||||
|
||||
file.seekg(0, std::ios::end);
|
||||
|
||||
size_t file_size = file.tellg();
|
||||
resize(file_size);
|
||||
|
||||
file.seekg(0, std::ios::beg);
|
||||
file.read((char *)buffer, size);
|
||||
|
||||
if (file)
|
||||
taken = file_size;
|
||||
else
|
||||
taken = file.gcount();
|
||||
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Buffer::load_from_file(std::string file_path)
|
||||
{
|
||||
this->file_path = file_path;
|
||||
return load_from_file();
|
||||
}
|
98
projektna_naloga/compression/src/compressor.cpp
Normal file
98
projektna_naloga/compression/src/compressor.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
#include "compressor.h"
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
std::vector<int> Compressor::predict(std::vector<std::vector<uint8_t>> &P)
|
||||
{
|
||||
int hight = P.size();
|
||||
int width = P[0].size();
|
||||
std::vector<int> E(hight * width, 0);
|
||||
|
||||
E[0] = P[0][0];
|
||||
|
||||
for (size_t i = 1; i < width; i++)
|
||||
{
|
||||
E[i] = P[0][i - 1] - P[0][i];
|
||||
}
|
||||
|
||||
for (size_t i = 1; i < hight; i++)
|
||||
{
|
||||
E[i * width] = P[i - 1][0] - P[i][0];
|
||||
}
|
||||
|
||||
for (size_t y = 1; y < hight; y++)
|
||||
{
|
||||
for (size_t x = 1; x < width; x++)
|
||||
{
|
||||
if (P[y - 1][x - 1] >= std::max(P[y][x - 1], P[y - 1][x]))
|
||||
{
|
||||
E[y * width + x] = std::min(P[y][x - 1], P[y - 1][x]) - P[y][x];
|
||||
}
|
||||
else if (P[y - 1][x - 1] <= std::min(P[y][x - 1], P[y - 1][x]))
|
||||
{
|
||||
E[y * width + x] = std::max(P[y][x - 1], P[y - 1][x]) - P[y][x];
|
||||
}
|
||||
else
|
||||
{
|
||||
E[y * width + x] = P[y][x - 1] + P[y - 1][x] - P[y - 1][x - 1] - P[y][x];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return E;
|
||||
}
|
||||
|
||||
void Compressor::encode(int v, int g)
|
||||
{
|
||||
for (int i = 0; i < g; ++i)
|
||||
{
|
||||
writer.writeBit((v >> i) & 1);
|
||||
}
|
||||
}
|
||||
|
||||
void Compressor::IC(std::vector<int> &C, int L, int H)
|
||||
{
|
||||
if (H - L <= 1)
|
||||
return;
|
||||
if (C[H] == C[L])
|
||||
return;
|
||||
|
||||
int m = (H + L) / 2;
|
||||
int g = std::ceil(std::log2(C[H] - C[L] + 1));
|
||||
|
||||
encode(C[m] - C[L], g);
|
||||
|
||||
if (L < m)
|
||||
IC(C, L, m);
|
||||
if (m < H)
|
||||
IC(C, m, H);
|
||||
}
|
||||
|
||||
void Compressor::compress(std::vector<std::vector<uint8_t>> &matrix)
|
||||
{
|
||||
std::vector<int> E = predict(matrix);
|
||||
|
||||
std::vector<int> N(E.size(), 0);
|
||||
N[0] = E[0];
|
||||
for (size_t i = 1; i < E.size(); i++)
|
||||
{
|
||||
if (E[i] >= 0)
|
||||
N[i] = 2 * E[i];
|
||||
else
|
||||
N[i] = 2 * std::abs(E[i]) - 1;
|
||||
}
|
||||
|
||||
std::vector<int> C(N.size(), 0);
|
||||
C[0] = N[0];
|
||||
for (size_t i = 1; i < C.size(); i++)
|
||||
{
|
||||
C[i] = C[i - 1] + N[i];
|
||||
}
|
||||
writer.write16(matrix.size());
|
||||
writer.writeByte(E[0]);
|
||||
writer.writeInt(C[C.size() - 1]);
|
||||
writer.writeInt(C.size());
|
||||
|
||||
IC(C, 0, C.size() - 1);
|
||||
writer.finish();
|
||||
}
|
119
projektna_naloga/compression/src/decompressor.cpp
Normal file
119
projektna_naloga/compression/src/decompressor.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
#
|
||||
#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 &width, int &hight)
|
||||
{
|
||||
|
||||
hight = reader.readShort();
|
||||
int first = reader.readByte();
|
||||
int last = reader.readInt();
|
||||
int size = reader.readInt();
|
||||
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);
|
||||
}
|
19
projektna_naloga/compression/src/stb.cpp
Normal file
19
projektna_naloga/compression/src/stb.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "stb.h"
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include "stb_image_write.h"
|
||||
|
||||
unsigned char *stb_l(char const *filename, int *x, int *y, int *comp, int req_comp)
|
||||
{
|
||||
return stbi_load(filename, x, y, comp, req_comp);
|
||||
}
|
||||
int stb_w(char const *filename, int x, int y, int comp, const void *data)
|
||||
{
|
||||
return stbi_write_bmp(filename, x, y, comp, data);
|
||||
}
|
||||
unsigned char *stb_lfm(unsigned char const *buffer, int len, int *x, int *y, int *comp, int req_comp)
|
||||
{
|
||||
return stbi_load_from_memory(buffer, len, x, y, comp, req_comp);
|
||||
};
|
Reference in New Issue
Block a user