141 lines
3.2 KiB
C++
141 lines
3.2 KiB
C++
#include "pibytearray.h"
|
|
|
|
|
|
int PIHuffman::nodeCompare(const void * f, const void * s) {
|
|
return (reinterpret_cast<node * >(const_cast<void * >(s))->freq -
|
|
reinterpret_cast<node * >(const_cast<void * >(f))->freq);
|
|
}
|
|
|
|
|
|
PIVector<uchar> PIHuffman::compress(const PIVector<uchar> & src) {
|
|
calcFrequencies(src);
|
|
return src;
|
|
}
|
|
|
|
|
|
void PIHuffman::calcFrequencies(const PIVector<uchar> & src) {
|
|
nodes.resize(256);
|
|
for (uint i = 0; i < 256; ++i) {
|
|
nodes[i].parent = nodes[i].right = nodes[i].left = 0;
|
|
nodes[i].freq = 0;
|
|
nodes[i].word.resize(1);
|
|
nodes[i].word[0] = static_cast<uchar>(i);
|
|
}
|
|
for (uint i = 0; i < src.size(); ++i)
|
|
nodes[src[i]].freq++;
|
|
std::qsort(nodes.data(), 256, sizeof(node), nodeCompare);
|
|
for (uint i = 255; i >= 0; --i)
|
|
if (nodes[i].freq > 0 && i < 255)
|
|
{nodes.remove(i + 1, 255 - i); break;}
|
|
for (uint i = 0; i < nodes.size(); ++i)
|
|
cout << string((char*)nodes[i].word.data(), 1) << ": " << nodes[i].freq << endl;
|
|
}
|
|
|
|
|
|
PIHuffman PIByteArray::huffman;
|
|
|
|
PIByteArray & PIByteArray::convertToBase64() {
|
|
base64HelpStruct hs;
|
|
PIByteArray t;
|
|
if (size() == 0) return *this;
|
|
uint sz = (size() / 3) * 3;
|
|
for (uint i = 0; i < sz; ++i) {
|
|
hs.byte0 = hs.byte1 = hs.byte2 = 0;
|
|
hs.byte0 = at(i);
|
|
hs.byte1 = at(++i);
|
|
hs.byte2 = at(++i);
|
|
t.push_back(base64Table[hs.ascii0]);
|
|
t.push_back(base64Table[hs.ascii1]);
|
|
t.push_back(base64Table[hs.ascii2]);
|
|
t.push_back(base64Table[hs.ascii3]);
|
|
}
|
|
hs.byte0 = hs.byte1 = hs.byte2 = 0; sz = size() % 3;
|
|
switch (sz) {
|
|
case 1:
|
|
hs.byte0 = back();
|
|
t.push_back(base64Table[hs.ascii0]);
|
|
t.push_back(base64Table[hs.ascii1]);
|
|
t.push_back('=');
|
|
t.push_back('=');
|
|
break;
|
|
case 2:
|
|
hs.byte0 = at(size() - 2); hs.byte1 = back();
|
|
t.push_back(base64Table[hs.ascii0]);
|
|
t.push_back(base64Table[hs.ascii1]);
|
|
t.push_back(base64Table[hs.ascii2]);
|
|
t.push_back('=');
|
|
break;
|
|
default: break;
|
|
}
|
|
*this = t;
|
|
return *this;
|
|
}
|
|
|
|
|
|
PIByteArray & PIByteArray::convertFromBase64() {
|
|
base64HelpStruct hs;
|
|
PIByteArray t;
|
|
uint sz = size();
|
|
if (sz == 0) return *this;
|
|
for (uint i = 0; i < sz; ++i) {
|
|
hs.byte0 = hs.byte1 = hs.byte2 = 0;
|
|
hs.ascii0 = base64InvTable[at(i)];
|
|
hs.ascii1 = base64InvTable[at(++i)];
|
|
hs.ascii2 = base64InvTable[at(++i)];
|
|
hs.ascii3 = base64InvTable[at(++i)];
|
|
t.push_back(hs.byte0);
|
|
t.push_back(hs.byte1);
|
|
t.push_back(hs.byte2);
|
|
}
|
|
if (back() == '=') t.pop_back();
|
|
if (sz > 1) if (at(sz - 2) == '=') t.pop_back();
|
|
*this = t;
|
|
return *this;
|
|
}
|
|
|
|
|
|
PIByteArray & PIByteArray::compressRLE(uchar threshold) {
|
|
PIByteArray t;
|
|
uchar fb, clen, mlen = 255 - threshold;
|
|
for (uint i = 0; i < size();) {
|
|
fb = at(i);
|
|
clen = 1;
|
|
while (at(++i) == fb) {
|
|
++clen;
|
|
if (clen == mlen)
|
|
break;
|
|
}
|
|
if (clen > 1) {
|
|
t.push_back(threshold + clen);
|
|
t.push_back(fb);
|
|
continue;
|
|
}
|
|
if (fb >= threshold) {
|
|
t.push_back(threshold + 1);
|
|
t.push_back(fb);
|
|
} else
|
|
t.push_back(fb);
|
|
}
|
|
*this = t;
|
|
return *this;
|
|
}
|
|
|
|
|
|
PIByteArray & PIByteArray::decompressRLE(uchar threshold) {
|
|
PIByteArray t;
|
|
uchar fb, clen;
|
|
for (uint i = 0; i < size(); ++i) {
|
|
fb = at(i);
|
|
if (fb >= threshold) {
|
|
clen = fb - threshold;
|
|
fb = at(++i);
|
|
for (uint j = 0; j < clen; ++j)
|
|
t.push_back(fb);
|
|
continue;
|
|
} else
|
|
t.push_back(fb);
|
|
}
|
|
*this = t;
|
|
return *this;
|
|
}
|