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 and vice versa.

common.h
rgb_ybr.h
encode.h
rgb_ybr.cpp
encode.cpp
typlayer.cpp
Makefile
sample_video.raw



encode.cpp:
/*
  encode.cpp
  Contains functions to convert an RGB frame to YCbCr and to save the converted data.
  See 'http://www.webkinesia.com/games/vcompress.php'
*/
#include <stdio.h>
#include <stdlib.h>
#include "common.h"
#include "rgb_ybr.h"

extern short width;		//image width
extern short height;		//image height

//save one YCbCr macroblock.
void save_ybrblocks( YCbCr_MACRO *ycbcr_macro, FILE *fpo )
{
  short block, i, j, k, *py;
  
  //save 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
    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++ ) {
	putc ( ( int )  *(py+j),fpo);	//save one byte of data
      }
    }
  }
  
  //save one 8x8 Cb block
  k = 0;
  for ( i = 0; i < 8; ++i ) {
    for ( j = 0; j < 8; ++j ) {
      putc( ( int ) ycbcr_macro->Cb[k++], fpo );
    }
  }

  //save one 8x8 Cr block
  k = 0; 
  for ( i = 0; i < 8; ++i ) {
    for ( j = 0; j < 8; ++j ) {
      putc( ( int ) ycbcr_macro->Cr[k++], fpo );
    }
  } 
}

/*
  Convert RGB to YCbCr 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_ybrblocks( &ycbcr_macro, fpo );		//save one YCbCr macroblock
    } //for col
  } //for row
}