#include<iostream>
#include<iomanip>
#include<fstream>
#include<math.h>
using namespace std;
struct Mblock { int unit[8][8] ; } ;
int Photo_write ( unsigned char *image_rgb, long width, long height, unsigned char *header1, unsigned char *header2 ) ;
void Photo_block ( unsigned char *image_rgb, Mblock **Yblock, Mblock **Cbblock, Mblock **Crblock, long width, long height ) ;
void InversePhoto_block ( unsigned char *image_rgb, Mblock **Yblock, Mblock **Cbblock, Mblock **Crblock, long width, long height ) ;
void Photo_DCT ( Mblock **block, long width, long height ) ;
void InversePhoto_DCT ( Mblock **block, long width, long height ) ;
void Photo_sub_Y ( Mblock **block, long width, long height ) ;
void Photo_add_Y ( Mblock **block, long width, long height ) ;
void Photo_420 ( Mblock **block, long width, long height ) ;
void Photo_quantization ( Mblock **block, double ScalingFactor, int q, long width, long height ) ;
void InversePhoto_quantization ( Mblock **block, double ScalingFactor, int q, long width, long height ) ;
void Countzero(Mblock **block, long width, long height) ;
int Photo_write ( unsigned char *image_rgb, long width, long height, unsigned char *header1, unsigned char *header2 )
{
FILE *fp ;
if ( !(fp = fopen("output.bmp", "wb")) )
return -1 ;
fwrite ( header1, sizeof(unsigned char), 18, fp ) ;
fwrite ( (unsigned char *)&width, sizeof(long), 1, fp ) ;
fwrite ( (unsigned char *)&height, sizeof(long), 1, fp ) ;
fwrite ( header2, sizeof(unsigned char), 28, fp ) ;
fwrite ( image_rgb, sizeof(unsigned char), width*height*3, fp ) ;
fclose (fp) ;
return 0 ;
}
void Photo_block ( unsigned char *image_rgb, Mblock **Yblock, Mblock **Cbblock, Mblock **Crblock, long width, long height )
{
int i, j ;
for ( j = 0 ; j < height ; j++ )
for ( i = 0 ; i < width*3 ; i+=3 ) {
Yblock[j/8][i/24].unit[j%8][(i/3)%8] = 0.114*image_rgb[j*width*3+i] + 0.587*image_rgb[j*width*3+i+1] + 0.299*image_rgb[j*width*3+i+2] ;
Cbblock[j/8][i/24].unit[j%8][(i/3)%8] = 0.5*image_rgb[j*width*3+i] + -0.3313*image_rgb[j*width*3+i+1] + -0.1687*image_rgb[j*width*3+i+2] ;
Crblock[j/8][i/24].unit[j%8][(i/3)%8] = -0.0813*image_rgb[j*width*3+i] + -0.4187*image_rgb[j*width*3+i+1] + 0.5*image_rgb[j*width*3+i+2] ;
}
}
void InversePhoto_block ( unsigned char *image_rgb, Mblock **Yblock, Mblock **Cbblock, Mblock **Crblock, long width, long height )
{
int i, j ;
for ( j = 0 ; j < height ; j++ )
for ( i = 0 ; i < width*3 ; i+=3 ) {
image_rgb[j*width*3+i] = Yblock[j/8][i/24].unit[j%8][(i/3)%8] + 1.772*Cbblock[j/8][i/24].unit[j%8][(i/3)%8] ;
image_rgb[j*width*3+i+2] = Yblock[j/8][i/24].unit[j%8][(i/3)%8] + 1.402*Crblock[j/8][i/24].unit[j%8][(i/3)%8] ;
image_rgb[j*width*3+i+1] = Yblock[j/8][i/24].unit[j%8][(i/3)%8] + -0.34414*Cbblock[j/8][i/24].unit[j%8][(i/3)%8] + -0.71414*Crblock[j/8][i/24].unit[j%8][(i/3)%8] ;
}
}
void Photo_DCT ( Mblock **block, long width, long height )
{
int mi, mj, i, j, x, y ;
double p ;
double pi = 3.1415926 ;
struct Mblock temp_block ;
double ci[8] = { 0.707, 1, 1, 1, 1, 1, 1, 1 } ;
double cj[8] = { 0.707, 1, 1, 1, 1, 1, 1, 1 } ;
for ( mj = 0 ; mj < height/8 ; mj++ ) {
for ( mi = 0 ; mi < width/8 ; mi++ ) {
for ( j = 0 ; j < 8 ; j++ ) {
for ( i = 0 ; i < 8 ; i++ ) {
p = 0 ;
for ( y = 0 ; y < 8 ; y++ )
for ( x = 0 ; x < 8 ; x++ )
p += ((block[mj][mi].unit[y][x])*cos((2*x+1)*i*pi*0.0625)*cos((2*y+1)*j*pi*0.0625)) ;
temp_block.unit[j][i] = ci[i]*cj[j]*p*0.25 ;
}
}
for ( j = 0 ; j < 8 ; j++ )
for ( i = 0 ; i < 8 ; i++ )
block[mj][mi].unit[j][i] = temp_block.unit[j][i] ;
}
}
}
void InversePhoto_DCT ( Mblock **block, long width, long height )
{
int mi, mj, i, j, x, y ;
double p ;
double pi = 3.1415926 ;
struct Mblock temp_block ;
double ci[8] = { 0.707, 1, 1, 1, 1, 1, 1, 1 } ;
double cj[8] = { 0.707, 1, 1, 1, 1, 1, 1, 1 } ;
for ( mj = 0 ; mj < height/8 ; mj++ ) {
for ( mi = 0 ; mi < width/8 ; mi++ ) {
for ( j = 0 ; j < 8 ; j++ ) {
for ( i = 0 ; i < 8 ; i++ ) {
p = 0 ;
for ( y = 0 ; y < 8 ; y++ )
for ( x = 0 ; x < 8 ; x++ )
p += (ci[x]*cj[y]*block[mj][mi].unit[y][x]*cos((2*i+1)*x*pi*0.0625)*cos((2*j+1)*y*pi*0.0625)) ;
temp_block.unit[j][i] = p*0.25 ;
}
}
for ( j = 0 ; j < 8 ; j++ )
for ( i = 0 ; i < 8 ; i++ )
block[mj][mi].unit[j][i] = temp_block.unit[j][i] ;
}
}
}
void Photo_420 ( Mblock **block, long width, long height )
{
int mj, mi, i, j ;
double temp ;
for ( mj = 0 ; mj < height/8 ; mj++ )
for ( mi = 0 ; mi < width/8 ; mi++ )
for ( j = 0 ; i < 8 ; j+=2 )
for ( i = 0 ; i < 8 ; i+=2 ) {
temp = (block[mj][mi].unit[j][i] + block[mj][mi].unit[j][i+1] + block[mj][mi].unit[j+1][i] + block[mj][mi].unit[j+1][i+1])/4 ;
block[mj][mi].unit[j][i] = temp ;
block[mj][mi].unit[j][i+1] = temp ;
block[mj][mi].unit[j+1][i] = temp ;
block[mj][mi].unit[j+1][i+1] = temp ;
}
}
void Photo_quantization ( Mblock **block, double ScalingFactor, int q, long width, long height )
{
int mi, mj, i , j ;
double qtable[8][8] =
{
10,10,15,20,25,30,35,40,
10,15,20,25,30,35,40,50,
15,20,25,30,35,40,50,60,
20,25,30,35,40,50,60,70,
25,30,35,40,50,60,70,80,
30,35,40,50,60,70,80,90,
35,40,50,60,70,80,90,100,
40,50,60,70,80,90,100,110
};
for ( mj = 0 ; mj < height/8 ; mj++ )
for ( mi = 0 ; mi < width/8 ; mi++ )
for ( j = 0 ; j < 8 ; j++ )
for ( i = 0 ; i < 8 ; i++ ) {
block[mj][mi].unit[j][i] = block[mj][mi].unit[j][i] / (qtable[j][i]*ScalingFactor) ;
}
}
void Countzero(Mblock **block, long width, long height)
{
int mi, mj, i, j, count=0 , a ;
for ( mj = 0 ; mj < height/8 ; mj++ )
for ( mi = 0 ; mi < width/8 ; mi++ )
for ( j = 0 ; j < 8 ; j++ )
for ( i = 0 ; i < 8 ; i++ )
{
a = block[mj][mi].unit[j][i] ;
if (a < 1)
count++ ;
}
cout << "countzero = " << count << endl ;
}
void InversePhoto_quantization ( Mblock **block, double ScalingFactor, int q, long width, long height )
{
int mi, mj, i , j ;
double qtable[8][8] =
{
10,10,15,20,25,30,35,40,
10,15,20,25,30,35,40,50,
15,20,25,30,35,40,50,60,
20,25,30,35,40,50,60,70,
25,30,35,40,50,60,70,80,
30,35,40,50,60,70,80,90,
35,40,50,60,70,80,90,100,
40,50,60,70,80,90,100,110
};
for ( mj = 0 ; mj < height/8 ; mj++ )
for ( mi = 0 ; mi < width/8 ; mi++ )
for ( j = 0 ; j < 8 ; j++ )
for ( i = 0 ; i < 8 ; i++ )
block[mj][mi].unit[j][i] = block[mj][mi].unit[j][i] * (qtable[j][i]*ScalingFactor) ;
}
int main()
{
int i ;
FILE *fp ;
long width, height ;
long width_blk, height_blk ;
char PhotoName[30] ;
double ScalingFactor ;
int q ;
unsigned char header1[18] ;
unsigned char header2[28] ;
cout << "Please key in the Scaling factor( bigger than 0 ): " ;
cin >> ScalingFactor ;
while ( ScalingFactor <= 0 ) {
cout << "Invalid Quantization factor, key in again( bigger than 0 ): " ;
cin >> ScalingFactor ;
}
cout << "Please key in the BMP file name:( *.bmp ) " ;
cin >> PhotoName ;
while ( !(fp = fopen( PhotoName, "rb" )) ) {
cout << "BMP file is not found, key in again( *.bmp ): " ;
memset ( PhotoName, 0, sizeof(PhotoName) ) ;
cin >> PhotoName ;
}
fread ( header1, sizeof(unsigned char), 18, fp ) ;
fread ( (unsigned char *)&width, sizeof(long), 1, fp ) ;
fread ( (unsigned char *)&height, sizeof(long), 1, fp ) ;
fread ( header2, sizeof(unsigned char), 28, fp ) ;
cout << endl << "BMP width = " << width << " pixels\n" << "BMP height = " << height ;
cout << " pixels\n" << endl << "Bitmap read OK!!" << endl ;
unsigned char *image_rgb