ピクチャ圧縮プロセスシミュレーション:dct離散コサイン変換+量子化+ハフマン符号化+LZ符号化+上記逆変換および復号c++

49207 ワード

「情報論」のカリキュラム設計は、タイトルの内容を完成させることを要求している.
//参考まで
matlabを使用するか、より便利で簡潔ですが、プロセスを一度考えたい場合は、次のコードを参照して、コンパイルにはopencvをインストールする必要があります.
コードには最適化の余地があり、ベクトルでコード内のポインタの多い問題を解決することができます.マルチスレッドで運転速度を最適化することもでき、LZ符号化クラスは独立性を増やし、ホフマン符号化との関連を取り消し、試運転時に小さな画像を使用してmain関数を通過することを提案することができる.
Webサイトおよび一部のコードソースを参照してください.
dct変換及び逆変換のコード及び量子化部の参照コード
https://blog.csdn.net/u014518566/article/details/46432621?ops_request_misc=&request_id=&biz_id=102&utm_term=dct%E7%A6%BB%E6%95%A3%E4%BD%99%E5%BC%A6%E5%8F%98%E6%8D%A2%E9%87%8F%E5%8C%96c++&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-46432621
量子化マトリクスのソース:
http://blog.sina.com.cn/s/blog_8bb885610102vizk.html
プログラム出力ファイルコメント:
image_outiフォルダには、量子化マトリクスiを使用して圧縮符号化された出力ファイルが含まれています.
decode.jpgは解凍後の画像です.
hdecode.jpgは,解凍後のピクチャの階調統計ヒストグラムであり,横軸は0から255の階調値,縦軸は横軸対応階調値の解凍後の統計回数を表し,正規化処理を行った.
hdelta1.jpgは1種類の誤差ヒストグラムであり,横軸は−255から255までの階調値差,縦軸は対応差の周波数分布を表し,正規化処理を行った.
hdelta2.jpgは2種類の誤差ヒストグラムであり、横軸は原図が0から255の階調値を表し、縦軸は原図が対応する階調値の相対解凍後のピクチャの階調値周波数の変化を表し、同様に正規化処理を行ったが、正負が存在するため、x軸はピクチャ中の境界線であり、y軸はピクチャ左枠である.
hfmlist.txtはホフマン符号化によって生成された辞書である.
hfmout.txtはホフマン符号化の出力シーケンスである.
ho.jpgは初期化後のピクチャの階調統計ヒストグラムであり、横軸は0から255の階調値、縦軸は横軸対応階調値の元のピクチャにおける統計回数を表し、正規化処理を行った.
lzlist.txtは、LZ符号化におけるソースシンボルの符号化辞書である.
lzout.txtは、LZ符号化の出力シーケンスである.
o.jpgは初期化後のピクチャ(元のピクチャは3チャネル図の長さと幅の任意のピクチャであり、初期化後は単一チャネル階調図に変更され、長さと幅はいずれも8または16の倍数のピクチャ)である.
sch.jpgは圧縮量子化されたピクチャであり、値が負の画素がデータオーバーフローにより正の値に変更される.
sch.txtは、量子化後のピクチャの各マトリクスの画素値データを圧縮し、負の値を保持する.
1.jpgはプログラム実行時に入力したピクチャで、3チャネルピクチャでなければならない.そうしないと、エラーが発生し、その他の任意である.
コンソール出力txtは、プログラム実行終了後にコンソールから出力される文字であり、各ステップ実行時間、ソースシンボルデータ、符号化データ、ピクチャデータなどの情報が含まれている.
コンパイルにはopencvをインストールする必要があります.
 
//QQ:2048728358
//2020/05/10

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
using namespace cv;

#define NUM 8
#define PI 3.1415926
//      
class HFMP;
//      
class HFMCODE;
//      
class HFMDECODE;
//LZ    
class LZP;
//LZ   //           
class LZCODE;
//LZ   
class LZDECODE;
//JPEG    


//N=8    

