consolidate all repos to one for archive

This commit is contained in:
2025-01-28 13:46:42 +01:00
commit a6610fbc7a
5350 changed files with 2705721 additions and 0 deletions

View File

@@ -0,0 +1,44 @@
#pragma once
#include "Buffer.h"
class BitReader
{
public:
int k = 8;
Buffer buffer;
char x = 0;
size_t pos = 0;
int readInt()
{
int ret = *(int *)&buffer.buffer[pos];
pos += 4;
return ret;
}
unsigned short int readShort()
{
short ret = *(unsigned short int *)&buffer.buffer[pos];
pos += 2;
return ret;
}
char readByte()
{
x = buffer.buffer[pos];
pos++;
return x;
}
bool readBit()
{
if (k == 8)
{
readByte();
k = 0;
}
bool b = (x >> k) & 1;
k++;
return b;
}
};

View File

@@ -0,0 +1,43 @@
#pragma once
#include "Buffer.h"
class BitWriter
{
public:
int k = 0;
Buffer buffer;
char x = 0;
void writeByte(uint8_t v)
{
buffer.add_end(&v, sizeof(v));
}
void writeInt(int v)
{
buffer.add_end((uint8_t *)&v, sizeof(v));
}
void write16(unsigned short int v)
{
buffer.add_end((uint8_t *)&v, sizeof(v));
}
void writeBit(bool b)
{
if (k == 8)
{
writeByte(x);
k = 0;
x = 0;
}
x ^= (-b ^ x) & (1 << k);
k++;
}
void finish()
{
if (k > 0)
writeByte(x);
}
};

View File

@@ -0,0 +1,37 @@
#pragma once
#include <cstdint>
#include <string>
class Buffer
{
public:
uint8_t *buffer = nullptr;
size_t taken = 0;
size_t size = 0;
std::string file_path;
Buffer(size_t size);
Buffer();
~Buffer();
bool resize(size_t new_size);
int add_end(uint8_t *data, size_t data_size);
int add_middle(uint8_t *data, size_t data_size, size_t index);
void copy(Buffer &other);
// Removes data from buffer without checking if it's in the buffer
void remove_fast(uint8_t *data, size_t data_size);
void remove(size_t index, size_t data_size);
int find(uint8_t *data, size_t data_size);
void remove(uint8_t *data, size_t data_size);
void clear() { taken = 0; }
bool save_to_file();
bool save_to_file(std::string file_path);
bool load_from_file();
bool load_from_file(std::string file_path);
};

View File

@@ -0,0 +1,15 @@
#include <vector>
#include <cstdint>
#include "BitWriter.h"
class Compressor
{
public:
BitWriter writer;
void compress(std::vector<std::vector<uint8_t>> &matrix);
private:
void IC(std::vector<int> &C, int L, int H);
std::vector<int> predict(std::vector<std::vector<uint8_t>> &P);
void encode(int v, int g);
};

View File

@@ -0,0 +1,14 @@
#pragma once
#include "BitReader.h"
#include <vector>
class Decompressor
{
public:
std::vector<unsigned char> decompress();
BitReader reader;
int decode(int g);
void DEIC(std::vector<int> &C, int L, int H);
std::vector<unsigned char> predictInvers(std::vector<int> &E, int width, int hight);
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,325 @@
#pragma once
/*
#define VECTOR_UTILS
#define BUFFER
*/
#include <vector>
#include <cstdint>
#include <string>
#include <iostream>
#include <fstream>
#include <cstring>
#ifdef BUFFER
class Buffer
{
public:
uint8_t *buffer = nullptr;
size_t taken = 0;
size_t size = 0;
std::string file_path;
Buffer(size_t size);
Buffer();
~Buffer();
bool resize(size_t new_size);
int add_end(uint8_t *data, size_t data_size);
int add_middle(uint8_t *data, size_t data_size, size_t index);
void copy(Buffer &other);
// Removes data from buffer without checking if it's in the buffer
void remove_fast(uint8_t *data, size_t data_size);
void remove(size_t index, size_t data_size);
int find(uint8_t *data, size_t data_size);
void remove(uint8_t *data, size_t data_size);
void clear() { taken = 0; }
bool save_to_file();
bool save_to_file(std::string file_path);
bool load_from_file();
bool load_from_file(std::string file_path);
};
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();
}
#endif // BUFFER
#ifdef BIT_READER
class BitReader
{
public:
int k = 8;
Buffer buffer;
char x = 0;
size_t pos = 0;
int readInt()
{
int ret = *(int *)&buffer.buffer[pos];
pos += 4;
return ret;
}
unsigned short int readShort()
{
short ret = *(unsigned short int *)&buffer.buffer[pos];
pos += 2;
return ret;
}
char readByte()
{
x = buffer.buffer[pos];
pos++;
return x;
}
bool readBit()
{
if (k == 8)
{
readByte();
k = 0;
}
bool b = (x >> k) & 1;
k++;
return b;
}
};
#endif // BIT_READER
#ifdef BIT_WRITER
class BitWriter
{
public:
int k = 0;
Buffer buffer;
char x = 0;
void writeByte(uint8_t v)
{
buffer.add_end(&v, sizeof(v));
}
void writeInt(int v)
{
buffer.add_end((uint8_t *)&v, sizeof(v));
}
void write16(unsigned short int v)
{
buffer.add_end((uint8_t *)&v, sizeof(v));
}
void writeBit(bool b)
{
if (k == 8)
{
writeByte(x);
k = 0;
x = 0;
}
x ^= (-b ^ x) & (1 << k);
k++;
}
void finish()
{
if (k > 0)
writeByte(x);
}
};
#endif // BIT_WRITER
#ifdef VECTOR_UTILS
template <typename T>
void print_vec(std::vector<T> &vec, int wrap = 5)
{
for (size_t i = 0; i < vec.size(); i++)
{
printf("%2d ", vec[i]);
if (i % wrap == wrap - 1)
printf("\n");
}
printf("\n");
}
template <typename T>
void print_matrix(std::vector<std::vector<T>> &vec)
{
for (size_t i = 0; i < vec.size(); i++)
{
for (size_t j = 0; j < vec[i].size(); j++)
{
printf("%2d ", vec[i][j]);
}
printf("\n");
}
printf("\n");
}
#endif // VECTOR_UTILS

