-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcompressor.cpp
More file actions
160 lines (142 loc) · 3.64 KB
/
compressor.cpp
File metadata and controls
160 lines (142 loc) · 3.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/* Compressor LZW by Caroline GALLIEZ */
#include <iostream>
#include <fstream>
#include <iomanip>
#include <map>
#include <sstream>
using namespace std;
class lzwStream : public ifstream
{
private:
map<string,unsigned int> dictionary;
void writeCode(unsigned short code, ostream &output);
int Position = 0;
char OldCode = 0;
public:
// Constructor
lzwStream():ifstream() { initializeDictionary(); };
// Compressor function
bool CompressToStream(ostream &output);
// Initialize (or reinitialize) the dictionary
void initializeDictionary();
};
void lzwStream::initializeDictionary()
{
// Remove all the elements from the dictionary
dictionary.clear();
// Fill it with initial values
for (unsigned int code=0; code<=255; code++)
{
// we use a string because we may have to add to the dictionary a string (for instance "HE")
string E;(char)code;
E = (char)code;
dictionary.insert(pair<string, unsigned int>(E,code));
}
}
void lzwStream::writeCode(unsigned short code, ostream &output)
{
// If we have an even number of code
if (Position & 1)
{
OldCode = (OldCode << 4) | (code >> 8);
output.write(&OldCode, 1);
OldCode = code & 0xff;
output.write(&OldCode, 1);
}
else // we have an odd number of code
{
OldCode = code & 0xf;
code = code >> 4;
output.write((char*)&code, 1);
}
Position++;
}
// function Compression(text, dictionnary):
// w = ""
// WHILE (there is character to read in the text):
// c = Read(text) // one char
// p = concatenate(w,c)
// IF (p is in the dictionary):
// w=p
// ELSE:
// Add p to the dictionnary
// Write the code of w to the compressed file
// w=c
// END;
bool lzwStream::CompressToStream(ostream &output)
{
string w = ""; // Initialize an empty string
string p;
bool bEven = 0;
while (true)
{
// Read one code in the Lzw file
char c;
this->read((char *)&c, 1);
if (this->eof()) // If we have reached the end of file we return false
{
map<string, unsigned int>::iterator itw;
itw = dictionary.find(w);
if (itw != dictionary.end())
{
// write
writeCode(itw->second, output);
}
return false;
}
p = w + c; // Concatenate w and c
// Find p in the dictionnary
map<string, unsigned int>::iterator itp;
itp = dictionary.find(p);
if (itp == dictionary.end()) // p is not in the dictionnary
{
// add p to the dictionnary
if (dictionary.size() >= (size_t)(1 << 12)) // if dictionnary is full, we reinitialize it
initializeDictionary();
dictionary.insert(pair<string, unsigned int>(p, (unsigned)dictionary.size()));
// Write the w code to the compressed file
map<string, unsigned int>::iterator itw;
itw = dictionary.find(w);
if (itw != dictionary.end()) // If we have found w
{
// write
writeCode(itw->second, output);
}
w = c;
}
else
w = p;
}
return true;
}
int main (int argc, char *argv[])
{
// Verify the command line arguments
string fileName;
if (argc!=2)
{
cout << "Syntax: compressor filename\n";
return 0;
}
else
fileName = argv[1];
// Create the lzm File and the compressed file
string fileNameCompressed;
lzwStream fileToCompress;
ofstream fileCompressed;
// Open the file to compress
fileToCompress.open(fileName.c_str(), ios::binary);
// Open the compressed file
fileNameCompressed=fileName.substr(0,fileName.find_last_of('.'))+".z";
fileCompressed.open(fileNameCompressed.c_str(), ios::binary);
if (!fileToCompress.is_open())
{
cout << "Cannot open file " << fileName << "\n";
}
// Compress to the file
fileToCompress.CompressToStream(fileCompressed);
// Close the files
fileToCompress.close();
fileCompressed.close();
return 1;
}