int F8[14][8][8] = { 
//100
{
    {1,1,1,1,1,1,1,1},
    {1,1,1,1,1,1,1,1},
    {1,1,1,1,1,1,1,1},
    {1,1,1,1,1,1,1,1},
    {1,1,1,1,1,1,1,1},
    {1,1,1,1,1,1,1,1},
    {1,1,1,1,1,1,1,1},
    {1,1,1,1,1,1,1,1}
},
//98
{
    {1,1,1,1,1,2,2,2},
    {1,1,1,1,1,2,2,2},
    {1,1,1,1,2,2,3,2},
    {1,1,1,1,2,3,3,2},
    {1,1,1,2,3,4,4,3},
    {1,1,2,3,3,4,5,4},
    {2,3,3,3,4,5,5,4},
    {3,4,4,4,4,4,4,4}
},
//96
{
    {1,1,1,1,2,3,4,5},
    {1,1,1,2,3,5,6,4},
    {1,1,1,2,3,5,6,4},
    {1,1,2,2,4,7,6,5},
    {1,2,3,4,5,9,8,6},
    {2,3,4,5,6,8,9,7},
    {4,5,6,7,8,10,10,8},
    {6,7,8,8,9,8,8,8}
},
//94
{
    {2,1,1,2,3,5,6,7},
    {1,1,2,2,3,7,7,7},
    {2,2,2,3,5,7,8,7},
    {2,2,3,3,6,10,10,7},
    {2,3,4,7,8,13,12,9},
    {3,4,7,8,10,12,14,11},
    {6,8,9,10,12,15,14,12},
    {9,11,11,12,13,12,12,12}
},
//92
{
    {3,2,2,3,4,6,8,10},
    {2,2,2,3,4,9,10,9},
    {2,2,3,4,6,9,11,9},
    {2,3,4,5,8,14,13,10},
    {3,4,6,9,11,17,16,12},
    {4,6,9,10,13,17,18,15},
    {8,10,12,14,16,19,19,16},
    {12,15,15,16,18,16,16,16}
},
//90
{
    {3,2,2,3,5,8,10,12},
    {2,2,3,4,5,12,12,11},
    {3,3,3,5,8,11,14,11},
    {3,3,4,6,10,17,16,12},
    {4,4,7,11,14,22,21,15},
    {5,7,11,13,16,21,23,18},
    {10,13,16,17,21,24,24,20},
    {14,18,19,20,22,20,21,20}
},
//88
{
    {4,3,2,4,6,10,12,15},
    {3,3,3,5,6,14,14,13},
    {3,3,4,6,10,14,17,13},
    {3,4,5,7,12,21,19,15},
    {4,5,9,13,16,26,25,18},
    {6,8,13,15,19,25,27,22},
    {12,15,19,21,25,29,26,24},
    {17,22,23,24,27,24,25,24}
},
//86
{
    {4,3,3,4,7,11,14,17},
    {3,3,4,5,7,16,17,15},
    {4,4,4,7,11,16,19,16},
    {4,5,6,8,14,24,22,17},
    {5,6,10,16,19,31,29,22},
    {7,10,15,18,23,29,32,26},
    {14,18,22,24,29,34,34,28},
    {20,26,27,27,31,28,29,28}
},
//84
{
    {5,4,3,5,8,13,16,20},
    {4,4,4,6,8,19,19,18},
    {4,4,5,8,13,18,22,18},
    {4,5,7,9,16,28,26,20},
    {6,7,12,18,22,35,33,25},
    {8,11,18,20,26,33,36,29},
    {16,20,25,28,33,39,38,32},
    {23,29,30,31,36,32,33,32}
},
//82
{
    {6,4,4,6,9,14,18,12},
    {4,4,5,7,9,21,22,20},
    {5,5,6,9,14,21,25,20},
    {5,6,8,10,18,31,29,22},
    {6,8,13,20,24,39,37,28},
    {9,13,20,23,29,37,41,33},
    {18,23,28,31,37,44,43,36},
    {26,33,34,35,40,36,37,36}
},
//80
{
    {6, 4, 4, 6, 10, 16, 20, 24},
    { 5,5,6,8,10,23,24,22 },
    { 6,5,6,10,16,23,28,22 },
    { 6,7,9,12,20,35,32,25 },
    { 7,9,15,22,27,44,41,31 },
    { 10,14,22,26,32,42,45,37 },
    { 20,26,31,35,41,48,48,40 },
    { 29,37,38,39,45,40,41,40 }
},
//    
{
    {16,11,10,16,24,40,51,61},
    {12,12,14,19,26,58,60,55},
    {14,13,16,24,40,57,69,56},
    {14,17,22,29,51,87,80,62},
    {18,22,37,56,68,109,103,77},
    {24,35,55,64,81,104,113,92},
    {49,64,78,87,103,121,120,101},
    {72,92,95,98,112,100,103,99}
},
//       ,6
{
{1,1,1,512,512,512,512,512},
{1,1,512,512,512,512,512,512},
{1,512,512,512,512,512,512,512},
{512,512,512,512,512,512,512,512},
{512,512,512,512,512,512,512,512},
{512,512,512,512,512,512,512,512},
{512,512,512,512,512,512,512,512},
{512,512,512,512,512,512,512,512}
},
//       ,10
{
    { 1,1,1,1,512, 512, 512, 512},
    { 1,1,1,512,512,512,512,512 },
    { 1,1,512,512,512,512,512,512 },
    { 1,512,512,512,512,512,512,512 },
    { 512,512,512,512,512,512,512,512 },
    { 512,512,512,512,512,512,512,512 },
    { 512,512,512,512,512,512,512,512 },
    { 512,512,512,512,512,512,512,512 }
}
};



//   8*8    
int input[8][8] = {

          {89, 101, 114, 125, 126, 115, 105, 96},

          {97, 115, 131, 147, 149, 135, 123, 113},

          {114, 134, 159, 178, 175, 164, 149, 137},

          {121, 143, 177, 196, 201, 189, 165, 150},

          {119, 141, 175, 201, 207, 186, 162, 144},

          {107, 130, 165, 189, 192, 171, 144, 125},

          {97, 119, 149, 171, 172, 145, 117, 96},

          {88, 107, 136, 156, 155, 129, 97, 75}

};//       


//        
int Initimage(Mat& imagein);
//DCT  
void DCT(int data[NUM][NUM]);
//DCT   
void IDCT(int data[NUM][NUM]);
//    
int around(double a);
//  
void DCT(int data[NUM][NUM]);
//DCT   
void IDCT(int data[NUM][NUM]);
//  
int SCH(int data[NUM][NUM], int k);
//   
int ISCH(int data[NUM][NUM], int k);
//Z   
int Zscan(int datain[NUM][NUM], int dataout[NUM * NUM]);
// Z   
int IZscan(int datain[NUM * NUM], int dataout[NUM][NUM]);
//  
int fhasaki(Mat image, Mat& imageout1, int*& image1line, int**& image1int, int sch);
//   
int fdehasaki(int length, int w, int h, int* imageline, Mat& imageout2, int sch);
//int      
string inttoox(int x, int width);
//      int
int oxtoint(string s);
//         
int gethistogram(string dst, Mat image);
int gethistogram(string dst, Mat image1, Mat image2);
int gethistogram(Mat image1, Mat image2, string dst);

class HFMP {
public:
    int num;//    (  )
    int count;//    
    double p;//  
    bool tag;//  ,   true,               
    string s;//    
    HFMP* b[2];
    HFMP() :num(0), count(0), p(0.0), tag(true) {
        s = "";
        b[0] = NULL;
        b[1] = NULL;
    }
    ~HFMP() {
        if (b[0])
            delete b[0];
        if (b[1])
            delete b[1];
        if (this == NULL)
            return;
    }
};

class HFMCODE {
    friend LZCODE;
    HFMP* root;//    
    HFMP* code;//    
    HFMP* temp;//     
    int count;//       
    int pnum;//    
    int codelength;//      
    double H;
    void init() {///   
        delete code;
        delete root;
        delete temp;
        temp = NULL;
        code = NULL;
        root = new HFMP;//
        root->num = 0;
        pnum = 1;
        count = 0;
    }
    //  
    void fcount(int* data)
    {
        cout << "      " << endl;
        cout << "        :" << count << endl;
        int i = 0;
        for (i = 0; i < count; i++)
        {
            HFMP* q = findp(data[i], root);
            if (q)
                q->count++;
            else
            {
                newp(data[i], root);
                pnum++;
            }
        }
    }
    HFMP* findp(int data, HFMP* p) {
        if (p->num == data && p->tag)
            return p;
        if (p->b[1] != NULL)
        {
            HFMP* q = findp(data, p->b[1]);
            if (q != NULL)
                return q;
        }
        if (p->b[0] != NULL)
            return findp(data, p->b[0]);
        return NULL;
    }
    void newp(int data, HFMP* p)
    {
        if (data < p->num && p->b[0])
            newp(data, p->b[0]);
        if (data > p->num && p->b[1])
            newp(data, p->b[1]);
        if (data < p->num && p->b[0] == NULL)
        {
            p->b[0] = new HFMP;
            p->b[0]->num = data;
            p->b[0]->count++;
        }
        if (data > p->num && p->b[1] == NULL)
        {
            p->b[1] = new HFMP;
            p->b[1]->num = data;
            p->b[1]->count++;
        }
        if (p->num == data)
            cout << "           !" << endl;
    }

