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 ec73fac..0000000
Binary files a/appIcon.ico and /dev/null differ
diff --git a/choose.cpp b/choose.cpp
deleted file mode 100644
index 840ce87..0000000
--- a/choose.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/***********************************************
-Copyright (c) 2012 Piyush Kant
-See the file license.txt for copying permission.
-************************************************/
-
-#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);
-
- /** 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 f7289d3..0000000
Binary files a/icon.png and /dev/null differ
diff --git a/license.txt b/license.txt
deleted file mode 100644
index 789ef32..0000000
--- a/license.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-Copyright (c) 2012 Piyush Kant
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
\ No newline at end of file
diff --git a/main.cpp b/main.cpp
deleted file mode 100644
index 00aa48c..0000000
--- a/main.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-/***********************************************
-Copyright (c) 2012 Piyush Kant
-See the file license.txt for copying permission.
-************************************************/
-
-#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();
-}