Sample program for converting RGB to YCbCr to DCT coefficients and vice versa.
/*
encode.cpp
Contains functions to convert an RGB frame to YCbCr to DCT coeffs and to save the converted data.
See 'http://www.webkinesia.com/games/vcompress4.php'
*/
#include <stdio.h>
#include <stdlib.h>
#include "common.h"
#include "rgb_ybr.h"
#include "dct_video.h"
extern short width; //image width
extern short height; //image height
//save one DCT block; this is just for testing and learning. Eventually, we won't need this
void save_dct_block ( int *Y, FILE *fpo )
{
short temp[64];
for ( int i = 0; i < 64; ++i )
temp[i] = ( short ) Y[i]; //convert to short ( 2 bytes );
fwrite ( temp, 2, 64, fpo ); //save the block
}
//save DCT coeffs for one macroblock.
void save_dctcoefs( YCbCr_MACRO *ycbcr_macro, FILE *fpo )
{
short block, i, j, k, *py;
int X[64], Y[64]; //for DCT transform
//save DCT coefs for four 8x8 Y sample blocks
for ( block = 0; block < 4; block++ ) {
if ( block < 2 )
py = ( short * ) &ycbcr_macro->Y + 8*block; //points to beginning of block
else
py = (short *)&ycbcr_macro->Y + 128 + 8*(block-2);//points to beginning of block
k = 0;
for ( i = 0; i < 8; i++ ) { //one sample-block
if ( i > 0 ) py += 16; //advance py by 16 ( length of one row )
for ( j = 0; j < 8; j++ ) {
X[k++] = (int) *( py + j );
}
}
dct ( X, Y ); //perform DCT for the sample block
save_dct_block ( Y, fpo ); //save DCT coefs for Y block
}
//save one 8x8 Cb block
k = 0;
for ( i = 0; i < 8; ++i ) {
for ( j = 0; j < 8; ++j ) {
X[k] = (int) ycbcr_macro->Cb[k];
k++;
}
}
dct ( X, Y ); //perform DCT for the sample block
save_dct_block ( Y, fpo ); //save DCT coefs for Cb block
//save one 8x8 Cr block
k = 0;
for ( i = 0; i < 8; ++i ) {
for ( j = 0; j < 8; ++j ) {
X[k] = (int) ycbcr_macro->Cr[k];
k++;
}
}
dct ( X, Y ); //perform DCT for the sample block
save_dct_block ( Y, fpo ); //save DCT coefs for Cr block
}
/*
Convert RGB to YCbCr to DCT coefs and save the converted data.
width, height are global variables of image.
*/
void encode ( char *image, FILE *fpo )
{
short row, col, i, j, r;
RGB macro16x16[256]; //16x16 pixel macroblock; assume 24-bit for each RGB pixel
YCbCr_MACRO ycbcr_macro; //macroblock for YCbCr samples
RGB *p; //pointer to an RGB pixel
static int nframe = 0;
for ( row = 0; row < height; row += 16 ) {
for ( col = 0; col < width; col += 16 ) {
p = ( RGB *) image + ( row * width + col ); //points to beginning of macroblock
r = 0; //note pointer arithmetic
for ( i = 0; i < 16; ++i ) {
for ( j = 0; j < 16; ++j ) {
macro16x16[r++] = (RGB) *p++;
}
p += ( width - 16 ); //points to next row within macroblock ( note pointer arithmetic )
}
macroblock2ycbcr ( macro16x16, &ycbcr_macro ); //convert from RGB to YCbCr
save_dctcoefs( &ycbcr_macro, fpo ); //save one YCbCr macroblock
} //for col
} //for row
}