    //      
    void sort2(HFMP* p)//        ,       //   temp;
    {
        HFMP* q = NULL;
        HFMP* qq = NULL;
        if (temp == NULL)//     
        {

            q = new HFMP;
            q->num = p->num;
            q->count = p->count;
            temp = q;
            return;
        }
        if (temp->count <= p->count)//          p
        {
            q = new HFMP;
            q->num = p->num;
            q->count = p->count;
            q->b[0] = temp;
            /*temp->b[1] = q;*/
            temp = q;
            return;
        }
        if (temp->b[0] == NULL)//             p
        {
            q = new HFMP;
            q->num = p->num;
            q->count = p->count;
            temp->b[0] = q;
            /* q->b[1] = temp;*/
            return;
        }
        q = temp;
        while (q->b[0]) {//      p   
            if (q->b[0]->count > p->count)
            {
                q = q->b[0];
                continue;
            }
            qq = new HFMP;
            qq->num = p->num;
            qq->count = p->count;
            qq->b[0] = q->b[0];
            /* qq->b[1] = q;*/
            q->b[0] = qq;
            return;
        }
        qq = new HFMP;//         p
        qq->num = p->num;
        qq->count = p->count;
        /*qq->b[1] = q;*/
        q->b[0] = qq;
        return;
    }
    void sort1(HFMP* p)
    {
        sort2(p);
        if (p->b[0])
            sort1(p->b[0]);
        if (p->b[1])
            sort1(p->b[1]);
    }
    void sort()//                root;
    {
        cout << "      " << endl;
        sort1(root);
        delete root;
        root = temp;
        temp = NULL;
    }

    //      
    void plantsort(HFMP* p)//        temp;
    {
        HFMP* q = p;
        if (temp == NULL)//     
        {
            temp = p;
            return;
        }
        if (temp->count <= p->count)//          p
        {
            p->b[0] = temp;
            temp = p;
            return;
        }
        if (temp->b[0] == NULL)//             p
        {
            temp->b[0] = p;
            /* q->b[1] = temp;*/
            return;
        }
        q = temp;
        while (q->b[0]) {//      p   
            if (q->b[0]->count > p->count)
            {
                q = q->b[0];
                continue;
            }
            p->b[0] = q->b[0];
            /* qq->b[1] = q;*/
            q->b[0] = p;
            return;
        }
        q->b[0] = p;
        return;
    }
    void plant1(HFMP* p, HFMP** pp, int l) {
        if (p->tag)
            return;
        plant2(p, pp, l);
        if (p->b[0])
            plant1(p->b[0], pp, l);
        if (p->b[1])
            plant1(p->b[1], pp, l);
    }
    void plant2(HFMP* p, HFMP** pp, int l)
    {
        int i;
        for (i = 0; i < l; i++)
        {
            if ((p->count == pp[i]->count) && pp[i]->b[0] && pp[i]->b[1])
            {
                p->b[0] = pp[i]->b[0];
                pp[i]->b[0] = NULL;
                p->b[1] = pp[i]->b[1];
                pp[i]->b[1] = NULL;
                return;
            }
        }
        cout << "     plant2()    !" << endl;
    }
    bool plant() {
        cout << "        " << endl;
        HFMP** proot = NULL;
        temp = root;
        root = NULL;
        HFMP* q;
        int i;
        for (i = 0; temp->b[0]->b[0]->b[0];)//     3 
        {
            HFMP* p = new HFMP;
            HFMP* pp = new HFMP;
            //    
            q = temp;
            while (q->b[0]->b[0])
                q = q->b[0];
            p->b[0] = q->b[0];
            q->b[0] = NULL;
            //     
            q = temp;
            while (q->b[0]->b[0])
                q = q->b[0];
            p->b[1] = q->b[0];
            q->b[0] = NULL;

            p->count = p->b[0]->count + p->b[1]->count;
            pp->count = p->count;
            p->tag = false;
            pp->tag = false;
            if (proot == NULL)
                proot = (HFMP**)malloc(sizeof(HFMP*));
            else
                proot = (HFMP**)realloc(proot, (i + 1) * sizeof(HFMP*));
            proot[i] = p;
            i++;
            plantsort(pp);
            p = NULL;
            pp = NULL;
        }
        HFMP* p = new HFMP;
        HFMP* pp = new HFMP;
        p->b[0] = temp->b[0]->b[0];
        temp->b[0]->b[0] = NULL;
        p->b[1] = temp->b[0];
        temp->b[0] = NULL;
        p->count = p->b[0]->count + p->b[1]->count;
        pp->count = p->count;
        p->tag = false;
        pp->tag = false;
        proot = (HFMP**)realloc(proot, (i + 1) * sizeof(HFMP*));
        proot[i] = p;
        i++;
        plantsort(pp);
        pp = NULL;
        p = new HFMP;
        pp = new HFMP;
        p->b[0] = temp->b[0];
        temp->b[0] = NULL;
        p->b[1] = temp;
        temp = NULL;
        p->count = p->b[0]->count + p->b[1]->count;
        pp->count = p->count;
        if (p->count != count)
        {
            delete p;
            for (; i >= 0; i--)
            {
                delete proot[i];
                free(proot[i]);
            }
            return false;
        }
        p->tag = false;
        pp->tag = false;
        temp = pp;
        pp = NULL;
        proot = (HFMP**)realloc(proot, (i + 1) * sizeof(HFMP*));
        proot[i] = p;
        i++;
        p = NULL;
        //  ,            ,           


        plant1(temp, proot, i);
        code = temp;
        temp = NULL;
        //  ,        
        //      
        for (; i > 0; i--)
        {
            delete proot[i - 1];
            proot[i - 1] = NULL;
        }
        free(proot);
        return true;
    }