View File

@@ -0,0 +1,131 @@
#include <iostream>
#include <vector>
#include <cmath>
#include <chrono>
#include <ctime>
#include <optional>
#include <filesystem>
#include "compressor.h"
#include "decompressor.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
struct ResultS
{
int original;
int compressed;
int64_t compression_time;
int64_t decompression_time;
};
std::optional<ResultS> run(const char *filepath)
{
int x, y, n;
unsigned char *data = stbi_load(filepath, &x, &y, &n, 1);
if (data == NULL)
{
printf("Error loading image!\n");
return std::nullopt;
}
std::vector<std::vector<unsigned char>> matrix(x, std::vector<unsigned char>(y));
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
matrix[i][j] = data[i * y + j];
}
}
delete[] data;
Compressor com;
auto startCom = std::chrono::high_resolution_clock::now();
com.compress(matrix);
auto endCom = std::chrono::high_resolution_clock::now();
Decompressor dec;
dec.reader.buffer.copy(com.writer.buffer);
auto startDec = std::chrono::high_resolution_clock::now();
std::vector<unsigned char> ret = dec.decompress();
auto endDec = std::chrono::high_resolution_clock::now();
stbi_write_bmp("out.bmp", x, y, 1, ret.data());
auto compTime = std::chrono::duration_cast<std::chrono::milliseconds>(endCom - startCom);
auto decTime = std::chrono::duration_cast<std::chrono::milliseconds>(endDec - startDec);
ResultS res;
res.original = x * y;
res.compressed = com.writer.buffer.taken;
res.compression_time = compTime.count();
res.decompression_time = decTime.count();
return res;
}
// ... x = width, y = height
// Velikost original, Velikost stisnjena, Razmerje (orig./stisn.), Čas kompresije, Čas dekompresije,
int main(int argc, char **argv)
{
if (false)
{
std::optional<ResultS> ret = run("slike/Sunrise.bmp");
if (ret.has_value())
{
ResultS res = ret.value();
printf("%9d\t", res.original);
printf("%9d\t", res.compressed);
printf("%9f\t", (float)res.original / (float)res.compressed);
printf("%9ld\t", res.compression_time);
printf("%9ld\t", res.decompression_time);
printf("%s", "slike/Sunrise.bmp");
printf("\n");
}
return 0;
}
printf("%9s\t%9s\t%9s\t%9s\t%9s\t\n", "Original", "Comp.", "Ratio", "Comp. ms", "Dec. ms");
std::string directory_path = "slike/";
std::vector<std::string> files;
// Iterate over the files in the directory
for (const auto &entry : std::filesystem::directory_iterator(directory_path))
{
// Check if the entry is a regular file
if (std::filesystem::is_regular_file(entry.path()))
{
files.push_back(entry.path().string());
}
}
std::sort(files.begin(), files.end());
for (auto file : files)
{
// std::cout << file << std::endl;
// if (file == "slike/Sunrise.bmp") continue;
std::optional<ResultS> ret = run(file.c_str());
if (ret.has_value())
{
ResultS res = ret.value();
printf("%9d\t", res.original);
printf("%9d\t", res.compressed);
printf("%9f\t", (float)res.original / (float)res.compressed);
printf("%9ld\t", res.compression_time);
printf("%9ld\t", res.decompression_time);
printf("%s", file.c_str());
printf("\n");
}
}
return 0;
}

View File

@@ -0,0 +1,27 @@
CC=g++
CFLAGS= -std=c++23
INCLUDE_DIR= include
SRC_DIR= src
# Get all cpp files from src directory
SRCS := $(wildcard $(SRC_DIR)/*.cpp)
all: main run
main: main.cpp $(SRCS) $(INCLUDE_DIR)/*.h
$(CC) $(CFLAGS) -O3 -I $(INCLUDE_DIR) $(SRCS) main.cpp -o main
debug: main.cpp $(SRCS)
$(CC) $(CFLAGS) -I$(INCLUDE_DIR) $(SRCS) -g main.cpp -o main
run: main
./main
zip:
zip -r main.zip main.cpp $(INCLUDE_DIR) $(SRC_DIR) makefile
clean:
rm main

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

View 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();
}

View 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();
}

View 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 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);
}