C++画像圧縮アルゴリズムbmpハフマンツリー
12302 ワード
Compressor.h
#pragma once
#include"HuffmanTree.h"
#include"HCode.h"
#include
#include
class Compressor
{
public:
Compressor();
~Compressor();
void compress(string TargetPath, string sourcePath);//
void decompress(string TargetPath, string sourcePath);//
private:
int colorTypeCount;
int imageWidth;
int imageHeight;
string filePath;
HuffmanTree *tree;
};
HCode.h
#pragma once
#include
#include
using namespace std;
class Color
{
int color;
int count;
};
class HCode
{
public:
HCode();
~HCode();
void addColor(unsigned char color);
int getCodeLen();
bool getBItAt(int inidx);
void addBit(bool in, unsigned char color);
void tranverse();
HCode& operator<
HuffmanTree.h
#pragma once
#include"HCode.h"
#include
using namespace std;
class HuffmanTreeNode
{
public:
HuffmanTreeNode();
char data;//
int weight;//
HuffmanTreeNode * leftChild;
HuffmanTreeNode * rightChild;
};
class HuffmanTree
{
public:
int size;
void HuffmanTreeCreate();
HuffmanTree();
HCode hcode;
~HuffmanTree();
void getCodeRecusion(HuffmanTreeNode * root, string code);
void getCodeMa();
HuffmanTreeNode *root;
void deleteTree(HuffmanTreeNode *root);
};
class MinHeap
{
public:
HuffmanTreeNode ** heapArray;
int currentSize;
int maxSize;
MinHeap(int max);
bool insert(HuffmanTreeNode * data);
HuffmanTreeNode * removeMin();
void shiftDown(int left);
void shiftUp(int child);
};
Compressor.cpp
#include "Compressor.h"
typedef struct tagBITMAPFILEHEADER//BMP (14 )
{
unsigned short bfType; // , BM(0-1 )
unsigned int bfSize; // , (2-5 )
unsigned short bfReserved1; // , 0(6-7 )
unsigned short bfReserved2; // , 0(8-9 )
unsigned int bfOffBits; // , (10-13 )
// ,
} BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER // (40 )
{
unsigned int biSize; // (14-17 )
unsigned int biWidth; // , (18-21 )
unsigned int biHeight; // , (22-25 )
unsigned short biPlanes; // , 1(26-27 )
unsigned short biBitCount;// , 1( ),(28-29 )
// 4(16 ),8(256 ) 24( )
unsigned int biCompression; // , 0( ),(30-33 )
// 1(BI_RLE8 ) 2(BI_RLE4 )
unsigned int biSizeImage; // , (34-37 )
unsigned int biXPelsPerMeter; // , (38-41 )
unsigned int biYPelsPerMeter; // , (42-45 )
unsigned int biClrUsed;// (46-49 )
unsigned int biClrImportant;// (50-53 )
} BITMAPINFOHEADER;
typedef struct tagRGBQUAD
{
unsigned char Blue;// ( 0-255)
unsigned char Green; // ( 0-255)
unsigned char Red; // ( 0-255)
unsigned char Alpha;//
} RGBA;
Compressor::Compressor()
{
tree = new HuffmanTree;
}
Compressor::~Compressor()
{
}
void Compressor::compress(string TargetPath,string sourcePath)
{
ofstream outfile(TargetPath, ios_base::binary);
ifstream infile(sourcePath, ios_base::binary);
if (!infile.is_open())
{
cout << " " << endl;
return;
}
if (!outfile.is_open())
{
cout << " " << endl;
return;
}
BITMAPFILEHEADER bmphead;
tagBITMAPINFOHEADER bmptag;
infile.read((char *)&bmphead, 14);
infile.read((char *)&bmptag, 40);
cout << bmptag.biHeight << " " << bmptag.biWidth << bmptag.biBitCount << endl;
int max = 4 * bmptag.biWidth*bmptag.biHeight;
unsigned char * bmpdot = new unsigned char[max];
cout << max;
for (int i = 0; i < max; i++)
{
infile.read((char *)(bmpdot + i), 1);
tree->hcode.addColor(bmpdot[i]);
}
tree->HuffmanTreeCreate();//
for (int i = 0; i < 256; i++)
{
if (tree->hcode.codeLength[i] != 0)
cout << " " << i << " " << tree->hcode.codeContent[i] << " " << tree->hcode.codeLength[i] << endl;
}
tree->getCodeMa();
outfile.write((char *)&bmphead, 14);
outfile.write((char *)&bmptag, 40);
for (int i = 0; i < 256; i++) //
{
if (tree->hcode.codeLength[i] != 0)
{
outfile.write((char *)&i, 1);
outfile.write((char *)&(tree->hcode.codeLength[i]), 1);
for (int p = 0; phcode.codeBYTE[i]; p++)
outfile.write((char *)&(tree->hcode.code[i][p]), 1);
}
}
int i = 0;
outfile.write((char *)&i, 4);
unsigned int Buffer = 0;
int Bufferlen = 0;
for (int i = 0; i < max; i++) //
{
unsigned char thiscolor = bmpdot[i];
int thisColorLen = tree->hcode.codeLength[thiscolor];
for (int k = 0; k < tree->hcode.codeBYTE[thiscolor]; k++)
{
int mmm = tree->hcode.codeBYTE[thiscolor];
if (thisColorLen >= 8)
{
Buffer = (Buffer << 8) | tree->hcode.code[thiscolor][k];
Bufferlen += 8;
thisColorLen -= 8;
}
else
{
Buffer = (Buffer << thisColorLen) | (tree->hcode.code[thiscolor][k] >> (8 - thisColorLen));
Bufferlen += thisColorLen;
thisColorLen = 0;
}
if (Bufferlen >= 8)
{
int temp = Buffer >> (Bufferlen - 8);
outfile.write((char *)&temp, 1);
Bufferlen -= 8;
}
}
}
infile.close();
outfile.close();
}
void Compressor::decompress(string TargetPath, string sourcePath)
{
ofstream outfile(TargetPath, ios_base::binary);
ifstream infile(sourcePath, ios_base::binary);
if (!infile.is_open())
{
cout << " " << endl;
return;
}
if (!outfile.is_open())
{
cout << " " << endl;
return;
}
BITMAPFILEHEADER bmphead;
tagBITMAPINFOHEADER bmptag;
infile.read((char *)&bmphead, 14);
infile.read((char *)&bmptag, 40);
outfile.write((char *)&bmphead, 14);
outfile.write((char *)&bmptag, 40);
cout << bmptag.biHeight << " " << bmptag.biWidth << bmptag.biBitCount << endl;
int max = 4 * bmptag.biWidth*bmptag.biHeight;
unsigned char * bmpdot = new unsigned char[max];
tree->root = new HuffmanTreeNode;
while (1) // ,
{
HuffmanTreeNode *p=tree->root;
unsigned char color;
int length=0;
infile.read((char *)&color, 1);
printf(" %d ", color);
infile.read((char *)&length, 1);
cout << " " << length<> (8 - m)&0x00000001;
count++;
if (lead == 0)
{
cout << "0";
if (p->leftChild == 0)
{
p->leftChild = new HuffmanTreeNode;
}
p = p->leftChild;
}
else
{
cout << "1";
if (p->rightChild == 0)
{
p->rightChild = new HuffmanTreeNode;
}
p = p->rightChild;
}
if (count == length)
{
count = 0;
p->data = color;
goto XX;
}
}
}
XX: cout << endl;
}
unsigned int Buffer;
int bufferLen = 8;
infile.read((char *)&Buffer, 1);
HuffmanTreeNode *q=tree->root;
for (int i = 0; i < max; i++)
{
q = tree->root;
while (1)
{
int lead=Buffer >> (bufferLen-1) & 0x00000001;
bufferLen --;
if (bufferLen == 0)
{
infile.read((char *)&Buffer, 1);
bufferLen += 8;
}
if (lead == 1)
{
q = q->rightChild;
}
else
{
q = q->leftChild;
}
if (q->leftChild == NULL||q->rightChild == NULL)
{
outfile.write((char *)&(q->data), 1);
break;
}
}
}
}
HCode.cpp
#include "HCode.h"
#include
using namespace std;
HCode::HCode()
{
codeLength = new int[256];
codeContent = new string[256];
colorWeight = new int[256];
for (int i = 0; i < 256; i++)
{
codeLength[i]=0;
colorWeight[i]=0;
}
}
HCode::~HCode()
{
}
void HCode::addColor(unsigned char color)
{
colorWeight[color]++;
}
void HCode::addBit(bool in, unsigned char color)
{
if (in == 0)
{
codeContent[color] += '0';
}
else
{
codeContent[color] += '1';
}
codeLength[color]++;
//cout << " " << (int)color << " 1, "<
HuffmanTree.cpp
#include "HuffmanTree.h"
HuffmanTree::~HuffmanTree()
{
}
void HuffmanTree::HuffmanTreeCreate()
{
MinHeap heap(256);
HuffmanTreeNode *parent, *firstChild, *secondChild;
HuffmanTreeNode *newNode;
for (int i = 0; i < 256; ++i)
{
if (hcode.colorWeight[i] != 0)
{
size++;
newNode = new HuffmanTreeNode;
newNode->weight = hcode.colorWeight[i];
newNode->data = i;
heap.insert(newNode);
}
}
cout << "size==" << size << "maxln=" << heap.currentSize << endl;
for (int i = 0; i < size-1 ; ++i)
{
parent = new HuffmanTreeNode;
firstChild = heap.removeMin();
secondChild = heap.removeMin();
parent->weight = firstChild->weight + secondChild->weight;
parent->leftChild = firstChild;
parent->rightChild = secondChild;
heap.insert(parent);
root = parent;
}
root = heap.heapArray[0];
string ll;
getCodeRecusion(root, ll);
}
HuffmanTree::HuffmanTree()
{
size = 0;
}
void HuffmanTree::getCodeRecusion(HuffmanTreeNode * root, string code)
{
if (root->leftChild == NULL&&root->rightChild == NULL)
{ for (int i = 0; i < code.length(); i++)
{
if (code[i] == '0')
hcode.addBit(0, root->data);
else
hcode.addBit(1, root->data);
}
}
else
{
getCodeRecusion(root->leftChild, code + '0');
getCodeRecusion(root->rightChild, code + '1');
}
}
void HuffmanTree::getCodeMa()
{
for (int i = 0; i < 256; i++)//
{
if (hcode.codeLength[i] != 0)
{
int lenth = hcode.codeLength[i];
unsigned int temp = 0;//
int count = 0;
int zijiecount = 0;
for (int j = 0; j 0)
{
int parent = (child - 1) / 2;
if (heapArray[child]->weight <= heapArray[parent]->weight)
{
HuffmanTreeNode *temp = heapArray[parent];
heapArray[parent] = heapArray[child];
heapArray[child] = temp;
child = parent;
}
else break;
}
}
HuffmanTreeNode * MinHeap::removeMin()
{
if (currentSize == 1)
{
currentSize--;
return heapArray[0];;
}
HuffmanTreeNode * temp = heapArray[0];
heapArray[0] = heapArray[currentSize - 1];
currentSize--;
shiftDown(0);
return temp;
}
void MinHeap::shiftDown(int left)
{
int i = left;
int j = 2 * i + 1;
HuffmanTreeNode *temp = heapArray[i];
while (j < currentSize)
{
if ((j < currentSize - 1) && heapArray[j]->weight > heapArray[j + 1]->weight)
j++;
if (temp->weight > heapArray[j]->weight)
{
heapArray[i] = heapArray[j];
i = j;
j = 2 * j + 1;
}
else break;
}
heapArray[i] = temp;
}
HuffmanTreeNode::HuffmanTreeNode()
{
leftChild = rightChild = NULL;
weight = 0;
}