    //      ,      ,          
    void calculatep(int* data) {
        fcount(data);
        sort();
        plant();
        cout << "        " << endl;
        calculatep1(code);
    }
    void calculatep1(HFMP* p) {
        p->p = ((double)p->count / (double)count);
        if (p->tag)
        {
            H -= (log(p->p) / log(2)) * p->p;
        }
        if (p->b[0])
            calculatep1(p->b[0]);
        if (p->b[1])
            calculatep1(p->b[1]);
    }
    void fcode(int l, int* data, fstream* tlist, fstream* tout) {
        count = l;
        calculatep(data);
        fcode1(code);
        cout << "          " << endl;
        fcode2(code, tlist);
        cout << "           " << endl;
        fout(data, tout);
    }
    void fcode1(HFMP* p) {//     
        if (p->b[0])
        {
            p->b[0]->s = p->s + "0";
            fcode1(p->b[0]);
        }
        if (p->b[1])
        {
            p->b[1]->s = p->s + "1";
            fcode1(p->b[1]);
        }
    }
    void fcode2(HFMP* p, fstream* t)//        
    {
        if (p->b[1])
            fcode2(p->b[1], t);
        if (p->tag)
        {
            *t <num <p << "\t\t" << p->s <<  endl;
        }
        if (p->b[0])
            fcode2(p->b[0], t);
    }
    void fout(int* data, fstream* t)
    {
        HFMP* p;
        for (int i = 0; i < count; i++)
        {
            p = findp(data[i], code);
            codelength = codelength + (int)p->s.length();
            *t << p->s;
        }
        cout << "            :" << codelength << endl;
    }

    //           
    void copyhfmtreeP(HFMP* p, HFMP* q) {
        p->num = q->num;
        p->count = q->count;
        p->p = q->p;
        p->tag = q->tag;
        p->s = q->s;
        p->b[0] = NULL;
        p->b[1] = NULL;
    }
    void copyhfmtree(HFMP* frooty, HFMP* frootx) {
        for (int i = 0; i < 2; i++)
        {
            if (frooty->b[i])
                delete frooty->b[i];
            frooty->b[i] = new HFMP;
            if (frootx->b[i])
            {
                copyhfmtreeP(frooty->b[i], frootx->b[i]);
                copyhfmtree(frooty->b[i], frootx->b[i]);
            }
        }
    }
public:
    int getpnum() {
        return pnum;
    }
    HFMP* gethfmtree() {
        HFMP* p = new HFMP;
        copyhfmtreeP(p, code);
        copyhfmtree(p, code);
        return p;
    }
    double getH() { return H; }
    HFMCODE(int l, int* data, fstream* tlist, fstream* tout) :H(0.0), count(0), codelength(0)//      0
    {
        temp = NULL;
        code = NULL;
        root = new HFMP;
        root->num = 0;
        pnum = 1;
        fcode(l, data, tlist, tout);
        cout << "           :" << pnum << endl;
        cout << "           :" << count << endl;
        cout << "         :" << (double)codelength / count << endl;
        cout << "     :" << H << endl;
        cout << "         :" << H / (double)codelength * count << endl;
        cout << "          :" << (double)count * 8 / codelength << endl;
    }
    ~HFMCODE() {
        delete temp;
        delete code;
        delete root;
    }
};

class HFMDECODE {

    HFMP* code;//    
    int count;//       
    int pnum;//    
    int* decode;
public:
    HFMDECODE(HFMP* p, int fpnum, fstream* tin) :count(0), pnum(fpnum), decode(NULL)
    {
        cout << "           :" << pnum << endl;
        code = p;
        p = NULL;
        char ch;
        string s = "";
        HFMP* q = code;
        int i = 0;
        while (1)
        {
            *tin >> ch;
            s = s + ch;
            if (ch == '1')
                q = q->b[1];
            else
                q = q->b[0];
            if (tin->eof())
                break;
            if (q->tag)//
            {
                decode = (int*)realloc(decode, (count + 1) * sizeof(int));
                if (q->s == s)
                    decode[count] = q->num;
                else
                    cout << "hfm decode error!" << endl;
                count++;
                s = "";
                q = code;
            }
        }
        cout << "             :" << count << endl;
    }
    ~HFMDECODE() {
        if (code)
            delete code;
        free(decode);
    }
};

class LZP {//                
public:
    int num;//    
    int lastposit;//     
    int posit;//    
    int pnum;//    
    LZP** p;//    

    LZP() :num(0), posit(0), pnum(0), p(NULL), lastposit(0) {};
    ~LZP() {
        for (; pnum > 0; pnum--)
        {
            if (p[pnum - 1])
                delete p[pnum - 1];
        }
        if (p)
            free(p);
    }
};

class LZCODE
{
    LZP* root;//lz     
    int* list;//     ,        
    int xnum;//      
    int** file;//      ,        ,0      ,1        //     
    int ynum;//  
    double H;
    //             //      ,    
    LZP* findp1(int* numlist, int length) {

        if (numlist == NULL)
            return NULL;
        if (length < 1)
            return NULL;
        LZP* q = root;
        for (int i = 0; i < length; i++)
        {
            q = findp2(q, numlist[i]);
            if (q == NULL)
                return NULL;
        }
        return q;
    }

    //   LZ             ,          //     ,     

    LZP* findp2(LZP* last, int num) {
        int i = 0;
        for (i = 0; i < last->pnum; i++)
        {
            if (last->p[i])
                if (last->p[i]->num == num)
                    return last->p[i];
        }
        return NULL;
    }

    //            num,     lastposit,     posit   
    void newp(LZP* p, int num, int lastposit, int posit) {
        p->pnum++;
        p->p = (LZP**)realloc(p->p, p->pnum * sizeof(LZP*));
        p->p[p->pnum - 1] = new LZP;
        p->p[p->pnum - 1]->num = num;
        p->p[p->pnum - 1]->posit = posit;
        p->p[p->pnum - 1]->lastposit = lastposit;
    }

    //          LZ        //       ,          
    int record(HFMP* p, int i) {
        if (p->tag)
        {
            list = (int*)realloc(list, (i + 1) * sizeof(int));
            list[i] = p->num;
            i++;
        }
        if (p->b[0])
            i = record(p->b[0], i);
        if (p->b[1])
            i = record(p->b[1], i);
        return i;
    }

