/*
  Encode.java
  Contains functions that convert an RGB frame to YCbCr and save the converted data.
*/

import java.io.*;

class Encode {

  //save one YCbCr macroblock.
  public void save_yccblocks( YCbCr_MACRO ycbcr_macro, DataOutputStream out )
  {
    int b, i, j, k, r;
  
    //one macroblock has 256 Y samples
    byte [] Yblock = new byte[256];

     r = 0;
    //save four 8x8 Y sample blocks
    for ( b = 0; b < 4; b++ ) {
      if ( b < 2 )
        k = 8 * b;                //points to beginning of block
      else
        k = 128 + 8 * ( b - 2 );  //points to beginning of block
      for ( i = 0; i < 8; i++ ) { //one sample-block
        if ( i > 0 ) k += 16;     //advance k by 16 ( length of one row )
        for ( j = 0; j < 8; j++ ) {
          Yblock[r] = ( byte ) ycbcr_macro.Y[k+j]; 
          r++;
        } 
      }
    }

    //save one 8x8 Cb block
    byte [] Cb_block = new byte[64]; 
    k = 0;
    for ( i = 0; i < 8; ++i ) {
      for ( j = 0; j < 8; ++j ) {
        Cb_block[k] = ( byte ) ycbcr_macro.Cb[k];
        k++;
      }
    }

    //save one 8x8 Cr block
    byte [] Cr_block = new byte[64]; 
    k = 0; 
    for ( i = 0; i < 8; ++i ) {
      for ( j = 0; j < 8; ++j ) {
        Cr_block[k] = ( byte ) ycbcr_macro.Cr[k];
        k++;
      }
    }

    //save four Y sample blocks, one Cb block, one Cr block in file
    try {
      out.write ( Yblock );
      out.write ( Cb_block );
      out.write ( Cr_block );
    } catch (IOException e) {
      e.printStackTrace();
      System.exit(0);
    }
  }

  /*
    Convert one frome of RGB to YCbCr and save the converted data.
  */
  public void encode ( RGBImage image, DataOutputStream out )
  {
    int row, col, i, j, k, r;
    RGB_MACRO rgb_macro = new RGB_MACRO();
    YCbCr_MACRO ycbcr_macro = new YCbCr_MACRO(); //macroblock for YCbCr samples
    RgbYcc rgbycc = new RgbYcc ();
    for ( row = 0; row < image.height; row += 16 ) {
      for ( col = 0; col < image.width; col += 16 ) {
        k = row * image.width + col;
        r = 0;				
        for ( i = 0; i < 16; ++i ) {
	  for ( j = 0; j < 16; ++j ) 
	    rgb_macro.rgb[r++] = image.ibuf[k++];
	  k += ( image.width - 16 );  //points to next row within macroblock
        }
        rgbycc.macroblock2ycbcr( rgb_macro, ycbcr_macro );//convert from RGB to YCbCr
        if ( row == 0 && col == 0 )
          rgbycc.print_ymacro ( ycbcr_macro );
        save_yccblocks( ycbcr_macro, out );		  //save one YCbCr macroblock
      } //for col
    } //for row
  }
}
