136 lines
4.2 KiB
C++
136 lines
4.2 KiB
C++
/**
|
|
* This file is part of RenderD7
|
|
* Copyright (C) 2021-2024 NPI-D7, tobid7
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <renderd7/nimg.hpp>
|
|
|
|
// Use an Npi simplifier cause I am lazy
|
|
#define reca_cc(x) reinterpret_cast<const char*>(x)
|
|
#define reca_c(x) reinterpret_cast<char*>(x)
|
|
#define pak32(q, w, e, r) \
|
|
((((q)&0xff) << 0) | (((w)&0xff) << 8) | (((e)&0xff) << 16) | \
|
|
(((r)&0xff) << 24))
|
|
|
|
// Stupid RLE Algorithm
|
|
void npi_compress(std::vector<unsigned char>& ret,
|
|
const std::vector<unsigned char>& in) {
|
|
unsigned char counter = 1;
|
|
unsigned char tmp = in[0];
|
|
for (size_t i = 1; i < in.size(); ++i) {
|
|
if (tmp == in[i]) {
|
|
counter++;
|
|
} else {
|
|
ret.push_back(counter);
|
|
ret.push_back(tmp);
|
|
counter = 1;
|
|
tmp = in[i];
|
|
}
|
|
if (counter == 255) {
|
|
ret.push_back(counter);
|
|
ret.push_back(tmp);
|
|
counter = 0;
|
|
}
|
|
}
|
|
if (counter > 0) {
|
|
ret.push_back(counter);
|
|
ret.push_back(tmp);
|
|
}
|
|
}
|
|
|
|
void npi_decompress(std::vector<unsigned char>& ret,
|
|
const std::vector<unsigned char>& in) {
|
|
// Size is sus
|
|
if ((in.size() % 2) != 0) return;
|
|
for (size_t i = 0; i < in.size(); i += 2) {
|
|
int count = in[i];
|
|
int value = in[i + 1];
|
|
for (int c = 0; c < count; c++) {
|
|
ret.push_back(value);
|
|
}
|
|
}
|
|
}
|
|
|
|
namespace RenderD7 {
|
|
nimg NIMG_Load(std::string path) {
|
|
nimg res;
|
|
std::ifstream fin(path, std::ios::in | std::ios::binary);
|
|
// Check magic
|
|
fin.read(reca_c(&res.magic), sizeof(uint32_t));
|
|
if (res.magic != NPI_NIMG_) {
|
|
std::cout << path << " is invalid!" << std::endl;
|
|
return res;
|
|
}
|
|
// Read Information
|
|
fin.read(reca_c(&res.width), sizeof(int));
|
|
fin.read(reca_c(&res.height), sizeof(int));
|
|
fin.read(reca_c(&res.format), sizeof(int));
|
|
fin.read(reca_c(&res.compression), sizeof(int));
|
|
// Read Pixeldata
|
|
if (res.compression == 1) {
|
|
std::vector<unsigned char> tb;
|
|
int pb_size = 0;
|
|
fin.read(reca_c(&pb_size), sizeof(int));
|
|
tb.resize(pb_size);
|
|
fin.read(reca_c(tb.data()), pb_size);
|
|
npi_decompress(res.pixel_buffer, tb);
|
|
} else {
|
|
int pb_size = 0;
|
|
fin.read(reca_c(&pb_size), sizeof(int));
|
|
res.pixel_buffer.resize(pb_size);
|
|
fin.read(reca_c(res.pixel_buffer.data()), pb_size);
|
|
}
|
|
|
|
// Close stream
|
|
fin.close();
|
|
// Return the loadet imaeg
|
|
return res;
|
|
}
|
|
|
|
nimg NIMG_LoadFromMem(unsigned char* buffer, size_t bf_size) { return nimg(); }
|
|
|
|
void NIMG_Save(nimg image, std::string path) {
|
|
std::ofstream fout(path);
|
|
// Write Magic
|
|
fout.write(reca_cc(&image.magic), sizeof(uint32_t));
|
|
// Write Information
|
|
fout.write(reca_cc(&image.width), sizeof(int));
|
|
fout.write(reca_cc(&image.height), sizeof(int));
|
|
fout.write(reca_cc(&image.format), sizeof(int));
|
|
fout.write(reca_cc(&image.compression), sizeof(int));
|
|
std::vector<unsigned char> test;
|
|
// Write pixels
|
|
if (image.compression == 1) {
|
|
std::vector<unsigned char> tb;
|
|
npi_compress(tb, image.pixel_buffer);
|
|
int buf_szs = tb.size();
|
|
fout.write(reca_cc(&buf_szs), sizeof(int)); // buf_size
|
|
fout.write(reca_cc(tb.data()),
|
|
tb.size()); // buffer
|
|
} else {
|
|
int buf_szs = image.pixel_buffer.size();
|
|
fout.write(reca_cc(&buf_szs), sizeof(int)); // buf_size
|
|
fout.write(reca_cc(image.pixel_buffer.data()),
|
|
image.pixel_buffer.size()); // buffer
|
|
}
|
|
|
|
// Close stream
|
|
fout.close();
|
|
}
|
|
} // namespace RenderD7
|