    int findnumcode(int num)//        
    {
        for (int i = 0; i < xnum; i++)
        {
            if (list[i] == num)
                return i;
        }
        cout << "LZ        " << endl;
        return 0;
    }


    //LZ  
    void fcode(int* line, int length) {
        LZP* q = NULL;
        LZP* p = NULL;
        int i;
        q = root;
        cout << "LZ        :" << length << endl;
        for (i = 0; i < length; i++)//           
        {
            p = findp2(q, line[i]);
            if (i == length - 1 && p)
            {
                file = (int**)realloc(file, (ynum + 1) * sizeof(int*));
                file[ynum] = (int*)malloc(2 * sizeof(int));
                file[ynum][0] = q->posit;
                file[ynum][1] = findnumcode(p->num);
                ynum++;
                return;
            }
            else if (p == NULL)
            {
                newp(q, line[i], q->posit, ynum + 1);
                file = (int**)realloc(file, (ynum + 1) * sizeof(int*));
                file[ynum] = (int*)malloc(2 * sizeof(int));
                p = findp2(q, line[i]);
                if (!p)
                {
                    cout << "lz code error!" << endl;
                    return;
                }
                file[ynum][0] = q->posit;
                file[ynum][1] = findnumcode(p->num);
                ynum++;
                q = root;
                p = NULL;
            }
            else
                q = p;
        }
    }
    //             
    void fout(fstream* flist, fstream* ffile)
    {
        cout << "LZ        :" << xnum << endl;
        cout << "LZ    (   0 ):" << ynum << endl;
        int xl = (int)(log(xnum) / log(2)) + 1;
        int yl = (int)(log(ynum) / log(2)) + 1;
        int i;
        for (i = 0; i < xnum; i++)
        {
            *flist << inttoox(i, xl) << " " << list[i] << endl;
        }
        for (i = 0; i < ynum; i++)
        {
            *ffile << inttoox(file[i][0], yl) << inttoox(file[i][1], xl);
        }
        cout << "LZ        :" << (xl + yl) * ynum << endl;
    }
    //       
public:
    LZCODE(HFMCODE& T, int* line, int length, fstream* flist, fstream* ffile) :xnum(0), list(NULL), file(NULL), ynum(0)
    {
        //        
        xnum = record(T.code, xnum);
        H = T.getH();
        if (xnum != T.pnum)
        {
            cout << xnum << " " << T.pnum << endl;
            cout << "LZ code error!" << endl;
        }
        root = new LZP;
        fcode(line, length);
        fout(flist, ffile);
        int xl = (int)(log(xnum) / log(2)) + 1;
        int yl = (int)(log(ynum) / log(2)) + 1;
        cout << "LZ      :" << (double)ynum * (xl + yl) / (double)length << endl;
        cout << "LZ      :" << H / (double)ynum / (xl + yl) * (double)length << endl;
        cout << "LZ       :" << (double)T.count*8 / ynum / (xl + yl) << endl;
    }
    int* getlist()//       
    {
        int* p = (int*)malloc(xnum * sizeof(int));
        for (int i = 0; i < xnum; i++)
        {
            p[i] = list[i];
        }
        return p;
    }
    int getxnum() { return xnum; }
    int getynum() { return ynum; }
    ~LZCODE() {
        free(list);
        delete root;
        for (; ynum > 0; ynum--)
            free(file[ynum - 1]);
        free(file);
    }
};

class LZDECODE {
    int** root;//LZ  ,       ,    、    
    int ynum;//LZ    
    int* list;//     //     
    int xnum;//      
    int* code;//  
    int znum;//      
    //            num,     lastposit,     posit   

public:
    //      ,       ,      ,    
    LZDECODE(int* flist, int fxnum, fstream* ffile, int fynum) :root(NULL), list(NULL), xnum(0), ynum(0), code(NULL), znum(0) {
        list = (int*)malloc(fxnum * sizeof(int));
        while (xnum < fxnum)
        {
            list[xnum] = flist[xnum];
            xnum++;
        }
        int xl = (int)(log(fxnum) / log(2)) + 1;
        int yl = (int)(log(fynum) / log(2)) + 1;
        cout << "LZ        :" << xnum << endl;
        char ch;
        string ss1 = "";
        string ss2 = "";
        root = (int**)malloc(sizeof(int*));//  0 
        ynum++;
        while (1)
        {
            for (int i = 0; i < yl; i++)
            {
                ch = ffile->get();
                ss1 = ss1 + ch;
            }
            if (ffile->eof())
                break;
            for (int i = 0; i < xl; i++)
            {
                ch = ffile->get();
                ss2 = ss2 + ch;
            }
            root = (int**)realloc(root, (ynum + 1) * sizeof(int*));
            root[ynum] = (int*)malloc(2 * sizeof(int));
            root[ynum][0] = oxtoint(ss1);//  
            root[ynum][1] = oxtoint(ss2);//      

            ynum++;
            ss1 = "";
            ss2 = "";
        }
        cout << "LZ      (   0 ):" << ynum << endl;
        int* p = NULL;
        int i, j;
        for (i = 1, j = 0; i < ynum; i++)
        {
            j = 0;
            p = (int*)malloc(sizeof(int));
            p[0] = list[root[i][1]];
            int tempposit = root[i][0];
            j++;
            while (tempposit != 0)
            {
                p = (int*)realloc(p, (j + 1) * sizeof(int));
                p[j] = list[root[tempposit][1]];
                tempposit = root[tempposit][0];
                j++;
            }
            code = (int*)realloc(code, (znum + j) * sizeof(int));
            for (int k = 0; k < j; k++)
            {
                code[znum] = p[j - k - 1];
                znum++;
            }
            free(p);
        }
        cout << "LZ        :" << znum << endl;
    };
    ~LZDECODE()
    {
        free(list);
        free(code);
        for (int i = 1; i < ynum; i++)
        {
            free(root[i]);
        }
        free(root);
    }
};

