From 1e9e5fc8575a97977cdd596d016888f2ae3a88ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=B1=D0=B1=D0=B0=D1=81=20=D0=93=D1=83=D1=81=D0=B5?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2?= Date: Tue, 27 Nov 2018 00:54:48 +0600 Subject: [PATCH] =?UTF-8?q?=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=20=D1=80?= =?UTF-8?q?=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D0=BD=D0=B3,?= =?UTF-8?q?=20=D0=BD=D0=B0=D0=BF=D0=B8=D1=81=D0=B0=D0=BB=20=D0=BA=D0=BE?= =?UTF-8?q?=D0=BC=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=80=D0=B8=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AppIcon.rc | 1 - .../HuffmanCoding.pro | 24 + .../choose.cpp | 58 ++ .../choose.h | 12 +- .../choose.ui | 50 ++ .../decoding.cpp | 57 ++ .../decoding.h | 43 ++ .../decoding.ui | 62 +++ .../encoding.cpp | 57 ++ .../encoding.h | 43 ++ .../encoding.ui | 62 +++ .../guiutils.cpp | 12 + .../guiutils.h | 7 + .../huffman.cpp | 512 ++++++++++++++++++ .../huffman.h | 92 ++++ .../main.cpp | 17 + HuffmanCoding.pro | 29 - HuffmanCoding.pro.user | 365 ------------- README | 1 - Res.qrc | 5 - appIcon.ico | Bin 370070 -> 0 bytes choose.cpp | 47 -- choose.ui | 56 -- decoding.cpp | 283 ---------- decoding.h | 93 ---- decoding.ui | 81 --- encoding.cpp | 419 -------------- encoding.h | 120 ---- encoding.ui | 81 --- icon.png | Bin 31370 -> 0 bytes license.txt | 18 - main.cpp | 18 - 32 files changed, 1103 insertions(+), 1622 deletions(-) delete mode 100644 AppIcon.rc create mode 100644 Huffman-algorithm-implementation-in-Qt/HuffmanCoding.pro create mode 100644 Huffman-algorithm-implementation-in-Qt/choose.cpp rename choose.h => Huffman-algorithm-implementation-in-Qt/choose.h (51%) create mode 100644 Huffman-algorithm-implementation-in-Qt/choose.ui create mode 100644 Huffman-algorithm-implementation-in-Qt/decoding.cpp create mode 100644 Huffman-algorithm-implementation-in-Qt/decoding.h create mode 100644 Huffman-algorithm-implementation-in-Qt/decoding.ui create mode 100644 Huffman-algorithm-implementation-in-Qt/encoding.cpp create mode 100644 Huffman-algorithm-implementation-in-Qt/encoding.h create mode 100644 Huffman-algorithm-implementation-in-Qt/encoding.ui create mode 100644 Huffman-algorithm-implementation-in-Qt/guiutils.cpp create mode 100644 Huffman-algorithm-implementation-in-Qt/guiutils.h create mode 100644 Huffman-algorithm-implementation-in-Qt/huffman.cpp create mode 100644 Huffman-algorithm-implementation-in-Qt/huffman.h create mode 100644 Huffman-algorithm-implementation-in-Qt/main.cpp delete mode 100644 HuffmanCoding.pro delete mode 100644 HuffmanCoding.pro.user delete mode 100644 README delete mode 100644 Res.qrc delete mode 100644 appIcon.ico delete mode 100644 choose.cpp delete mode 100644 choose.ui delete mode 100644 decoding.cpp delete mode 100644 decoding.h delete mode 100644 decoding.ui delete mode 100644 encoding.cpp delete mode 100644 encoding.h delete mode 100644 encoding.ui delete mode 100644 icon.png delete mode 100644 license.txt delete mode 100644 main.cpp diff --git a/AppIcon.rc b/AppIcon.rc deleted file mode 100644 index bf46194..0000000 --- a/AppIcon.rc +++ /dev/null @@ -1 +0,0 @@ -IDI_ICON1 ICON DISCARDABLE "appIcon.ico" \ No newline at end of file diff --git a/Huffman-algorithm-implementation-in-Qt/HuffmanCoding.pro b/Huffman-algorithm-implementation-in-Qt/HuffmanCoding.pro new file mode 100644 index 0000000..5283fad --- /dev/null +++ b/Huffman-algorithm-implementation-in-Qt/HuffmanCoding.pro @@ -0,0 +1,24 @@ +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = HuffmanCoding +TEMPLATE = app + + +SOURCES += main.cpp\ + choose.cpp \ + encoding.cpp \ + decoding.cpp \ + huffman.cpp \ + guiutils.cpp + +HEADERS += choose.h \ + encoding.h \ + decoding.h \ + huffman.h \ + guiutils.h + +FORMS += choose.ui \ + encoding.ui \ + decoding.ui diff --git a/Huffman-algorithm-implementation-in-Qt/choose.cpp b/Huffman-algorithm-implementation-in-Qt/choose.cpp new file mode 100644 index 0000000..b2723d2 --- /dev/null +++ b/Huffman-algorithm-implementation-in-Qt/choose.cpp @@ -0,0 +1,58 @@ +#include "choose.h" +#include "ui_choose.h" +#include "encoding.h" +#include "decoding.h" + +// Конструктор: +Choose::Choose(QWidget *parent) : + QDialog(parent), + ui(new Ui::Choose) +{ + ui->setupUi(this); + + // Связать клик на кнопку "Сжать данные" с методом showCompressDialog(): + connect(ui->compressButton, SIGNAL(clicked()), this, SLOT(showCompressDialog())); + + // Связать клик на кнопку "Восстановить данные" с методом showDecompressDialog(): + connect(ui->decompressButton, SIGNAL(clicked()), this, SLOT(showDecompressDialog())); +} + +// Деструктор: +Choose::~Choose() +{ + delete ui; +} + +// Показать диалоговое окно для сжатия данных: +void Choose::showCompressDialog() +{ + // Диалоговое окно для сжатия данных: + Encoding* en = new Encoding(this); + // Если в конструктор передавать указатель на родительский виджет, + // то диалоговое окно будет отцентрировано относительно родителя. + + // Делаем размеры диалогового окна не изменяемыми: + en->setFixedSize(en->size()); + + en->setWindowTitle("Сжати данных по алгоритму Хаффмана"); + + // Показать диалоговое окно: + en->exec(); +} + +// Показать диалоговое окно для восстановления данных: +void Choose::showDecompressDialog() +{ + // Диалоговое окно для восстановления данных: + Decoding* de = new Decoding(this); + // Если в конструктор передавать указатель на родительский виджет, + // то диалоговое окно будет отцентрировано относительно родителя. + + // Делаем размеры диалогового окна не изменяемыми: + de->setFixedSize(de->size()); + + de->setWindowTitle("Восстановление данных сжатых по алгоритму Хаффмана"); + + // Показать диалоговое окно: + de->exec(); +} diff --git a/choose.h b/Huffman-algorithm-implementation-in-Qt/choose.h similarity index 51% rename from choose.h rename to Huffman-algorithm-implementation-in-Qt/choose.h index 38be58e..9e4760d 100644 --- a/choose.h +++ b/Huffman-algorithm-implementation-in-Qt/choose.h @@ -1,8 +1,3 @@ -/*********************************************** -Copyright (c) 2012 Piyush Kant -See the file license.txt for copying permission. -************************************************/ - #ifndef CHOOSE_H #define CHOOSE_H @@ -12,19 +7,26 @@ namespace Ui { class Choose; } +// Главное диалоговое окно приложения: class Choose : public QDialog { Q_OBJECT public: + // Конструктор: explicit Choose(QWidget *parent = 0); + + // Деструктор: ~Choose(); private: Ui::Choose *ui; private slots: + // Показать диалоговое окно для сжатия данных: void showCompressDialog(); + + // Показать диалоговое окно для восстановления данных: void showDecompressDialog(); }; diff --git a/Huffman-algorithm-implementation-in-Qt/choose.ui b/Huffman-algorithm-implementation-in-Qt/choose.ui new file mode 100644 index 0000000..48e4bb4 --- /dev/null +++ b/Huffman-algorithm-implementation-in-Qt/choose.ui @@ -0,0 +1,50 @@ + + + Choose + + + + 0 + 0 + 300 + 200 + + + + Сжатие и восстановление данных + + + + :/images/icon.png:/images/icon.png + + + + + 20 + 20 + 256 + 64 + + + + Сжать данные + + + + + + 20 + 110 + 256 + 64 + + + + Восстановить данные + + + + + + + diff --git a/Huffman-algorithm-implementation-in-Qt/decoding.cpp b/Huffman-algorithm-implementation-in-Qt/decoding.cpp new file mode 100644 index 0000000..03a3377 --- /dev/null +++ b/Huffman-algorithm-implementation-in-Qt/decoding.cpp @@ -0,0 +1,57 @@ +#include "decoding.h" +#include "ui_decoding.h" +#include "QFileDialog" +#include "guiutils.h" + +// Конструктор: +Decoding::Decoding(QWidget *parent) : + QDialog(parent), + ui(new Ui::Decoding) +{ + ui->setupUi(this); + + // Связать кнопку "Обзор…" с методом browseInputFile(): + connect(ui->browseButton, SIGNAL(clicked()), this, SLOT(browseInputFile())); + + // Связать кнопку "Восстановить данные" с методом decompressFile(): + connect(ui->decodeButton, SIGNAL(clicked()), this, SLOT(decompressFile())); +} + +// Деструктор: +Decoding::~Decoding() +{ + delete ui; +} + +// Метод для выбора файла для восстановления: +void Decoding::browseInputFile() +{ + // Открыть диалоговое окно для выбора файла: + inputFileName = QFileDialog::getOpenFileName(this, + tr("Открыть файл"), + QString(), + tr("Бинарные файлы (*.bin)")); + + ui->inputFile->setText(inputFileName); +} + +// Восстановить сжатый файл: +void Decoding::decompressFile() +{ + // Если имя файла пустое: + if (inputFileName == "") + { + showDoneMessage("Пожалуйста, выберите файл.", "Восстановление данных"); + } + + // Иначе, если имя файла есть: + else + { + // Имя файла: + QByteArray byteArray = inputFileName.toUtf8(); + const char* inputFile = byteArray.constData(); + + // Сжать файл: + huffmanDecode(inputFile); + } +} diff --git a/Huffman-algorithm-implementation-in-Qt/decoding.h b/Huffman-algorithm-implementation-in-Qt/decoding.h new file mode 100644 index 0000000..0e29de0 --- /dev/null +++ b/Huffman-algorithm-implementation-in-Qt/decoding.h @@ -0,0 +1,43 @@ +#ifndef DECODING_H +#define DECODING_H + +#include +#include "huffman.h" + +namespace Ui { +class Decoding; +} + +class Decoding : public QDialog +{ + Q_OBJECT + +public: + + // Конструктор: + explicit Decoding(QWidget *parent = 0); + + // Деструктор: + ~Decoding(); + + // Получить имя входного файла: + QString getInputFileName(); + +private: + + // Пользовательский интерфейс: + Ui::Decoding *ui; + + // Имя входного файла: + QString inputFileName; + +public slots: + + // Метод для выбора файла для восстановления: + void browseInputFile(); + + // Восстановить сжатый файл: + void decompressFile(); +}; + +#endif // DECODING_H diff --git a/Huffman-algorithm-implementation-in-Qt/decoding.ui b/Huffman-algorithm-implementation-in-Qt/decoding.ui new file mode 100644 index 0000000..41a3a1e --- /dev/null +++ b/Huffman-algorithm-implementation-in-Qt/decoding.ui @@ -0,0 +1,62 @@ + + + Decoding + + + + 0 + 0 + 500 + 79 + + + + Dialog + + + + :/images/icon.png:/images/icon.png + + + + + 10 + 40 + 475 + 23 + + + + Восстановить данные + + + + + + 10 + 10 + 401 + 20 + + + + + + + + + + 420 + 10 + 64 + 23 + + + + Обзор… + + + + + + diff --git a/Huffman-algorithm-implementation-in-Qt/encoding.cpp b/Huffman-algorithm-implementation-in-Qt/encoding.cpp new file mode 100644 index 0000000..401c5dd --- /dev/null +++ b/Huffman-algorithm-implementation-in-Qt/encoding.cpp @@ -0,0 +1,57 @@ +#include "encoding.h" +#include "ui_encoding.h" +#include "QFileDialog" +#include "guiutils.h" + +// Конструктор: +Encoding::Encoding(QWidget *parent) : + QDialog(parent), + ui(new Ui::Encoding) +{ + ui->setupUi(this); + + // Связать кнопку "Обзор…" с методом browseInputFile(): + connect(ui->browseButton, SIGNAL(clicked()), this, SLOT(browseInputFile())); + + // Связать кнопку "Сжать данные" с методом compressFile(): + connect(ui->encodeButton, SIGNAL(clicked()), this, SLOT(compressFile())); +} + +// Деструктор: +Encoding::~Encoding() +{ + delete ui; +} + +// Метод для выбора файла для сжатия: +void Encoding::browseInputFile() +{ + // Открыть диалоговое окно для выбора файла: + inputFileName = QFileDialog::getOpenFileName(this, + tr("Открыть файл"), + QString(), + tr("Текстовые файлы (*.txt)")); + + ui->inputFile->setText(inputFileName); +} + +// Метод для сжатия файла: +void Encoding::compressFile() +{ + // Если имя файла пустое: + if (inputFileName == "") + { + showDoneMessage("Пожалуйста, выберите файл.", "Сжатие данных"); + } + + // Иначе, если имя файла есть: + else + { + // Имя файла: + QByteArray byteArray = inputFileName.toUtf8(); + const char* inputFile = byteArray.constData(); + + // Сжать файл: + huffmanEncode(inputFile); + } +} diff --git a/Huffman-algorithm-implementation-in-Qt/encoding.h b/Huffman-algorithm-implementation-in-Qt/encoding.h new file mode 100644 index 0000000..bc2afb1 --- /dev/null +++ b/Huffman-algorithm-implementation-in-Qt/encoding.h @@ -0,0 +1,43 @@ +#ifndef ENCODING_H +#define ENCODING_H + +#include +#include "huffman.h" + +namespace Ui { +class Encoding; +} + +class Encoding : public QDialog +{ + Q_OBJECT + +public: + + // Конструктор: + explicit Encoding(QWidget *parent = 0); + + // Деструктор: + ~Encoding(); + + // Получить имя входного файла: + QString getInputFileName(); + +private: + + // Пользовательский интерфейс: + Ui::Encoding *ui; + + // Имя входного файла: + QString inputFileName; + +public slots: + + // Метод для выбора файла для сжатия: + void browseInputFile(); + + // Метод для сжатия файла: + void compressFile(); +}; + +#endif // ENCODING_H diff --git a/Huffman-algorithm-implementation-in-Qt/encoding.ui b/Huffman-algorithm-implementation-in-Qt/encoding.ui new file mode 100644 index 0000000..c3909f6 --- /dev/null +++ b/Huffman-algorithm-implementation-in-Qt/encoding.ui @@ -0,0 +1,62 @@ + + + Encoding + + + + 0 + 0 + 500 + 79 + + + + Dialog + + + + :/images/icon.png:/images/icon.png + + + + + 10 + 40 + 475 + 23 + + + + Сжать данные + + + + + + 10 + 10 + 401 + 20 + + + + + + + + + + 420 + 10 + 64 + 23 + + + + Обзор… + + + + + + diff --git a/Huffman-algorithm-implementation-in-Qt/guiutils.cpp b/Huffman-algorithm-implementation-in-Qt/guiutils.cpp new file mode 100644 index 0000000..f4b5e71 --- /dev/null +++ b/Huffman-algorithm-implementation-in-Qt/guiutils.cpp @@ -0,0 +1,12 @@ +#include "guiutils.h" +#include "QMessageBox" + +// Показать информационное сообщение: +void showDoneMessage(const char* msg, const char* title) +{ + QMessageBox msgBox; + msgBox.setText(msg); + msgBox.setWindowTitle(title); + msgBox.setIcon(QMessageBox::Information); + msgBox.exec(); +} diff --git a/Huffman-algorithm-implementation-in-Qt/guiutils.h b/Huffman-algorithm-implementation-in-Qt/guiutils.h new file mode 100644 index 0000000..42572e5 --- /dev/null +++ b/Huffman-algorithm-implementation-in-Qt/guiutils.h @@ -0,0 +1,7 @@ +#ifndef GUIUTILS_H +#define GUIUTILS_H + +// Показать информационное сообщение: +void showDoneMessage(const char* msg, const char* title); + +#endif // GUIUTILS_H diff --git a/Huffman-algorithm-implementation-in-Qt/huffman.cpp b/Huffman-algorithm-implementation-in-Qt/huffman.cpp new file mode 100644 index 0000000..9a0b1a6 --- /dev/null +++ b/Huffman-algorithm-implementation-in-Qt/huffman.cpp @@ -0,0 +1,512 @@ +#include "huffman.h" +#include "QProgressDialog" +#include "guiutils.h" + +// Посчитать частотность всех символов и сохранить в списке: +void calcCharFreq(FILE* src, unsigned int* freqList) +{ + int c; // символ. + + // Считываем очередной символ из файла: + while((c = fgetc(src)) != EOF) + { + freqList[c]++; + } + + // Перемещаемся в начало файла: + rewind(src); +} + +// Построить список узлов Хаффмана (частотности сортируются по возрастанию): +void buildNodeList(HuffNode** nodeList, unsigned int* freqList) +{ + unsigned int i; + HuffNode* newNode; + + for (i = 0; i < CHARS_LIMIT; i++) + { + // Если частотность символа больше 0, + // т.е. символ встречался во входном файле: + if (freqList[i] > 0) + { + // Создание нового узла дерева Хаффмана: + newNode = (HuffNode *)calloc(1, sizeof(HuffNode)); + newNode->charCode = i; + newNode->freq = freqList[i]; + newNode->next = NULL; + newNode->left = NULL; + newNode->right = NULL; + newNode->leaf = true; + + // Добавление нового узла в дерево Хаффмана: + addToNodeList(nodeList, newNode); + } + } +} + +// Построить список узлов из раскодированных частотностей: +void buildNodeList(HuffNode** nodeList, HuffFreq* hFreq, unsigned int numOfFreq) +{ + unsigned int i; + HuffNode* newNode; + + for (i = 0; i < numOfFreq; i++) + { + newNode = (HuffNode *)malloc(sizeof(HuffNode)); + newNode->charCode = hFreq[i].charCode; + newNode->freq = hFreq[i].freq; + newNode->next = 0; + newNode->left = 0; + newNode->right = 0; + newNode->leaf = true; + + addToNodeList(nodeList, newNode); + } +} + + +// Добавить новый узел в список узлов Хаффмана (по возрастающему порядку): +void addToNodeList(HuffNode** nodeList, HuffNode* newNode) +{ + HuffNode* prevNode = NULL; // предыдущий узел. + HuffNode* currNode = *nodeList; // текущий узел. + + while(currNode != NULL && currNode->freq < newNode->freq) + { + prevNode = currNode; + currNode = prevNode->next; + } + + newNode->next = currNode; + + if(prevNode == NULL) + { + *nodeList = newNode; + } + else + { + prevNode->next = newNode; + } +} + +// Построить дерево Хаффмана из списка узлов Хаффмана: +void buildHuffTree(HuffNode** nodeList) +{ + HuffNode* leftNode, *rightNode; + HuffNode* newNode; + + while ((*nodeList)->next) + { + leftNode = *nodeList; + *nodeList = leftNode->next; + + rightNode = *nodeList; + *nodeList = rightNode->next; + + newNode = (HuffNode *)calloc(1, sizeof(HuffNode)); + newNode->charCode = 0; + newNode->freq = leftNode->freq + rightNode->freq; + newNode->next = NULL; + newNode->left = leftNode; + newNode->right = rightNode; + newNode->leaf = false; + + addToNodeList(nodeList, newNode); + } +} + +// Построить таблицу перекодировки Хаффмана: +bool buildHuffCode(HuffNode* treeRoot, HuffCode* hCode, unsigned char goalChar) +{ + if (treeRoot->charCode == goalChar && treeRoot->leaf) + { + return true; + } + + if (treeRoot->left) + { + hCode->code[hCode->length] = '0'; + hCode->length++; + + if (hCode->length == MAX_CODE_SIZE) + { + printf("Code size exceeds limit!"); + return false; + } + + if (buildHuffCode(treeRoot->left, hCode, goalChar)) + { + hCode->code[hCode->length] = 0; + return true; + } + else + { + hCode->length--; + hCode->code[hCode->length] = 0; + } + } + + if (treeRoot->right) + { + hCode->code[hCode->length] = '1'; + hCode->length++; + + if (buildHuffCode(treeRoot->right, hCode, goalChar)) + { + return true; + } + else + { + hCode->length--; + hCode->code[hCode->length] = 0; + } + } + + return false; +} + +// Вывести заголовок Хаффмана в выходной файл: +void writeHeader(FILE* dest, unsigned int numOfFreq, unsigned int fileSize) +{ + HuffHeader hHeader; + + hHeader.numOfFreq = numOfFreq; // количество частотностей. + hHeader.fileSize = fileSize; // размер файла. + + fwrite(&hHeader, sizeof(hHeader), 1, dest); +} + +// Вывести символ и его частотность в выходной файл: +void writeFreq(FILE* dest, unsigned int* freqList) +{ + unsigned int i; + HuffFreq hFreq; + for (i = 0; i < CHARS_LIMIT; i++) + { + // Если частотность символа больше 0, + // т.е. символ встречался во входном файле: + if (freqList[i] > 0) + { + hFreq.charCode = i; // код символа. + hFreq.freq = freqList[i]; // частотность символа. + + fwrite(&hFreq, sizeof(HuffFreq), 1, dest); + } + } +} + +// Вывести закодированные по Хаффману данные в выходной файл: +void writeEncodedData(FILE* src, FILE* dest, HuffCode* huffCodeTable, unsigned int fileSize) +{ + int i, c; + unsigned int bits = 0; + char currChar = 0; + HuffCode currCode; + bool cancel = false; + unsigned int interval = fileSize/100; + int progress = 1; + unsigned int bytes = 0; + + QProgressDialog progressDialog("Сжатие данных...", "Отмена", 0, fileSize, nullptr); + progressDialog.setWindowModality(Qt::WindowModal); + progressDialog.setValue(0); + + while ((c = fgetc(src)) != EOF) + { + bytes++; + currCode = huffCodeTable[c]; + + for (i = 0; i < currCode.length; i++) + { + currChar = (currChar << 1) + (currCode.code[i] == '1' ? 1 : 0); + bits++; + + if(bits == 8) + { + fputc(currChar, dest); + currChar = 0; + bits = 0; + } + } + + + if (bytes > interval * progress) + { + progressDialog.setValue(progress); + progress++; + } + + if (progressDialog.wasCanceled()) + { + cancel = true; + showDoneMessage("Отменено!", "Сжатие данных"); + break; + } + } + + if (bits > 0) + { + currChar = currChar << (8 - bits); + fputc(currChar, dest); + } + + progressDialog.setValue(fileSize); + + if (!cancel) + { + showDoneMessage("Файл успешно сжат!", "Сжатие данных"); + } +} + +// Вывести раскодированные по Хаффману данные в выходной файл: +void writeDecodedData(FILE * src, FILE * dest, HuffNode * rootTree, unsigned int fileSize) +{ + int bit = -1; + int c; + unsigned int bytesWritten = 0; + HuffNode * currNode = rootTree; + bool cancel = false; + unsigned int interval = fileSize/100; + int progress = 1; + + QProgressDialog progressDialog("Восстановление данных...", "Отмена", 0, fileSize, nullptr); + progressDialog.setWindowModality(Qt::WindowModal); + progressDialog.setValue(0); + + while (bytesWritten < fileSize) + { + if (bit < 0) + { + c = fgetc(src); + + if (c == EOF) + { + break; + } + + bit = 7; + } + + if ((c >> bit) & 1) + { + currNode = currNode->right; + } + else + { + currNode = currNode->left; + } + + if (currNode->leaf) + { + fputc(currNode->charCode, dest); + bytesWritten++; + currNode = rootTree; + } + + bit--; + + if (bytesWritten > interval*progress) + { + progressDialog.setValue(interval*progress); + progress++; + } + + if (progressDialog.wasCanceled()) + { + cancel = true; + showDoneMessage("Омененно!", "Восстановление данных"); + break; + } + } + + progressDialog.setValue(fileSize); + + if(!cancel) + { + showDoneMessage("Файл успешно восстановлен!", "Восстановление данных"); + } +} + +// Освободить память занятую по дерево Хаффмана: +void freeHuffTree(HuffNode* treeRoot) +{ + if (treeRoot) // если узел не пустой. + { + freeHuffTree(treeRoot->left); // удаляем левую часть. + freeHuffTree(treeRoot->right); // удаляем правую часть. + + // После того как левая и правая часть удалены, + // удаляем сам узел: + free(treeRoot); + } +} + +// Закодировать файл по Хаффману: +void huffmanEncode(const char* inputFile) +{ + // Открыть исходный файл: + FILE* src = fopen(inputFile, "rb"); + + // Проверка на существование входного файла: + if (src == NULL) + { + fprintf(stderr, "Невозможно открыть входной файл."); + exit(EXIT_FAILURE); + } + + // Открыть выходной файл: + char outputPath[1000]; + const char * fileExtension = ".bin"; + outputFilePath(inputFile, outputPath, fileExtension); + FILE * dest = fopen(outputPath, "wb"); + + // Получить размер входного файла: + unsigned int fileSize; + fileSize = getFileSize(src); + + // Посчитать частотности символов: + unsigned int * freqList; + freqList = (unsigned int *)calloc(CHARS_LIMIT, sizeof(unsigned int)); + calcCharFreq(src, freqList); + + // Посчитать количество частотностей + // (т.е. тех которые больше нуля): + unsigned int numOfFreq; + numOfFreq = calcNumOfFreq(freqList); + + // Построить список Хаффмана (частотности отсортированные по возрастанию): + HuffNode* nodeList = NULL; + buildNodeList(&nodeList, freqList); + + // Построить дерево Хаффмана: + buildHuffTree(&nodeList); + HuffNode * treeRoot = nodeList; + + // Построить таблицу Хаффмана: + unsigned int i; + HuffCode newCode; + HuffCode * huffCodeTable; + huffCodeTable = (HuffCode *)calloc(CHARS_LIMIT, sizeof(HuffCode)); + for(i=0; i 0) + { + newCode.length = 0; + buildHuffCode(treeRoot, &newCode, i); + huffCodeTable[i] = newCode; + } + } + + // Записать заголовок: + writeHeader(dest, numOfFreq, fileSize); + + // Записать частотности: + writeFreq(dest, freqList); + + // Вывести закодированные по Хаффману данные в выходной файл: + writeEncodedData(src, dest, huffCodeTable, fileSize); + + // Освободить память: + freeHuffTree(treeRoot); + treeRoot = NULL; + free(huffCodeTable); + free(freqList); + + // Закрыть файлы: + fclose(src); + fclose(dest); +} + +// Раскодировать файл по Хаффману: +void huffmanDecode(const char * inputFile) +{ + // Открыть исходный файл: + FILE *src = fopen(inputFile, "rb"); + + // Проверка на существование входного файла: + if (src == NULL) + { + fprintf(stderr, "Невозможно открыть входной файл."); + exit(EXIT_FAILURE); + } + + // Открыть выходной файл: + char outputPath[1000]; + const char* fileExtension = ".txt"; + outputFilePath(inputFile, outputPath, fileExtension); + FILE* dest = fopen(outputPath, "wb"); + + // Считать заголовок: + HuffHeader hHeader; + fread(&hHeader, sizeof(hHeader), 1, src); + + // Считать частотности: + HuffFreq* hFreq = (HuffFreq *)calloc(hHeader.numOfFreq, sizeof(HuffFreq)); + fread(hFreq, sizeof(HuffFreq), hHeader.numOfFreq, src); + + // Построить список частотностей: + HuffNode* nodeList = NULL; + buildNodeList(&nodeList, hFreq, hHeader.numOfFreq); + + // Построить дерево Хаффмана: + buildHuffTree(&nodeList); + + // Вывести раскодированные по Хаффману данные в выходной файл: + writeDecodedData(src, dest, nodeList, hHeader.fileSize); + + // Освободить память: + freeHuffTree(nodeList); + nodeList = NULL; + free(hFreq); + + // Закрыть файлы: + fclose(src); + fclose(dest); +} + +// Получить размер файла в байтах: +unsigned int getFileSize(FILE* src) +{ + unsigned int fileSize = 0; + int c; + + while ((c = fgetc(src)) != EOF) + { + fileSize++; + } + rewind(src); + + return fileSize; +} + +// Вычислить количество частотностей: +unsigned int calcNumOfFreq(unsigned int* freqList) +{ + unsigned int i; + unsigned int numOfFreq = 0; + + for (i = 0; i < CHARS_LIMIT; i++) + { + if (freqList[i] > 0) + { + numOfFreq++; + } + } + + return numOfFreq; +} + +// Сформировать имя выходного файла: +void outputFilePath(const char *path, char * outputPath, const char *fileExtension) +{ + int i; + const int pathLength = strlen(path); + + for (i = 0; i < pathLength - 4; i++) + { + outputPath[i] = path[i]; + } + outputPath[i] = 0; + + strcat(outputPath, fileExtension); +} diff --git a/Huffman-algorithm-implementation-in-Qt/huffman.h b/Huffman-algorithm-implementation-in-Qt/huffman.h new file mode 100644 index 0000000..61995d3 --- /dev/null +++ b/Huffman-algorithm-implementation-in-Qt/huffman.h @@ -0,0 +1,92 @@ +#ifndef HUFFMAN_H +#define HUFFMAN_H + +#include "stdio.h" + +// Константы: +#define MAX_CODE_SIZE 32 +#define CHARS_LIMIT 256 + +// Узел Хаффмана: +struct HuffNode +{ + unsigned int freq; // частотность. + unsigned char charCode; // код символа. + bool leaf; // является ли узел листом? + + // Навигация по дереву: + HuffNode* next; + HuffNode* left; + HuffNode* right; +}; + +// Таблица Хаффмана: +struct HuffCode +{ + unsigned char code[MAX_CODE_SIZE]; + int length; +}; + +// Заголовок Хаффмана: +struct HuffHeader +{ + unsigned int numOfFreq; // количество частотностей. + unsigned int fileSize; +}; + +// Частотность Хаффмана: +struct HuffFreq +{ + unsigned int freq; // частотность. + unsigned char charCode; // код символа. +}; + +// Посчитать частотность всех символов и сохранить в списке: +void calcCharFreq(FILE* src, unsigned int* freqList); + +// Построить список узлов Хаффмана (частотности сортируются по возрастанию): +void buildNodeList(HuffNode** nodeList, unsigned int* freqList); + +// Построить список узлов из раскодированных частотностей: +void buildNodeList(HuffNode** nodeList, HuffFreq* hFreq, unsigned int numOfFreq); + +// Добавить новый узел в список узлов Хаффмана (по возрастающему порядку): +void addToNodeList(HuffNode** nodeList, HuffNode* newNode); + +// Построить дерево Хаффмана из списка узлов Хаффмана: +void buildHuffTree(HuffNode** nodeList); + +// Построить таблицу перекодировки Хаффмана: +bool buildHuffCode(HuffNode* treeRoot, HuffCode* hCode, unsigned char goalChar); + +// Вывести заголовок Хаффмана в выходной файл: +void writeHeader(FILE* dest, unsigned int numOfFreq, unsigned int fileSize); + +// Вывести символ и его частотность в выходной файл: +void writeFreq(FILE* dest, unsigned int* freqList); + +// Вывести закодированные по Хаффману данные в выходной файл: +void writeEncodedData(FILE* src, FILE* dest, HuffCode* huffCodeTable, unsigned int fileSize); + +// Вывести раскодированные по Хаффману данные в выходной файл: +void writeDecodedData(FILE* src, FILE* dest, HuffNode* rootTree, unsigned int fileSize); + +// Освободить память занятую по дерево Хаффмана: +void freeHuffTree(HuffNode* treeRoot); + +// Закодировать файл по Хаффману: +void huffmanEncode(const char* inputFile); + +// Раскодировать файл по Хаффману: +void huffmanDecode(const char * inputFile); + +// Получить размер файла в байтах: +unsigned int getFileSize(FILE* src); + +// Вычислить количество частотностей: +unsigned int calcNumOfFreq(unsigned int* freqList); + +// Сформировать имя выходного файла: +void outputFilePath(const char* path, char* outputPath, const char *fileExtension); + +#endif // HUFFMAN_H diff --git a/Huffman-algorithm-implementation-in-Qt/main.cpp b/Huffman-algorithm-implementation-in-Qt/main.cpp new file mode 100644 index 0000000..70cb5c2 --- /dev/null +++ b/Huffman-algorithm-implementation-in-Qt/main.cpp @@ -0,0 +1,17 @@ +#include +#include "choose.h" +#include "encoding.h" +#include "decoding.h" + +// Точка входа в программу: +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + + // Создание и отображение диалогового окна с двумя кнопками + // "Сжать данные" и "Восстановить данные": + Choose w; + w.show(); + + return a.exec(); +} diff --git a/HuffmanCoding.pro b/HuffmanCoding.pro deleted file mode 100644 index 248f762..0000000 --- a/HuffmanCoding.pro +++ /dev/null @@ -1,29 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2012-07-02T00:13:53 -# -#------------------------------------------------- - -QT += core gui - -TARGET = HuffmanCoding -TEMPLATE = app - - -SOURCES += main.cpp\ - choose.cpp \ - encoding.cpp \ - decoding.cpp - -HEADERS += choose.h \ - encoding.h \ - decoding.h - -FORMS += choose.ui \ - encoding.ui \ - decoding.ui - -RESOURCES += \ - Res.qrc - -RC_FILE = AppIcon.rc diff --git a/HuffmanCoding.pro.user b/HuffmanCoding.pro.user deleted file mode 100644 index 96a930d..0000000 --- a/HuffmanCoding.pro.user +++ /dev/null @@ -1,365 +0,0 @@ - - - - - - ProjectExplorer.Project.ActiveTarget - 0 - - - ProjectExplorer.Project.EditorSettings - - true - false - - Cpp - - CppGlobal - - - - QmlJS - - QmlJSGlobal - - - 2 - System - false - 4 - true - 1 - true - 0 - true - 0 - 8 - true - 1 - true - true - true - false - - - - ProjectExplorer.Project.PluginSettings - - - - ProjectExplorer.Project.Target.0 - - Desktop - Desktop - Qt4ProjectManager.Target.DesktopTarget - 0 - 0 - 0 - - ProjectExplorer.ToolChain.Msvc:D:\Program Files\Microsoft SDKs\Windows\v7.1\bin\SetEnv.cmd:/x86:C:/Program Files/Debugging Tools for Windows (x64)/cdb.exe - - - qmake - - QtProjectManager.QMakeBuildStep - false - true - - false - - - Make - - Qt4ProjectManager.MakeStep - false - - - - 2 - Build - - ProjectExplorer.BuildSteps.Build - - - - Make - - Qt4ProjectManager.MakeStep - true - clean - - - 1 - Clean - - ProjectExplorer.BuildSteps.Clean - - 2 - false - - Qt 4.8.1 for Desktop - MSVC2010 (Qt SDK) Debug - - Qt4ProjectManager.Qt4BuildConfiguration - 2 - D:/Document/Qt_workspace/HuffmanCoding-build-desktop-Qt_4_8_1_for_Desktop_-_MSVC2010__Qt_SDK__Debug - 1 - true - - - ProjectExplorer.ToolChain.Msvc:D:\Program Files\Microsoft SDKs\Windows\v7.1\bin\SetEnv.cmd:/x86:C:/Program Files/Debugging Tools for Windows (x64)/cdb.exe - - - qmake - - QtProjectManager.QMakeBuildStep - false - true - - false - - - Make - - Qt4ProjectManager.MakeStep - false - - - - 2 - Build - - ProjectExplorer.BuildSteps.Build - - - - Make - - Qt4ProjectManager.MakeStep - true - clean - - - 1 - Clean - - ProjectExplorer.BuildSteps.Clean - - 2 - false - - Qt 4.8.1 for Desktop - MSVC2010 (Qt SDK) Release - - Qt4ProjectManager.Qt4BuildConfiguration - 0 - D:/Document/Qt_workspace/HuffmanCoding-build-desktop-Qt_4_8_1_for_Desktop_-_MSVC2010__Qt_SDK__Release - 1 - true - - - ProjectExplorer.ToolChain.Mingw:D:/QtSDK/mingw/bin/mingw32-g++.exe.x86-windows-msys-pe-32bit.d:/QtSDK/pythongdb/python_2.7based/gdb-i686-pc-mingw32.exe - - - qmake - - QtProjectManager.QMakeBuildStep - false - true - - false - - - Make - - Qt4ProjectManager.MakeStep - false - - - - 2 - Build - - ProjectExplorer.BuildSteps.Build - - - - Make - - Qt4ProjectManager.MakeStep - true - clean - - - 1 - Clean - - ProjectExplorer.BuildSteps.Clean - - 2 - false - - Qt 4.7.4 for Desktop - MinGW 4.4 (Qt SDK) Debug - - Qt4ProjectManager.Qt4BuildConfiguration - 2 - D:/Document/Qt_workspace/HuffmanCoding-build-desktop-Qt_4_7_4_for_Desktop_-_MinGW_4_4__Qt_SDK__Debug - 4 - true - - - ProjectExplorer.ToolChain.Mingw:D:/QtSDK/mingw/bin/mingw32-g++.exe.x86-windows-msys-pe-32bit.d:/QtSDK/pythongdb/python_2.7based/gdb-i686-pc-mingw32.exe - - - qmake - - QtProjectManager.QMakeBuildStep - false - true - - false - - - Make - - Qt4ProjectManager.MakeStep - false - - - - 2 - Build - - ProjectExplorer.BuildSteps.Build - - - - Make - - Qt4ProjectManager.MakeStep - true - clean - - - 1 - Clean - - ProjectExplorer.BuildSteps.Clean - - 2 - false - - Qt 4.7.4 for Desktop - MinGW 4.4 (Qt SDK) Release - - Qt4ProjectManager.Qt4BuildConfiguration - 0 - D:/Document/Qt_workspace/HuffmanCoding-build-desktop-Qt_4_7_4_for_Desktop_-_MinGW_4_4__Qt_SDK__Release - 4 - true - - 4 - - - 0 - Deploy - - ProjectExplorer.BuildSteps.Deploy - - 1 - No deployment - - ProjectExplorer.DefaultDeployConfiguration - - 1 - - true - true - - - false - false - false - false - false - false - false - false - true - true - 0.01 - 0.01 - 10 - 10 - true - true - 25 - 25 - - - true - true - valgrind - valgrind - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - - HuffmanCoding - - Qt4ProjectManager.Qt4RunConfiguration - 2 - - HuffmanCoding.pro - false - false - - - 3768 - true - false - false - - 1 - - - - ProjectExplorer.Project.TargetCount - 1 - - - ProjectExplorer.Project.Updater.EnvironmentId - {066e5e43-daa7-4569-af38-c687449d4982} - - - ProjectExplorer.Project.Updater.FileVersion - 10 - - diff --git a/README b/README deleted file mode 100644 index 127fb47..0000000 --- a/README +++ /dev/null @@ -1 +0,0 @@ -This is an implementation of Huffman algorithm in Qt. \ No newline at end of file diff --git a/Res.qrc b/Res.qrc deleted file mode 100644 index ff6f51a..0000000 --- a/Res.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - icon.png - - diff --git a/appIcon.ico b/appIcon.ico deleted file mode 100644 index ec73facc742f40d296f084384a93c78655f21ae5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 370070 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 - - /** Connect Compress File button to open compress dialog **/ - connect(ui->compressButton, SIGNAL(clicked()), this, SLOT(showCompressDialog())); - - /** Connect Decompress File button to open decompress dialog **/ - connect(ui->decompressButton, SIGNAL(clicked()), this, SLOT(showDecompressDialog())); -} - -Choose::~Choose() -{ - delete ui; -} - -void Choose::showCompressDialog() -{ - QDialog parent; - Encoding * en; - en = new Encoding(&parent); - en->setFixedSize(en->size()); - en->setWindowTitle("Huffman Encoding"); - en->exec(); -} - -void Choose::showDecompressDialog() -{ - QDialog parent; - Decoding * de; - de = new Decoding(&parent); - de->setFixedSize(de->size()); - de->setWindowTitle("Huffman Decoding"); - de->exec(); -} diff --git a/choose.ui b/choose.ui deleted file mode 100644 index af44272..0000000 --- a/choose.ui +++ /dev/null @@ -1,56 +0,0 @@ - - - Choose - - - - 0 - 0 - 284 - 161 - - - - Huffman Coding - - - - :/images/icon.png:/images/icon.png - - - - - 80 - 20 - 133 - 121 - - - - - - - Compress File - - - - - - - Decompress File - - - - - - - - - compressButton - decompressButton - - - - - - diff --git a/decoding.cpp b/decoding.cpp deleted file mode 100644 index 78374bf..0000000 --- a/decoding.cpp +++ /dev/null @@ -1,283 +0,0 @@ -/*********************************************** -Copyright (c) 2012 Piyush Kant -See the file license.txt for copying permission. -************************************************/ - -#include "decoding.h" -#include "ui_decoding.h" -#include "QFileDialog" -#include "QMessageBox" -#include "stdio.h" -#include "stdlib.h" -#include -#include "QDebug" -#include "QProgressDialog" -#include "choose.h" - -Decoding::Decoding(QWidget *parent) : - QDialog(parent), - ui(new Ui::Decoding) -{ - ui->setupUi(this); - - /** Connect decompress dialog buttons **/ - connect(ui->browseButton, SIGNAL(clicked()), this, SLOT(browseInputFile())); - connect(ui->decodeButton, SIGNAL(clicked()), this, SLOT(decompressFile())); - - /** Warning initially hidden **/ - ui->warningText->setVisible(false); -} - -Decoding::~Decoding() -{ - delete ui; -} - -void Decoding::browseInputFile() -{ - /** Open select file dialog **/ - inputFileName = QFileDialog::getOpenFileName(this, tr("Open File"),"/home/piyush/Desktop", - tr("Binary File (*.bin)")); - - ui->inputFile->setText(inputFileName); -} - -QString Decoding::getInputFileName() -{ - return inputFileName; -} - -void Decoding::outputFilePath(const char *path, char * outputPath, const char *fileExtension) -{ - int i; - const int pathLength = strlen(path); - - for(i=0; iwarningText->setVisible(false); - showDoneMessage("Please select a file."); - } - else - { - ui->warningText->setVisible(false); - - QByteArray byteArray1 = inputFileName.toUtf8(); - const char* inputFile = byteArray1.constData(); - huffmanDecode(inputFile); - } -} - -void Decoding::showDoneMessage(const char * msg) -{ - QMessageBox msgBox; - msgBox.setText(msg); - msgBox.setWindowTitle("Decompression"); - msgBox.setIcon(QMessageBox::Information); - QIcon icon(":/images/icon.png"); - msgBox.setWindowIcon(icon); - msgBox.exec(); -} - -void Decoding::buildNodeList(HuffNode ** nodeList, HuffFreq * hFreq, unsigned int numOfFreq) -{ - unsigned int i; - HuffNode * newNode; - - for (i = 0; i < numOfFreq; i++) - { - newNode = (HuffNode *) malloc(sizeof(HuffNode)); - newNode->charCode = hFreq[i].charCode; - newNode->freq = hFreq[i].freq; - newNode->next = NULL; - newNode->left = NULL; - newNode->right = NULL; - newNode->leaf = true; - - addToNodeList(nodeList, newNode); - } -} - -void Decoding::addToNodeList(HuffNode ** nodeList, HuffNode * newNode) -{ - HuffNode * prevNode = NULL; - HuffNode * currNode = *nodeList; - - while ((currNode != NULL && currNode->freq < newNode->freq)) - { - prevNode = currNode; - currNode = prevNode->next; - } - - newNode->next = currNode; - - if (prevNode == NULL) - { - *nodeList = newNode; - } - else - { - prevNode->next = newNode; - } -} - -void Decoding::buildHuffTree(HuffNode ** nodeList) -{ - HuffNode * newNode, * leftNode, * rightNode; - - while((*nodeList)->next != NULL) - { - newNode = (HuffNode *)malloc(sizeof(HuffNode)); - - leftNode = *nodeList; - *nodeList = leftNode->next; - - rightNode = *nodeList; - *nodeList = rightNode->next; - - newNode->charCode = 0; - newNode->freq = leftNode->freq + rightNode->freq; - newNode->next = NULL; - newNode->left = leftNode; - newNode->right = rightNode; - newNode->leaf = false; - - addToNodeList(nodeList, newNode); - } -} - -void Decoding::writeDecodedData(FILE * src, FILE * dest, HuffNode * rootTree, unsigned int fileSize) -{ - int bit = -1; - unsigned int c; - unsigned int bytesWritten = 0; - HuffNode * currNode = rootTree; - bool cancel = false; - unsigned int interval = fileSize/100; - int progress = 1; - - QProgressDialog progressDialog("Decompressing...", "Cancel", 0, fileSize, this); - progressDialog.setWindowModality(Qt::WindowModal); - progressDialog.setValue(0); - - while(bytesWritten < fileSize) - { - if(bit < 0) - { - c = fgetc(src); - - if(c == EOF) - { - break; - } - - bit = 7; - } - - if((c >> bit) & 1) - { - currNode = currNode->right; - } - else - { - currNode = currNode->left; - } - - if(currNode->leaf) - { - fputc(currNode->charCode, dest); - bytesWritten++; - currNode = rootTree; - } - - bit--; - - if(bytesWritten > interval*progress) - { - progressDialog.setValue(interval*progress); - progress++; - } - - if (progressDialog.wasCanceled()) - { - cancel = true; - showDoneMessage("Aborted!"); - break; - } - } - - progressDialog.setValue(fileSize); - - if(!cancel) - { - showDoneMessage("File Decompressed Successfully!"); - } -} - -void Decoding::freeHuffTree(HuffNode * treeRoot) -{ - if(treeRoot) - { - freeHuffTree(treeRoot->left); - freeHuffTree(treeRoot->right); - - free(treeRoot); - } -} - -void Decoding::huffmanDecode(const char * inputFile) -{ - /** Open source file **/ - FILE *src = fopen(inputFile, "rb"); - - /** Open destination file **/ - char outputPath[1000]; - const char * fileExtension = ".txt"; - outputFilePath(inputFile, outputPath, fileExtension); - FILE * dest = fopen(outputPath, "wb"); - - /** Check if file exist **/ - if (src == NULL) - { - fprintf(stderr, "Could not open file."); - exit(EXIT_FAILURE); - } - - /** Read Hufffman header **/ - HuffHeader hHeader; - fread(&hHeader, sizeof(hHeader), 1, src); - - /** Read Huffman freq **/ - HuffFreq *hFreq = (HuffFreq *)calloc(hHeader.numOfFreq, sizeof(HuffFreq)); - fread(hFreq, sizeof(HuffFreq), hHeader.numOfFreq, src); - - /** Produce frequency node list **/ - HuffNode * nodeList = NULL; - buildNodeList(&nodeList, hFreq, hHeader.numOfFreq); - - /** Build Huffman tree **/ - buildHuffTree(&nodeList); - - /** Write Huffman decoded data to destination file **/ - writeDecodedData(src, dest, nodeList, hHeader.fileSize); - - /** Free up memory **/ - freeHuffTree(nodeList); - nodeList = NULL; - free(hFreq); - - /** Close files **/ - fclose(src); - fclose(dest); -} diff --git a/decoding.h b/decoding.h deleted file mode 100644 index 4eabfa1..0000000 --- a/decoding.h +++ /dev/null @@ -1,93 +0,0 @@ -/*********************************************** -Copyright (c) 2012 Piyush Kant -See the file license.txt for copying permission. -************************************************/ - -#ifndef DECODING_H -#define DECODING_H - -#include - -namespace Ui { -class Decoding; -} - -class Decoding : public QDialog -{ - Q_OBJECT - -public: - explicit Decoding(QWidget *parent = 0); - ~Decoding(); - - /** Input file name getter **/ - QString getInputFileName(); - - /** Huffman encoding **/ - void huffmanDecode(const char * inputFile); - -private: - Ui::Decoding *ui; - - /** Input file name string **/ - QString inputFileName; - - /** Output file path **/ - void outputFilePath(const char * path, char * outputPath, const char * fileExtension); - - /** Get output file name **/ - void getOutputFileName(); - - /** Show decompressing done message **/ - void showDoneMessage(const char * msg); - - /** Huffman node **/ - struct HuffNode - { - unsigned char charCode; - unsigned int freq; - bool leaf; - HuffNode * next; - HuffNode * left; - HuffNode * right; - }; - - /** Huffman header node **/ - struct HuffHeader - { - unsigned int numOfFreq; - unsigned int fileSize; - }; - - /** Huffman freq node **/ - struct HuffFreq - { - unsigned int freq; - unsigned char charCode; - }; - - /** Build node list of decoded freq **/ - void buildNodeList(HuffNode ** nodeList, HuffFreq * hFreq, unsigned int numOfFreq); - - /** Add new Huffman node to node list **/ - void addToNodeList(HuffNode ** nodeList, HuffNode * newNode); - - /** Construct Huffman tree **/ - void buildHuffTree(HuffNode ** nodeList); - - /** Write Huffman decoded data to output file **/ - void writeDecodedData(FILE * src, FILE * dest, HuffNode * rootTree, unsigned int fileSize); - - /** Free Huffman tree memory **/ - void freeHuffTree(HuffNode * treeRoot); - -public slots: - - /** Browse input file **/ - void browseInputFile(); - - /** Compress file **/ - void decompressFile(); -}; - -#endif // DECODING_H diff --git a/decoding.ui b/decoding.ui deleted file mode 100644 index 1c8dfb4..0000000 --- a/decoding.ui +++ /dev/null @@ -1,81 +0,0 @@ - - - Decoding - - - - 0 - 0 - 563 - 111 - - - - Dialog - - - - :/images/icon.png:/images/icon.png - - - - - 20 - 20 - 521 - 29 - - - - - - - - - - - - - - Browse - - - - - - - - - 210 - 70 - 91 - 23 - - - - Decompress - - - - - - 330 - 70 - 121 - 16 - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-style:italic; color:#ff0000;">*Please Select a File</span></p></body></html> - - - - - - - - diff --git a/encoding.cpp b/encoding.cpp deleted file mode 100644 index 629b467..0000000 --- a/encoding.cpp +++ /dev/null @@ -1,419 +0,0 @@ -/*********************************************** -Copyright (c) 2012 Piyush Kant -See the file license.txt for copying permission. -************************************************/ - -#include "encoding.h" -#include "ui_encoding.h" -#include "QFileDialog" -#include "QMessageBox" -#include "stdio.h" -#include "stdlib.h" -#include -#include "QProgressDialog" - -Encoding::Encoding(QWidget *parent) : - QDialog(parent), - ui(new Ui::Encoding) -{ - ui->setupUi(this); - - /** Connect compress dialog buttons **/ - connect(ui->browseButton, SIGNAL(clicked()), this, SLOT(browseInputFile())); - connect(ui->encodeButton, SIGNAL(clicked()), this, SLOT(compressFile())); - - /** Warning initially hidden **/ - ui->warningText->setVisible(false); -} - -Encoding::~Encoding() -{ - delete ui; -} - -void Encoding::browseInputFile() -{ - /** Open select file dialog **/ - inputFileName = QFileDialog::getOpenFileName(this, tr("Open File"),"/home/piyush/Desktop", - tr("Document Files (*.txt)")); - ui->inputFile->setText(inputFileName); -} - -void Encoding::outputFilePath(const char *path, char * outputPath, const char *fileExtension) -{ - int i; - const int pathLength = strlen(path); - - for(i=0; iwarningText->setVisible(false); - showDoneMessage("Please select a file."); - } - else - { - ui->warningText->setVisible(false); - - QByteArray byteArray1 = inputFileName.toUtf8(); - const char* inputFile = byteArray1.constData(); - - huffmanEncode(inputFile); - } -} - -void Encoding::showDoneMessage(const char * msg) -{ - QMessageBox msgBox; - msgBox.setText(msg); - msgBox.setWindowTitle("Compression"); - msgBox.setIcon(QMessageBox::Information); - QIcon icon(":/images/icon.png"); - msgBox.setWindowIcon(icon); - msgBox.exec(); -} - -unsigned int Encoding::getFileSize(FILE * src) -{ - unsigned int fileSize = 0; - unsigned int c; - - while((c = fgetc(src)) != EOF) - { - fileSize++; - } - rewind(src); - - return fileSize; -} - -void Encoding::calcCharFreq(FILE * src, unsigned int * freqList) -{ - unsigned int c; - - while((c = fgetc(src)) != EOF) - { - freqList[c]++; - } - rewind(src); -} - -unsigned int Encoding::calcNumOfFreq(unsigned int * freqList) -{ - unsigned int i; - unsigned int numOfFreq = 0; - - for(i=0; i 0) - { - numOfFreq++; - } - } - - return numOfFreq; -} - -void Encoding::buildNodeList(HuffNode ** nodeList, unsigned int * freqList) -{ - unsigned int i; - HuffNode * newNode; - - for(i=0; i 0) - { - newNode = (HuffNode *)calloc(1, sizeof(HuffNode)); - newNode->charCode = i; - newNode->freq = freqList[i]; - newNode->next = NULL; - newNode->left = NULL; - newNode->right = NULL; - newNode->leaf = true; - - addToNodeList(nodeList, newNode); - } - } -} - -void Encoding::addToNodeList(HuffNode ** nodeList, HuffNode * newNode) -{ - HuffNode * prevNode = NULL; - HuffNode * currNode = *nodeList; - - while(currNode != NULL && currNode->freq < newNode->freq) - { - prevNode = currNode; - currNode = prevNode->next; - } - - newNode->next = currNode; - - if(prevNode == NULL) - { - *nodeList = newNode; - } - else - { - prevNode->next = newNode; - } -} - -void Encoding::buildHuffTree(HuffNode ** nodeList) -{ - HuffNode * leftNode, * rightNode, * currNode; - HuffNode * newNode; - - while((*nodeList)->next) - { - leftNode = *nodeList; - *nodeList = leftNode->next; - - rightNode = *nodeList; - *nodeList = rightNode->next; - - newNode = (HuffNode *)calloc(1, sizeof(HuffNode)); - newNode->charCode = 0; - newNode->freq = leftNode->freq + rightNode->freq; - newNode->next = NULL; - newNode->left = leftNode; - newNode->right = rightNode; - newNode->leaf = false; - - addToNodeList(nodeList, newNode); - } -} - -bool Encoding::buildHuffCode(HuffNode * treeRoot, HuffCode * hCode, unsigned char goalChar) -{ - if(treeRoot->charCode == goalChar && treeRoot->leaf) - { - return true; - } - - if(treeRoot->left) - { - hCode->code[hCode->length] = '0'; - hCode->length++; - - if(hCode->length == MAX_CODE_SIZE) - { - printf("Code size exceeds limit!"); - return false; - } - - if(buildHuffCode(treeRoot->left, hCode, goalChar)) - { - hCode->code[hCode->length] = 0; - return true; - } - else - { - hCode->length--; - hCode->code[hCode->length] = 0; - } - } - - if(treeRoot->right) - { - hCode->code[hCode->length] = '1'; - hCode->length++; - - if(buildHuffCode(treeRoot->right, hCode, goalChar)) - { - return true; - } - else - { - hCode->length--; - hCode->code[hCode->length] = 0; - } - } - - return false; -} - -void Encoding::writeHeader(FILE * dest, HuffHeader hHeader, unsigned int numOfFreq, unsigned int fileSize) -{ - hHeader.numOfFreq = numOfFreq; - hHeader.fileSize = fileSize; - - fwrite(&hHeader, sizeof(hHeader), 1, dest); -} - -void Encoding::writeFreq(FILE * dest, unsigned int * freqList, HuffFreq hFreq) -{ - unsigned int i; - - for(i=0; i 0) - { - hFreq.charCode = i; - hFreq.freq = freqList[i]; - - fwrite(&hFreq, sizeof(HuffFreq), 1, dest); - } - } -} - -void Encoding::writeEncodedData(FILE * src, FILE * dest, HuffCode * huffCodeTable, unsigned int fileSize) -{ - unsigned int i, c; - unsigned int bits = 0; - char currChar = 0; - HuffCode currCode; - bool cancel = false; - unsigned int interval = fileSize/100; - int progress = 1; - unsigned int bytes = 0; - - QProgressDialog progressDialog("Compressing...", "Cancel", 0, fileSize, this); - progressDialog.setWindowModality(Qt::WindowModal); - progressDialog.setValue(0); - - while((c = fgetc(src)) != EOF) - { - bytes++; - currCode = huffCodeTable[c]; - - for(i=0; i interval*progress) - { - progressDialog.setValue(progress); - progress++; - } - - if (progressDialog.wasCanceled()) - { - cancel = true; - showDoneMessage("Aborted!"); - break; - } - } - - if(bits > 0) - { - currChar = currChar << (8 - bits); - fputc(currChar, dest); - } - - progressDialog.setValue(fileSize); - - if(!cancel) - { - showDoneMessage("File Compressed Successfully!"); - } -} - -void Encoding::freeHuffTree(HuffNode * treeRoot) -{ - if(treeRoot) - { - freeHuffTree(treeRoot->left); - freeHuffTree(treeRoot->right); - - free(treeRoot); - } -} - -void Encoding::huffmanEncode(const char* inputFile) -{ - /** Read source file **/ - FILE * src = fopen(inputFile, "rb"); - - /** Open destination file **/ - char outputPath[1000]; - const char * fileExtension = ".bin"; - outputFilePath(inputFile, outputPath, fileExtension); - FILE * dest = fopen(outputPath, "wb"); - - /** Check if source file exists **/ - if (src == NULL || dest == NULL) - { - printf("Could not find the input file!"); - exit(EXIT_FAILURE); - } - - /** Get size of source file **/ - unsigned int fileSize; - fileSize = getFileSize(src); - - /** Produce chars freqency list **/ - unsigned int * freqList; - freqList = (unsigned int *)calloc(CHARS_LIMIT, sizeof(unsigned int)); - calcCharFreq(src, freqList); - - /** Calculate number of frequencies **/ - unsigned int numOfFreq; - numOfFreq = calcNumOfFreq(freqList); - - /** Produce Huffman node list (frequencies sorted in ascending order)**/ - HuffNode * nodeList = NULL; - buildNodeList(&nodeList, freqList); - - /** Build Huffman tree **/ - buildHuffTree(&nodeList); - HuffNode * treeRoot = nodeList; - - /** Build Huffman code lookup table **/ - unsigned int i; - HuffCode newCode; - HuffCode * huffCodeTable; - huffCodeTable = (HuffCode *)calloc(CHARS_LIMIT, sizeof(HuffCode)); - for(i=0; i 0) - { - newCode.length = 0; - buildHuffCode(treeRoot, &newCode, i); - huffCodeTable[i] = newCode; - } - } - - /** Write Hufffman header to destination file **/ - HuffHeader hHeader; - writeHeader(dest, hHeader, numOfFreq, fileSize); - - /** Write Huffman freq to destination file **/ - HuffFreq hFreq; - writeFreq(dest, freqList, hFreq); - - /** Write encoded data to destination file **/ - writeEncodedData(src, dest, huffCodeTable, fileSize); - - /** Free up memory **/ - freeHuffTree(treeRoot); - treeRoot = NULL; - free(huffCodeTable); - free(freqList); - - /** Close files **/ - fclose(src); - fclose(dest); -} - - diff --git a/encoding.h b/encoding.h deleted file mode 100644 index 2204e27..0000000 --- a/encoding.h +++ /dev/null @@ -1,120 +0,0 @@ -/*********************************************** -Copyright (c) 2012 Piyush Kant -See the file license.txt for copying permission. -************************************************/ - -#ifndef ENCODING_H -#define ENCODING_H - -#include -#include - -/* Constants */ -#define MAX_CODE_SIZE 32 -#define CHARS_LIMIT 256 - -namespace Ui { -class Encoding; -} - -class Encoding : public QDialog -{ - Q_OBJECT - -public: - explicit Encoding(QWidget *parent = 0); - ~Encoding(); - - /** Input file name getter **/ - QString getInputFileName(); - - /** Huffman encoding **/ - void huffmanEncode(const char* inputFile); - - /** Get size of file (in bytes) **/ - unsigned int getFileSize(FILE * src); - - /** Calculate number of frequencies **/ - unsigned int calcNumOfFreq(unsigned int * freqList); - -private: - Ui::Encoding *ui; - - /** Input file name string **/ - QString inputFileName; - - /** Output file path **/ - void outputFilePath(const char * path, char * outputPath, const char * fileExtension); - - /** Show decompressing done message **/ - void showDoneMessage(const char * msg); - - /** Huffman node **/ - struct HuffNode - { - unsigned int freq; - unsigned char charCode; - bool leaf; - HuffNode * next; - HuffNode * left; - HuffNode * right; - }; - - /** Hufman code **/ - struct HuffCode - { - unsigned char code[MAX_CODE_SIZE]; - unsigned int length; - }; - - /** Huffman header node **/ - struct HuffHeader - { - unsigned int numOfFreq; - unsigned int fileSize; - }; - - /** Huffman freq node **/ - struct HuffFreq - { - unsigned int freq; - unsigned char charCode; - }; - - /** Calculate & store freq of each char in list **/ - void calcCharFreq(FILE * src, unsigned int * freqList); - - /** Build Huffman node list (frequencies sorted in ascending order) **/ - void buildNodeList(HuffNode ** nodeList, unsigned int * freqList); - - /** Add new node to list (in ascending order) **/ - void addToNodeList(HuffNode ** nodeList, HuffNode * newNode); - - /** Build Huffman tree from nodeList **/ - void buildHuffTree(HuffNode ** nodeList); - - /** Build Huffman code lookup table **/ - bool buildHuffCode(HuffNode * treeRoot, HuffCode * hCode, unsigned char goalChar); - - /** Write Huffman header to output file **/ - void writeHeader(FILE * dest, HuffHeader hHeader, unsigned int numOfFreq, unsigned int fileSize); - - /** Write char & freq data to output file **/ - void writeFreq(FILE * dest, unsigned int * freqList, HuffFreq hFreq); - - /** Write Huffman encoded data to output file **/ - void writeEncodedData(FILE * src, FILE * dest, HuffCode * huffCodeTable, unsigned int fileSize); - - /** Free Huffman tree memory **/ - void freeHuffTree(HuffNode * treeRoot); - -public slots: - - /** Browse input file **/ - void browseInputFile(); - - /** Compress file **/ - void compressFile(); -}; - -#endif // ENCODING_H diff --git a/encoding.ui b/encoding.ui deleted file mode 100644 index 25f373e..0000000 --- a/encoding.ui +++ /dev/null @@ -1,81 +0,0 @@ - - - Encoding - - - - 0 - 0 - 563 - 111 - - - - Dialog - - - - :/images/icon.png:/images/icon.png - - - - - 20 - 20 - 521 - 29 - - - - - - - - - - - - - - Browse - - - - - - - - - 210 - 70 - 91 - 23 - - - - Compress - - - - - - 320 - 70 - 141 - 20 - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-style:italic; color:#ff0000;">*Please Select a File</span></p></body></html> - - - - - - - - diff --git a/icon.png b/icon.png deleted file mode 100644 index f7289d328963e171636951e2e4485327769437a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31370 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

-R)wFVMWFPkUKs1w{Q- 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

XF{S{cpq= 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 czf5K(z|cI0BF;f>FdQ1 -#include "choose.h" -#include "encoding.h" -#include "decoding.h" - -int main(int argc, char *argv[]) -{ - QApplication a(argc, argv); - Choose w; - w.show(); - - return a.exec(); -}