Bug identified, first char of new chunk not witten (see uncompress.cc:59)

This commit is contained in:
Phuntsok Drak-pa 2018-06-24 18:03:09 +02:00
parent e01334a566
commit 0523fe77f2
5 changed files with 25 additions and 45 deletions

View File

@ -48,9 +48,6 @@ vuchar pack(const vuint16 &t_input) {
vuchar pack_n(const vuint16::const_iterator t_input_begin, vuchar pack_n(const vuint16::const_iterator t_input_begin,
const vuint16::const_iterator t_input_end, vuchar &t_res, const vuint16::const_iterator t_input_end, vuchar &t_res,
int t_n) { int t_n) {
#ifdef Debug
std::printf("%d bits!\n", t_n);
#endif // Debug
if (t_n == 16) { if (t_n == 16) {
return pack_16(t_input_begin, t_input_end, t_res); return pack_16(t_input_begin, t_input_end, t_res);
} }

View File

@ -37,30 +37,18 @@ ustring read_file(const string &filename) {
return res; return res;
} }
/**
* La chaîne de caractères \p t_text est lue caractère par caractère, et est
* selon la valeur de retour de la fonction \ref dico (permettant dans le même
* temps la création du dictionnaire), on rajoute ou non un nouveau caractère
* encodé sur 12bits dans le chunk courant. Dès que le dictionnaire est plein
* (2^12 caractères), le chunk est sauvegardé et vidé, et le dictionnaire est
* réinitialisé.
*
* \param t_text Chaîne de caractères uint8_t représentant le fichier d'entrée
* \return Vecteur de chunks (vecteurs de uint16_t)
*/
vvuint16 lzw_compress(ustring &&t_text) { vvuint16 lzw_compress(ustring &&t_text) {
std::puts("Compressing..."); vvuint16 res{};
const auto DICT_MAX = static_cast<size_t>(ipow(2, 17) - 256); /* 16 bits */ const auto DICT_MAX = static_cast<size_t>(ipow(2, 14) - 256); /* 16 bits */
uint16_t w = 0xFFFF; uint16_t w = 0xFFFF;
vuint16 chunk{}; vuint16 chunk{};
vvuint16 res{};
dict_t dict{}; dict_t dict{};
for (const auto c : t_text) { for (const auto c : t_text) {
if (dict.size() >= DICT_MAX) { if (dict.size() >= DICT_MAX) {
res.push_back(std::move(chunk)); res.push_back(chunk);
chunk = vuint16{};
dict = dict_t{};
w = 0xFFFF; w = 0xFFFF;
chunk.clear();
dict.clear();
} }
if (const auto &[exists, pos] = dico(dict, w, static_cast<uint8_t>(c)); if (const auto &[exists, pos] = dico(dict, w, static_cast<uint8_t>(c));
exists) { exists) {
@ -88,7 +76,7 @@ vvuint16 lzw_compress(ustring &&t_text) {
*/ */
void compress(const std::string &t_in_file, const char *t_out_file) { void compress(const std::string &t_in_file, const char *t_out_file) {
std::ofstream out{(t_out_file != nullptr) ? t_out_file : "output.lzw", std::ofstream out{(t_out_file != nullptr) ? t_out_file : "output.lzw",
std::ios::out | std::ios::binary}; ios::out | ios::binary};
if (!out.is_open()) { if (!out.is_open()) {
std::cerr << "Error at " << __FILE__ << ":" << __LINE__ - 4 std::cerr << "Error at " << __FILE__ << ":" << __LINE__ - 4
<< ": could not open output file. Aborting...\n"; << ": could not open output file. Aborting...\n";

View File

@ -48,9 +48,6 @@ void write_file(std::ofstream &t_out, const vvuint16 &t_chunks) {
* \param t_chunk Chunk to be written to \p t_out * \param t_chunk Chunk to be written to \p t_out
*/ */
void write_chunk(std::ofstream &t_out, const vuint16 &t_chunk) { void write_chunk(std::ofstream &t_out, const vuint16 &t_chunk) {
#ifdef Debug
std::printf("Chunk!\n");
#endif
const auto output = pack(t_chunk); const auto output = pack(t_chunk);
const auto chunk_size = static_cast<uint32_t>(output.size()); const auto chunk_size = static_cast<uint32_t>(output.size());
t_out.write(reinterpret_cast<const char *>(&chunk_size), sizeof(chunk_size)); t_out.write(reinterpret_cast<const char *>(&chunk_size), sizeof(chunk_size));

View File

@ -20,16 +20,11 @@ ustring lzw_uncompress(vuint16 &&t_compressed) {
ustring ret{}; ustring ret{};
uint16_t old = 0; uint16_t old = 0;
std::map<uint16_t, ustring> dict{}; std::map<uint16_t, ustring> dict{};
// uint16_t v = t_compressed[0];
// ret.append({static_cast<unsigned char>(v)});
// old = v;
ret.append({static_cast<unsigned char>(t_compressed[0])}); ret.append({static_cast<unsigned char>(t_compressed[0])});
old = t_compressed[0]; old = t_compressed[0];
for (auto it = t_compressed.begin() + 1; it != t_compressed.end(); ++it) { for (auto it = t_compressed.begin() + 1; it != t_compressed.end(); ++it) {
// v = *it;
const auto uncompressed{dico_uncompress(dict, *it, old)}; const auto uncompressed{dico_uncompress(dict, *it, old)};
ret.insert(ret.end(), uncompressed.begin(), uncompressed.end()); ret.insert(ret.end(), uncompressed.begin(), uncompressed.end());
// old = v;
old = *it; old = *it;
} }
@ -39,28 +34,30 @@ ustring lzw_uncompress(vuint16 &&t_compressed) {
void uncompress(const string &t_input_name, const char *t_output_name) { void uncompress(const string &t_input_name, const char *t_output_name) {
FILE *const input = std::fopen(t_input_name.c_str(), "rb"); FILE *const input = std::fopen(t_input_name.c_str(), "rb");
assert(input); assert(input);
FILE *const output = std::ofstream output{(t_output_name != nullptr)
(t_output_name != nullptr) ? t_output_name
? std::fopen(t_output_name, "wb") : t_input_name + "_uncompressed",
: std::fopen((t_input_name + "_uncompressed").c_str(), "wb"); std::ios::out | std::ios::binary | std::ios::app};
assert(output); assert(output.is_open());
uint16_t nb_chunks = 0; uint16_t nb_chunks = 0;
std::fread(&nb_chunks, sizeof(nb_chunks), 1, input); std::fread(&nb_chunks, sizeof(nb_chunks), 1, input);
for (uint16_t i = 0; i < nb_chunks; ++i) { for (uint16_t i = 0; i < nb_chunks; ++i) {
uncompress_chunk(input, output); uncompress_chunk(input, output);
} }
std::fclose(output); output.close();
std::fclose(input); std::fclose(input);
} }
void uncompress_chunk(FILE *const input, FILE *const output) { void uncompress_chunk(FILE *const t_input, std::ofstream &t_output) {
uint32_t size_chunk = 0; uint32_t size_chunk = 0;
fread(&size_chunk, sizeof(size_chunk), 1, input); fread(&size_chunk, sizeof(size_chunk), 1, t_input);
auto chunk = new unsigned char[size_chunk]; auto chunk = std::make_unique<unsigned char[]>(size_chunk);
fread(chunk, sizeof(unsigned char), size_chunk, input); fread(chunk.get(), sizeof(unsigned char), size_chunk, t_input);
auto unpacked = unpack(ustring{chunk, chunk + size_chunk}); auto unpacked = unpack(ustring{chunk.get(), chunk.get() + size_chunk});
delete[] chunk; auto uncompressed_chunk = lzw_uncompress(std::move(unpacked));
const auto uncompressed_chunk = lzw_uncompress(std::move(unpacked));
std::fwrite(uncompressed_chunk.data(), sizeof(uncompressed_chunk[0]), // attention here for bug ///////////////////////////////////////////////////
uncompressed_chunk.size(), output); uncompressed_chunk.push_back(0xFF);
t_output.write(reinterpret_cast<const char *>(uncompressed_chunk.data()),
sizeof(uncompressed_chunk[0]) * uncompressed_chunk.size());
} }

View File

@ -1,6 +1,7 @@
#ifndef LZW_SRC_UNCOMPRESS_H_ #ifndef LZW_SRC_UNCOMPRESS_H_
#define LZW_SRC_UNCOMPRESS_H_ #define LZW_SRC_UNCOMPRESS_H_
#include <fstream>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
@ -9,6 +10,6 @@ std::basic_string<unsigned char> lzw_uncompress(std::vector<std::uint16_t> &&);
void uncompress(const std::string &, const char *); void uncompress(const std::string &, const char *);
void uncompress_chunk(FILE *, FILE *); void uncompress_chunk(FILE *, std::ofstream&);
#endif /* LZW_SRC_UNCOMPRESS_H_ */ #endif /* LZW_SRC_UNCOMPRESS_H_ */