int main(void)
{
    int sch;
    for (sch = 0; sch < 14; sch++)
    {
        cout << "   " << sch << endl;
        clock_t startTime, endTime, time1, time2, time3, time4, time5, time6, time7, time8;
        startTime = clock();//    
        //       
        string ds = to_string(sch);
        char* buffer;//    
        string root;//    
        string src = "\\image_o\\1.jpg";//      
        string dstout = "\\image_out" + ds + "\\";//     
        cout << "        " << endl;
        //      
        if ((buffer = _getcwd(NULL, 0)) == NULL)
        {
            perror("_getcwderror");
            return -1;
        }  //         
        else
        {
            root = buffer;
            free(buffer);
            buffer = NULL;
            src = root + src;
            dstout = root + dstout;
        }
        cout << "        " << endl;
        cout << "      " << endl;
        //      
        Mat image1 = imread(src, IMREAD_UNCHANGED);//    
        if (image1.empty())//      
        {
            cout << "      !" << endl;
            CreateDirectory(L"image_o", NULL);
            cout << "      image_o       1.jpg   " << endl;
            return -1;
        }
        cout << "      " << endl;
        cout << "       " << endl;
        if (Initimage(image1) == 0)//     
        {
            cout << "    !" << endl;
            return -1;
        }
        cout << "       ,        image_out"+ds << endl;
        //       
        CreateDirectory(L"image_out" + (CString)ds.c_str(), NULL);

        //         
        imwrite(dstout + "o.jpg", image1);
        //  ,       
        ofstream out;
        string txtname = "sch.txt";
        out.open(dstout + txtname, ios::out);
        if (!out.is_open())
        {
            cout << "txt open fail!";
        }
        string imageoutdst2 = dstout + "sch.jpg";//   
        string imageoutdst3 = dstout + "decode.jpg";//      
        Mat image2, image3;
        int* imageline = NULL;
        int** imageint = NULL;


        cout << "    ,   " << endl;
        //      
        time1 = clock();
        if (fhasaki(image1, image2, imageline, imageint, sch) != 1)
        {
            cout << "      !" << endl;
            return -1;
        }
        cout << "      ,      " << endl;
        imwrite(imageoutdst2, image2);

        time2 = clock();
        cout << "    :" << (double)(time2 - time1) / CLOCKS_PER_SEC << "s" << endl;
        int i, k;
        for (i = 0, k = 0; i < image1.rows * image1.cols; i++, k++)
        {
            if (k >= NUM * NUM)
            {
                k = 0;
                out << endl;
            }
            /*out << imageline[i] << " ";*/
            out << setw(5) << imageline[i];
        }




        //     
        cout << "         " << endl;
        time3 = clock();
        fstream thfmout, thfmlist;
        thfmlist.open(dstout + "hfmlist.txt", ios::out);
        thfmout.open(dstout + "hfmout.txt", ios::out);
        HFMCODE hfm(image1.rows * image1.cols, imageline, &thfmlist, &thfmout);
        thfmout.close();
        thfmout.open(dstout + "hfmout.txt");
        time4 = clock();
        cout << "       :" << (double)(time4 - time3) / CLOCKS_PER_SEC << "s" << endl;

        cout << "         " << endl;

        HFMP* hfmtree = hfm.gethfmtree();
        HFMDECODE dhfm(hfmtree, hfm.getpnum(), &thfmout);
        hfmtree = NULL;//       

        time5 = clock();
        cout << "       :" << (double)(time5 - time4) / CLOCKS_PER_SEC << "s" << endl;



        //LZ  
        cout << "    LZ  " << endl;
        fstream tlzlist, tlzout;
        tlzlist.open(dstout + "lzlist.txt", ios::out);
        tlzout.open(dstout + "lzout.txt", ios::out);
        LZCODE lz(hfm, imageline, image1.rows * image1.cols, &tlzlist, &tlzout);
        tlzout.close();
        time6 = clock();
        cout << "LZ    :" << (double)(time6 - time5) / CLOCKS_PER_SEC << "s" << endl;
        tlzout.open(dstout + "lzout.txt");
        cout << "    LZ  " << endl;
        int* lzlist = lz.getlist();
        LZDECODE dlz(lzlist, lz.getxnum(), &tlzout, lz.getynum());
        time7 = clock();
        cout << "LZ    :" << (double)(time7 - time6) / CLOCKS_PER_SEC << "s" << endl;
        free(lzlist);



        //   
        fdehasaki(image1.rows * image1.cols, image1.cols / NUM, image1.rows / NUM, imageline, image3, sch);
        time8 = clock();
        cout << "     :" << (double)(time8 - time7) / CLOCKS_PER_SEC << "s" << endl;
        imwrite(imageoutdst3, image3);
        //     

        cout << "         " << gethistogram(dstout + "ho.jpg", image1) << endl;
        cout << "          " << gethistogram(dstout + "hdecode.jpg", image3) << endl;
        cout << "        " << gethistogram(dstout + "hdelta1.jpg", image1, image3) << endl;
        cout << "         " << gethistogram(image1, image3, dstout + "hdelta2.jpg") << endl;

        //             
        out.close();
        thfmout.close();
        thfmlist.close();
        tlzlist.close();
        tlzout.close();
        free(imageline);
        for (i = 0; i < image1.rows; i++)
        {
            free(*(imageint + i));
        }
        free(imageint);
        cout << "    " << endl;

        endTime = clock();//    
        cout << "    : " << (double)(endTime - startTime) / CLOCKS_PER_SEC << "s" << endl;
    }
    return 0;
}

