Linux Game Programming for PC & Embedded Systems using SDL
Presented by
Fore June
Author of Windows Fan, Linux Fan

Sample program for converting RGB to YCbCr to DCT coefficients and vice versa.

common.h
rgb_ybr.h
dct_video.h
encode.h
dctplayer.cpp
encode.cpp
dct_video.cpp
rgb_ybr.cpp
Makefile
sample_video.raw



encode.cpp:
/*
  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
}