// file: $USFS/class/image_analysis/v3.0/imaga_rle_03.cc
//

// system include files
//
#include <string.h>

// isip include files
//
#include "image_analysis.h"
#include <ppm.h>

#include "image_analysis_constants.h"

// method: rle_compute_cc
//
// arguments:
//  char_1* image_fname: (input) the image file name
//
// return:
//  a logical_1 value indicating status
//
// this method computes the compression ratio for each color
//
logical_1 Image_analysis::rle_compute_cc(char_1* image_fname_a) {

  // declare a ppm object
  //
  Ppm ppm;

  // open the ppm file
  //
  if (ppm.open_cc(image_fname_a, ISIP_READ_ONLY) == ISIP_FALSE) {
    error_handler_cc((char_1*)"rle_compute_cc",
		     (char_1*)"error opening the image file");
    return ISIP_FALSE;
  }

  // read the dimensions of the image
  //
  int_4 width = ppm.get_width_cc();
  int_4 height = ppm.get_height_cc();

  // initializing the block sizes
  //
  int_4 block_size = IMAGA_RLE_BLK_SIZE;
  int_4 actual_width = block_size;
  int_4 actual_height = block_size;
  
  // declaring the buffers for reading the ppm image
  //
  uint_1 b_red[block_size*block_size];
  uint_1 b_green[block_size*block_size];         
  uint_1 b_blue[block_size*block_size];

  // compute the cosine coefficients required for the DCT transform
  //
  if (rle_cos_cc() == ISIP_FALSE) {
    error_handler_cc((char_1*)"rle_compute_cc",
		     (char_1*)"error computing the cosine coefficients");
    return ISIP_FALSE;
  }
  
  // loop over the data
  //
  for (int_4 i=0; i < height; i+=block_size) {
    for (int_4 j=0; j < width; j+=block_size) {
      
      // checking for the out of bounds data
      //
      if ((j + block_size) >= width) {
	actual_width = width - j;
      }
      
      if ((i + block_size) >= height) {
	actual_height = height - i;
      }
      
      // read the ppm file block by block
      //
      if (ppm.read_cc(b_red, b_green, b_blue, j, i,
		      actual_width, actual_height) == ISIP_FALSE) {
	error_handler_cc((char_1*)"rle_compute_cc",
			 (char_1*)"error while reading the file");
	return ISIP_FALSE;
      }
      
      // debias the dc value before coding
      //
      if (rle_debias_cc(b_red, b_green, b_blue,
			actual_width, actual_height) == ISIP_FALSE) {
	error_handler_cc((char_1*)"rle_compute_cc",
			 (char_1*)"error subtracting the DC value");
	return ISIP_FALSE;
      }
      
      // perform the DCT transform
      //
      if (rle_dct_cc() == ISIP_FALSE) {
	error_handler_cc((char_1*)"rle_compute_cc",
			 (char_1*)"error computing the DCT transform");
	return ISIP_FALSE;
      }

      if (rle_normalize_cc() == ISIP_FALSE) {
	error_handler_cc((char_1*)"error_compute_cc",
			 (char_1*)"error normalizing the matrix");
	return ISIP_FALSE;
      }

      if (rle_zigzag_cc() == ISIP_FALSE) {
	error_handler_cc((char_1*)"rle_compute_cc",
			 (char_1*)"error performing the zigzag method");
	return ISIP_FALSE;
      }

      if (rle_bits_cc() == ISIP_FALSE) {
	error_handler_cc((char_1*)"rle_compute_cc",
			 (char_1*)"error computing the number of bits");
	return ISIP_FALSE;
      }
    }
  }

  // compute the compression ratio
  //
  rle_t_compression_d = rle_r_redbits_d + rle_r_grnbits_d + rle_r_blubits_d;
  rle_t_compression_d /= (width * height);
  
  // close the ppm object
  //
  if (ppm.close_cc() == ISIP_FALSE) {
    error_handler_cc((char_1*)"rle_compute_cc",
		     (char_1*)"error closing the file");
    return ISIP_FALSE;
  }
  
  // increment the counters
  //
  rle_r_nimages_d += (int_4)1;
  
  // exit gracefully
  //
  return ISIP_TRUE;
}