int Initimage(Mat& imagein)
{
    if (NUM != 8 && NUM != 16)
        return 0;
    int h, w;
    Mat imageout;
    h = imagein.rows / NUM;//  
    w = imagein.cols / NUM;//  
    imageout = Mat::zeros(h * NUM, w * NUM, CV_8UC1);
    resize(imagein, imageout, imageout.size());//    
    cvtColor(imageout, imageout, COLOR_RGB2GRAY);//    

    if (imageout.empty())
        return 0;
    imagein = imageout;
    return 1;
}
void DCT(int data[NUM][NUM])
{
    int output[NUM][NUM];
    double alpha, beta;//C(k)  C(l)
    int m = 0, n = 0, k = 0, l = 0;
    for (k = 0; k < NUM; k++)
    {
        for (l = 0; l < NUM; l++)
        {
            if (k == 0)
            {
                alpha = sqrt(1.0 / NUM);
            }
            else
            {
                alpha = sqrt(2.0 / NUM);
            }
            if (l == 0)
            {
                beta = sqrt(1.0 / NUM);
            }
            else
            {
                beta = sqrt(2.0 / NUM);
            }
            double temp = 0.0;
            for (m = 0; m < NUM; m++)
            {
                for (n = 0; n < NUM; n++)
                {
                    temp += data[m][n] * cos((2 * m + 1) * k * PI / (2.0 * NUM)) * cos((2 * n + 1) * l * PI / (2.0 * NUM));
                }
            }
            output[k][l] = around(alpha * beta * temp);
        }
    }
    memset(data, 0, sizeof(int) * NUM * NUM);
    std::memcpy(data, output, sizeof(int) * NUM * NUM);
}
void IDCT(int data[NUM][NUM])
{
    int output[NUM][NUM];
    double alpha, beta;
    int m = 0, n = 0, k = 0, l = 0;
    for (m = 0; m < NUM; m++)
    {
        for (n = 0; n < NUM; n++)
        {
            double temp = 0.0;
            for (k = 0; k < NUM; k++)
            {
                for (l = 0; l < NUM; l++)
                {
                    if (k == 0)
                    {
                        alpha = sqrt(1.0 / NUM);
                    }
                    else
                    {
                        alpha = sqrt(2.0 / NUM);
                    }
                    if (l == 0)
                    {
                        beta = sqrt(1.0 / NUM);
                    }
                    else
                    {
                        beta = sqrt(2.0 / NUM);
                    }

                    temp += alpha * beta * data[k][l] * cos((2 * m + 1) * k * PI / (2 * NUM)) * cos((2 * n + 1) * l * PI / (2 * NUM));

                }
            }
            output[m][n] = around(temp);
        }
    }
    memset(data, 0, sizeof(int) * NUM * NUM);
    std::memcpy(data, output, sizeof(int) * NUM * NUM);

}
int SCH(int data[NUM][NUM], int k)
{
    if (NUM == 8)
    {
        for (int i = 0; i < NUM; i++)
        {
            for (int j = 0; j < NUM; j++)
            {
                data[i][j] /= F8[k][i][j];
            }
        }
        return 1;
    }
    else
        return 0;
}
int ISCH(int data[NUM][NUM], int k)
{
    if (NUM == 8)
    {
        for (int i = 0; i < NUM; i++)
        {
            for (int j = 0; j < NUM; j++)
            {
                data[i][j] *= F8[k][i][j];
            }
        }
        return 1;
    }
    else
        return 0;
}
int around(double a)
{
    if (a >= 0)
    {
        return int(a + 0.5);
    }
    else
    {
        return int(a - 0.5);
    }

}
int fhasaki(Mat image, Mat& imageout1, int*& image1line, int**& image1int, int sch) {
    if (image.cols % NUM != 0 || image.rows % NUM != 0)
        return -1;
    int h = image.rows / NUM;
    int w = image.cols / NUM;
    imageout1 = Mat::zeros(h * NUM, w * NUM, CV_8UC1);
    //imageout2 = Mat::zeros(h * NUM, w * NUM, CV_8UC1);
    /*cout << h << w;*/
    image1line = (int*)malloc(h * w * NUM * NUM * sizeof(int));//Z          //    
    image1int = (int**)malloc(h * NUM * sizeof(int*));//          
    int k;
    for (k = 0; k < h * NUM; k++)
    {
        image1int[k] = (int*)malloc((int)w * NUM * sizeof(int));
    }
    int i, j, m, n;
    for (i = 0; i < w; i++)
    {
        for (j = 0; j < h; j++)
        {
            int piceline[NUM * NUM];
            int piceint[NUM][NUM];
            for (m = 0; m < NUM; m++)
            {
                for (n = 0; n < NUM; n++)
                {
                    piceint[m][n] = (int)image.at(j * NUM + m, i * NUM + n);//      
                }
            }
            DCT(piceint);
            SCH(piceint, sch);

            for (m = 0; m < NUM; m++)
            {
                for (n = 0; n < NUM; n++)
                {
                    image1int[j * NUM + m][i * NUM + n] = piceint[m][n];//          
                    imageout1.at(j * NUM + m, i * NUM + n) = (uchar)piceint[m][n];//          
                }
            }
            Zscan(piceint, piceline);
            for (k = 0; k < NUM * NUM; k++)
            {
                image1line[i * h * NUM * NUM + j * NUM * NUM + k] = piceline[k];//Z           
            }
            //ISCH(piceint);
            //IDCT(piceint);
            //for (m = 0; m < NUM; m++)
            //{
            //    for (n = 0; n < NUM; n++)
            //    {
            //        imageout2.at(j * NUM + m, i * NUM + n) = (uchar)piceint[m][n];//        
            //    }
            //}
        }
    }
    return 1;
}
int fdehasaki(int length, int w, int h, int* imageline, Mat& imageout2, int sch)
{
    imageout2 = Mat::zeros(h * NUM, w * NUM, CV_8UC1);
    int i, j, m, n;
    for (i = 0; i < w; i++)
    {
        for (j = 0; j < h; j++)
        {
            int piceline[NUM * NUM];
            int piceint[NUM][NUM];
            for (int k = 0; k < NUM * NUM; k++)
            {
                piceline[k] = imageline[i * h * NUM * NUM + j * NUM * NUM + k];//Z           
            }
            IZscan(piceline, piceint);
            ISCH(piceint, sch);
            IDCT(piceint);
            for (m = 0; m < NUM; m++)
            {
                for (n = 0; n < NUM; n++)
                {
                    imageout2.at(j * NUM + m, i * NUM + n) = (uchar)piceint[m][n];//        
                }
            }
        }
    }
    cout << "      !" << endl;
    return 0;
}
//     0       ,    1 ,    
int Zscan(int datain[NUM][NUM], int dataout[NUM * NUM])
{
    int i, j, k, c;
    for (i = 0, j = 0, k = 0, c = 0; k < NUM * NUM; k++)
    {
        dataout[k] = datain[i][j];
        if (i == 0 && j == 0)
            c = 0;
        else if (c == 0 && j == 0)
            c = 1;
        else if (c == 0 && j == (NUM - 1))
            c = 3;
        else if (c == 1 && j == NUM - 1)
            c = 0;
        else if (c == 1 && i == 0)
            c = 2;
        else if (c == 1)
            c = 1;
        else if (c == 2 && i == 0)
            c = 3;
        else if (c == 2 && i == (NUM - 1))
            c = 1;
        else if (c == 3 && i == (NUM - 1))
            c = 2;
        else if (c == 3 && j == 0)
            c = 0;
        else if (c == 3)
            c = 3;
        else
            return 0;
        if (c == 0)//    
        {
            i++;
        }
        else if (c == 1)//    
        {
            i--;
            j++;
        }
        else if (c == 2)//    
        {
            j++;
        }
        else if (c == 3)//    
        {
            i++;
            j--;
        }
        else
        {
            cout << "Zscan error" << endl;
            return 0;//error
        }
    }
    return 1;
}
int IZscan(int datain[NUM * NUM], int dataout[NUM][NUM])
{
    int i, j, k, c;
    for (i = 0, j = 0, k = 0, c = 0; k < NUM * NUM; k++)
    {
        dataout[i][j] = datain[k];
        if (i == 0 && j == 0)
            c = 0;
        else if (c == 0 && j == 0)
            c = 1;
        else if (c == 0 && j == (NUM - 1))
            c = 3;
        else if (c == 1 && j == NUM - 1)
            c = 0;
        else if (c == 1 && i == 0)
            c = 2;
        else if (c == 1)
            c = 1;
        else if (c == 2 && i == 0)
            c = 3;
        else if (c == 2 && i == (NUM - 1))
            c = 1;
        else if (c == 3 && i == (NUM - 1))
            c = 2;
        else if (c == 3 && j == 0)
            c = 0;
        else if (c == 3)
            c = 3;
        else
            return 0;
        if (c == 0)//    
        {
            i++;
        }
        else if (c == 1)//    
        {
            i--;
            j++;
        }
        else if (c == 2)//    
        {
            j++;
        }
        else if (c == 3)//    
        {
            i++;
            j--;
        }
        else
        {
            cout << "IZscan error" << endl;
            return 0;//error
        }
    }
    return 1;
}

