JPEG编码中的DCT与量化

来源:互联网 发布:linux下python mmap 编辑:程序博客网 时间:2024/06/08 19:00

研一上很快过去了,留下了若干课程资料的文件夹。最近整理一下这些资料,挑选一些有用的课程作业贴到博客里面来。

1. 简介

JPEG是最常用的有损图像压缩算法,而8×8的二维DCT(离散余弦变换)变换和量化又是该算法中的核心步骤。本文作业的例子,是针对一个8×8的数据块进行正反二维DCT变换、量化和反量化。

2. 作业题目

逐个读入8×8(十六进制文本串格式的)亮度数据块,依次进行二维DCT变换、量化(采用标准亮度量化表)、逆量化和逆二维DCT变换。输出原始数据、变换后的数据、量化表、量化后的数据、逆量化的数据和反变换的数据。

3. 过程

这里写图片描述
这里写图片描述

4. 源码

/* * main.cpp * *  Created on: 2016.10.17 *  Author: liboyang */#include <iostream>#include <stdlib.h>#include <math.h>#include <fstream>#include <string>#include <iomanip>#define MAXSIZE 64#define COL 8#define ROW 8#define PI 3.1415926using namespace std;int Char2Int(char c);void getIntInput(int index, int counterRow, string input);void DCT(int index);void IDCT(int index);void Quantisation(int index);void inverseQuantisation(int index);string inputString[4][ROW];int inputInt[4][ROW][COL];double outputDCT[4][ROW][COL];double outputIDCT[4][ROW][COL];double outputQuan[4][ROW][COL];double outputInverseQuan[4][ROW][COL];int quantisationChart[ROW][COL]= {        {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}};int main() {    string tempRead;    ifstream inFile;    /* Read from file */    inFile.open("./input.txt", ios::in);    if (NULL == inFile) {        cout << "文件打开失败!" << endl;        return 1;    }    int counterInput = 0, indexInput = 0;    while (getline(inFile, tempRead)) {        inputString[indexInput][counterInput] = tempRead;        counterInput++;        if (counterInput == 7) {            counterInput = 0;            indexInput++;            counterInput--;        }    }    /*cout << "源图像样本16进制" << endl;    for (int i = 0; i < 4; i++) {        for (int j = 0; j < ROW; j++) {            cout << setw(2) << inputString[i][j] << endl;        }        cout << endl;    }*/    /* Change Hex to Dec */    for (int i = 0; i < 4; i++) {        for (int j = 0; j < ROW; j++) {            getIntInput(i, j, inputString[i][j]);        }    }    cout << endl << "源图像样本10进制" << endl;    for (int m = 0; m < 4; m++) {        for (int i = 0; i < ROW; i++) {            for (int j = 0; j < COL; j++) {                cout << setw(2) << inputInt[m][i][j] << " \t";            }            cout << endl;        }        cout << endl;    }    cout << endl << "DCT" << endl;    /* DCT */    /* Each element minus 128 */    for (int m = 0; m < 4; m++) {        for (int i = 0; i < ROW; i++) {            for (int j = 0; j < COL; j++) {                inputInt[m][i][j] -= 128;            }        }    }    for (int i = 0; i < 4; i++) {        DCT(i);    }    for (int m = 0; m < 4; m++) {        for (int i = 0; i < ROW; i++) {            for (int j = 0; j < COL; j++) {                cout << setw(2) << fixed << setprecision(1) << outputDCT[m][i][j] << " \t";            }            cout << endl;        }        cout << endl;    }    cout << endl << "标准量化表" << endl;    /* Quantisation */    for (int i = 0; i < ROW; i++) {        for (int j = 0; j < COL; j++) {            cout << setw(2) << quantisationChart[i][j] << " \t";        }        cout << endl;    }    for (int i = 0; i < 4; i++) {        Quantisation(i);    }    cout << endl << "量化系数" << endl;    for (int m = 0; m < 4; m++) {        for (int i = 0; i < ROW; i++) {            for (int j = 0; j < COL; j++) {                cout << setw(2) << fixed << setprecision(0) << outputQuan[m][i][j] << " \t";            }            cout << endl;        }        cout << endl;    }    for (int i = 0; i < 4; i++) {        inverseQuantisation(i);    }    cout << endl << "反量化系数" << endl;    for (int m = 0; m < 4; m++) {        for (int i = 0; i < ROW; i++) {            for (int j = 0; j < COL; j++) {                cout << setw(2) << fixed << setprecision(0) << outputInverseQuan[m][i][j] << " \t";            }            cout << endl;        }        cout << endl;    }    cout << endl << "IDCT" << endl;    for (int i = 0; i < 4; i++) {        IDCT(i);    }    /* Each element add 128 */    for (int m = 0; m < 4; m++) {        for (int i = 0; i < ROW; i++) {            for (int j = 0; j < COL; j++) {                outputIDCT[m][i][j] += 128;            }        }    }    for (int m = 0; m < 4; m++) {        for (int i = 0; i < ROW; i++) {            for (int j = 0; j < COL; j++) {                cout << setw(2) << fixed << setprecision(0) << outputIDCT[m][i][j] << " \t";            }            cout << endl;        }        cout << endl;    }    system("pause");    return 0;}int Char2Int(char c) {    if (c >= '0'&& c <= '9') {        return c - '0';    }    else if (c >= 'A' && c <= 'F') {        return c - 'A' + 10;    }    else if (c >= 'a' && c <= 'f') {        return c - 'a' + 10;    }    return -1;}void getIntInput(int index, int counterRow, string input) {    int first, second;    int counter = 0;    for (int i = 0; i < MAXSIZE; i+=3) {        first = Char2Int(input[i]);        second = Char2Int(input[i+1]);        if (first != -1 && second != -1) {            inputInt[index][counterRow][counter] = second + first * 16;            counter++;        }    }}void DCT(int index) {    double ALPHA, BETA;    int u = 0;    int v = 0;    int i = 0;    int j = 0;    for (u = 0; u < ROW; u++) {        for (v = 0; v < COL; v++) {            if (u == 0) {                ALPHA = 1.0 / sqrt(2);            }            else {                ALPHA = 1.0;            }            if (v == 0) {                BETA = 1.0 / sqrt(2);            }            else {                BETA = 1.0;            }            double tmp = 0.0;            for (i = 0; i < ROW; i++) {                for (j = 0; j < COL; j++) {                    tmp += inputInt[index][i][j] * cos((2*i+1)*u*PI/16) * cos((2*j+1)*v*PI/16);                }            }            outputDCT[index][u][v] = ALPHA * BETA * tmp * 0.25;        }    }}void Quantisation(int index) {    int u, v;    for (u = 0; u < ROW; u++) {        for (v = 0; v < COL; v++) {            outputQuan[index][u][v] = round(outputDCT[index][u][v] / quantisationChart[u][v]);            if (outputQuan[index][u][v] == -0) {                outputQuan[index][u][v] = 0;            }        }    }}void inverseQuantisation(int index) {    int u, v;    for (u = 0; u < ROW; u++) {        for (v = 0; v < COL; v++) {            outputInverseQuan[index][u][v] = outputQuan[index][u][v] * quantisationChart[u][v];            if (outputInverseQuan[index][u][v] == -0) {                outputInverseQuan[index][u][v] = 0;            }        }    }}void IDCT(int index) {    double ALPHA, BETA;    int u = 0;    int v = 0;    int i = 0;    int j = 0;    for (i = 0; i < ROW; i++) {        for (j = 0; j < COL; j++) {            double tmp = 0.0;            for (u = 0; u < ROW; u++) {                for (v = 0; v < COL; v++) {                    if (u == 0) {                        ALPHA = 1.0 / sqrt(2);                    }                    else {                        ALPHA = 1.0;                    }                    if (v == 0) {                        BETA = 1.0 / sqrt(2);                    }                    else {                        BETA = 1.0;                    }                    tmp += ALPHA * BETA * cos((2*i+1)*u*PI/16) * cos((2*j+1)*v*PI/16) * outputInverseQuan[index][u][v];                }            }            outputIDCT[index][i][j] = 0.25 * tmp;        }    }}
0 0
原创粉丝点击