// file: $USFS/class/ppm/v1.0/ppm_write_1.cc
//

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

// isip include files
//
#include "ppm.h"

#include <integral_constants.h>
#include "ppm_constants.h"

// method: write_cc
//
// arguments:
//  uint_1* b_red_a: (input) intensity of the red component
//  uint_1* b_green_a: (input) intensity of the green component
//  uint_1* b_blue_a: (input) intensity of the blue component
//  int_4 offset_w_a: (input) starting pixel in the horizontal direction
//  int_4 offset_h_a: (input) starting pixel in the vertical direction
//  int_4 width_a: (input) number of pixels in the horizontal direction
//  int_4 height_a: (input) number of pixels in the vertical direction
//
// return: a logical_1 value indicating status
//
// this method writes data row by row. it uses a scratch buffer
// that is large enough to hold one row worth of data.
//
logical_1 Ppm::write_cc(uint_1* b_red_a, uint_1* b_green_a, uint_1* b_blue_a,
			int_4 offset_w_a, int_4 offset_h_a,
			int_4 width_a, int_4 height_a) {
  
  // check for out of bounds data in the width dimension
  //
  int_4 actual_width = width_a;
  
  if ((offset_w_a + actual_width) >= width_d) {
    actual_width = width_d - offset_w_a;
  }
  if (actual_width < (int_4)0) {
    return ISIP_FALSE;
  }
  
  // check for out of bounds data in the height dimension
  //
  int_4 actual_height = height_a;
  
  if ((offset_h_a + actual_height) >= height_d) {
    actual_height = height_d - offset_h_a;
  }

  if (actual_height < (int_4)0) {
    return ISIP_FALSE;
  }
  
  // loop over the rows			
  //			
  int_4 o_row = (int_4)0;
  int_4 last_row = offset_h_a + actual_height;
  
  for (int_4 row_num=offset_h_a; row_num<last_row; row_num++) {
    
    // compute the new position we need to seek to
    //	
    int_4 new_pos = (row_num * width_d + offset_w_a) *
      PPM_NBYTES_PER_PIXEL + beg_d;
    
    // seek to this new location
    //
    if (fseek(fp_d, new_pos, SEEK_SET) < (int)0) {
           return ISIP_FALSE;
    }
    
    // read the data into a temporary buffer
    //
    int_4 nbytes_to_write = actual_width * PPM_NBYTES_PER_PIXEL;
    uint_1* tmp_buf;
    tmp_buf = new uint_1[nbytes_to_write];
    
    // write the data first into a buffer
    //
    int_4 o_offset = o_row * width_a;
    int_4 last_val = o_offset + actual_width;
    
    int_4 j = 0;
    for (int_4 i=o_offset; i<last_val; i++) {
      tmp_buf[j++] = b_red_a[i];
      tmp_buf[j++] = b_green_a[i];
      tmp_buf[j++] = b_blue_a[i];
    }
    
    // write the data from the buffer into the file
    //
    if (fwrite((const void*)tmp_buf, 1, nbytes_to_write, fp_d) == 0) {
      error_handler_cc((char_1*)"fwrite",
		       (char_1*)"error in writing the message");
    }
    
    // delete the scratch space
    //
    delete [] tmp_buf;
    tmp_buf = (uint_1*)NULL;
    
    // increment the output row counter
    //
    o_row++;
  }
  
  // exit gracefully
  //
  return ISIP_TRUE;
}