string inttoox(int x, int width)
{
    string s = "";
    if (x == 0)
    {
        s = "0";
    }
    while (x != 0)
    {
        if (x % 2 == 0)
            s = "0" + s;
        else
            s = "1" + s;
        x /= 2;
    }
    if (s.length() < width)
    {
        int i = width - (int)s.length();
        for (; i > 0; i--)
            s = "0" + s;
    }
    return s;
}
int oxtoint(string s)
{
    int x = 0;
    for (int i = 0; i < s.length(); i++)
    {
        x *= 2;
        x += s[i] - '0';
    }
    return x;
}
int gethistogram(string dst, Mat image)
{
    int h = 300;
    int w = 512;
    int count[256] = { 0 };
    if (image.channels() != 1)
        Initimage(image);
    int i, j;
    for (i = 0; i < image.cols; i++)
        for (j = 0; j < image.rows; j++)
        {
            count[(int)image.at(j, i)]++;
        }

    int max = count[0];
    for (i = 0; i < 256; i++)
        if (count[i] > max)
            max = count[i];
    for (i = 0; i < 256; i++)
    {
        count[i] = max - count[i];
        count[i] = (count[i] * h / max);
    }

    Size s(w, h);
    Mat out(s, CV_8UC1);
    for (i = 0; i < 256; i++)
        for (j = 0; j < h; j++)
        {
            if (j < count[i])
            {
                out.at(j, 2 * i) = 200;
                out.at(j, 2 * i + 1) = 200;
            }
            else
            {
                out.at(j, 2 * i) = 0;
                out.at(j, 2 * i + 1) = 0;
            }
        }
    imwrite(dst, out);
    return max;
}
int gethistogram(string dst, Mat image1, Mat image2)
{
    double m=0;
    int h = 300;
    int w = 512;
    int count[256 + 255] = { 0 };
    if (image1.channels() != 1)
        Initimage(image1);
    if (image2.channels() != 1)
        Initimage(image2);
    if (image1.size() != image2.size())
    {
        cout << "     " << endl;
        return 0;
    }
    int i, j;
    for (i = 0; i < image1.cols; i++)
        for (j = 0; j < image1.rows; j++)
        {
            int x = image1.at(j, i) - image2.at(j, i);
            count[255 + x]++;
        }


    int max = count[0];
    for (i = 0; i < 256 + 255; i++)
    {
        if (count[i] > max)
            max = count[i];
        m += (i - 255) * (i - 255) * count[i];
    }
    for (i = 0; i < 256 + 255; i++)
    {
        count[i] = max - count[i];
        count[i] = (count[i] * h / max);
    }

    Size s(w, h);
    Mat out(s, CV_8UC1);
    for (i = 0; i < 256 + 255; i++)
        for (j = 0; j < h; j++)
        {
            if (j < count[i])
            {
                out.at(j, i) = 200;
            }
            else
            {
                out.at(j, i) = 0;
            }
        }
    imwrite(dst, out);
    cout << "  :"<(j, i)]++;
        }
    for (i = 0; i < image1.cols; i++)
        for (j = 0; j < image1.rows; j++)
        {
            count2[(int)image2.at(j, i)]++;
        }
    for (i = 0; i < 256; i++)
        count[i] = count1[i] - count2[i];
    int max = count[0];
    int min = count[0];
    for (i = 0; i < 256; i++)
    {
        if (count[i] > max)
            max = count[i];
        if (count[i] < min)
            min = count[i];
    }
   
    Size s(w, h);
    int v = (max*h / (max - min));
    Mat out(s, CV_8UC1);
    for (i = 0; i < 256; i++)
    {
        count[i] = -(count[i] * h / (max - min)) + v;
        for (j = 0; j < h; j++)
        {
            if (count[i] < v)
            {
                if (j < count[i] || j>v)
                {
                    out.at(j, 2 * i) = 200;
                    out.at(j, 2 * i + 1) = 200;
                }
                else
                {
                    out.at(j, 2 * i) = 0;
                    out.at(j, 2 * i + 1) = 0;
                }
            }
            else if (count[i] > v)
            {
                if (j > count[i] || j < v)
                {
                    out.at(j, 2 * i) = 200;
                    out.at(j, 2 * i + 1) = 200;
                }
                else
                {
                    out.at(j, 2 * i) = 0;
                    out.at(j, 2 * i + 1) = 0;
                }
            }
            else
            {
                out.at(j, 2 * i) = 200;
                out.at(j, 2 * i + 1) = 200;
            }
        }
    }
    imwrite(dst, out);
    return max-min;
}