Tuesday, June 20, 2017

imgops

/*
 * imageops.c - Simple operations on images
 *
 * C laboratory exercises.
 * Richard Vaughan, 2014.
 */

#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

/*-------------------------------------------------
  PART 0: DEMONSTRATION
*/


// get the value in the array at coordinate (x,y)
uint8_t get_pixel( const uint8_t array[],
           unsigned int cols,
           unsigned int rows,
           unsigned int x,
           unsigned int y )
{
    assert( x < cols );
    assert( y < rows );
    return array[ y*cols + x ];
}

// set the pixel at coordinate {x,y} to the specified color
void set_pixel( uint8_t array[],
        unsigned int cols,
        unsigned int rows,
        unsigned int x,
        unsigned int y,
        uint8_t color )
{
    assert( x < cols );
    assert( y < rows );
    array[ y * cols + x ] = color;
}

// Set every pixel to 0 (black)
void zero( uint8_t array[],
  unsigned int cols,
  unsigned int rows )
{
  // your code here.
}

// Returns a pointer to a freshly allocated array that contains the
// same values as the original array, or a null pointer if the
// allocation fails. The caller is responsible for freeing the array
// later.
uint8_t* copy( const uint8_t array[],
           unsigned int cols,
           unsigned int rows )
{
  // your code here
  /*uint8_t* cp = malloc(cols*rows*sizeof(uint8_t)); //creates new array
  if(cp ==NULL) return NULL;
  for(int i =0; i<rows; y++){
    for(int x =0; i<cols; x++){

    }
  }*/
  return NULL;
}



/*-------------------------------------------------
  PART 1: OPERATIONS ON THE WHOLE IMAGE
*/

/* TASK 1 - three easy functions to get started */

// Return the darkest color that appears in the array; i.e. the
// smallest value
uint8_t min( const uint8_t array[],
    unsigned int cols,
    unsigned int rows )
{
    int dark = array[0];
    for(int i=1; i<cols*rows; i++){
        if(array[i]<dark){
            dark = array[i];
        }
    }
    return dark;
}

// Return the lightest color that appears in the array; i.e. the
// largest value
uint8_t max( const uint8_t array[],
unsigned int cols,
unsigned int rows )
{
    int light = array[0];
    for(int i =1; i<cols*rows; i++){
        if(array[i]> light){
            light = array[i];
        }
    }
    return light;
}

// TASK 2

//  Replace every instance of pre_color with post_color.
void replace_color(  uint8_t array[],
    unsigned int cols,
    unsigned int rows,
    uint8_t pre_color,
    uint8_t post_color )
{
    for(int i=0; i<cols*rows; i++){
        if(array[i] == pre_color){
            array[i] = post_color;
        }
    }
}

/* TASK 3  - two functions */


// flip the image, left-to-right, like in a mirror.
void flip_horizontal( uint8_t array[],
              unsigned int cols,
              unsigned int rows )
{
    int start, end, temp;
    for(int i=0; i<rows; i++){
        start = i*cols;
        end = (cols-1)+i*cols;
        while(start<end){
            temp= array[start];
            array[start] = array[end];
            array[end] = temp;
            start++;
            end--;
        }
    }
}

// flip the image top-to-bottom.
void flip_vertical( uint8_t array[],
            unsigned int cols,
            unsigned int rows )
{
    int start1, start2, temp;
    int startrow = 0, endrow= rows-1;
    while(startrow<endrow){
        start1=startrow*cols;
        start2=endrow*cols;
        for(int i =0; i<cols; i++){
            temp = array[start1];
            array[start1] = array[start2];
            array[start2] = temp;
            start1++;
            start2++;
        }
        startrow++;
        endrow--;
    }
}

/* TASK 4 */

// Find the first coordinate of the first pixel with a value that
// equals color. Search from left-to-right, top-to-bottom. If it is
// found, store the coordinates in *x and *y and return 1. If it is
// not found, return 0.
int locate_color(  const uint8_t array[],
  unsigned int cols,
  unsigned int rows,
  uint8_t color,
  unsigned int *x,
  unsigned int *y )
{
    int found =0, index;
    for(unsigned int yy =0; yy<rows; yy++){
        for(unsigned int xx=0; xx<cols;xx++){
            index = xx + yy*cols;
            if( array[index] == color ){
                *x = xx;
                *y = yy;
                found = 1;
                break;
            }
        }
        if( found == 1 ){
            break;
        }
    }
    return found;
}


/* TASK 5 */

// Invert the image, so that black becomes white and vice versa, and
// light shades of grey become the corresponding dark shade.
void invert( uint8_t array[],
         unsigned int cols,
         unsigned int rows )
{
    uint8_t greyscale[256];
    int color = 255;
    // create an array with numbers 0 to 255:
    for(int i =0; i< 256; i++){
        greyscale[i] = color;
        color--;
    }
    // inverts the image:
    for(int k=0; k<cols*rows; k++){
        array[k] = greyscale[array[k]];
    }
}

/* TASK 6 */

// Multiply every pixel by scale_factor, in order to brighten or
// darken the image. Any resulting value over 255 is
// thresholded to 255.
void scale_brightness( uint8_t array[],
            unsigned int cols,
            unsigned int rows,
            double scale_factor )
{
for(int i=0; i<cols*rows; i++){
double k= round((double) array[i] * scale_factor);
if(k <= 255){
array[i] = (uint8_t) k;
    }else{
      array[i] = 255;
    }
}
}


/* TASK 7 */

// Normalize the dynamic range of the image, i.e. Shift and scale the
// pixel colors so that that darkest pixel is 0 and the lightest pixel
// is 255. Hint: you already wrote min() and max().
void normalize( uint8_t array[],
        unsigned int cols,
        unsigned int rows )
{
uint8_t darkest = min(array, cols, rows);
uint8_t lightest = max(array, cols, rows);
  uint8_t arr[lightest-darkest+1];
double scale_factor = (round) (256/(max-min+1));
  for(int i=darkest; i<lightest-darkest+1; i++){
    arr[i] = i;
  }
  for(int i=0; i<cols*rows; i++){
    for(uint8_t k=0; k<lightest-darkest+1; i++){
      if(arr[k] == array[i]){
        double new = k*scale_factor;
        array[i] = (uint8_t) new;
        break;
      }
    }
  }
}

/* TASK 8 */

// Return a new image of size rows/2 by cols/2 If the original image
// has an odd number of columns, ignore its rightmost column. If the
// original image has an odd number of rows, ignore its bottom row.
// The value of a pixel at (p,q) in the new image is the average of
// the four pixels at (2p,2q), (2p+1,2q), (2p+1,2q+1), (2p,2q+1) in
// the original image.
uint8_t* half( const uint8_t array[],
      unsigned int cols,
      unsigned int rows )
{
  // creates a new array
  unsigned int newCols, newRows;
if(cols %2 != 0 ){
newCols = cols-1;
} else if(rows%2 != 0){
newRows = rows-1;
}
newCols = newCols/2;
newRows = newRows/2;
  uint8_t* arr= malloc(newCols*newRows*sizeof(uint8_t));

  //  changes values of each element
  for(int y=0; y<newRows; y++){
    for(int x =0; x<newCols; x++){
        // creates an average of four pixels
        uint8_t p22q = array[2*x+2*y*cols];
        uint8_t p21_2q = array[(2*x+1)+2*y*cols];
        uint8_t p21_2q1 = array[(2*x+1)+(2*y+1)*cols];
        uint8_t p2_2q1 = array[(2*x)+(2*y+1)*cols];

        double avg = round((p22q+p21_2q1+p21_2q+p2_2q1)/4);
        arr[x+y*cols]= (uint8_t)avg;
    }

  }
return arr;
}




/*-------------------------------------------------
  PART 2: OPERATIONS ON IMAGE SUB-REGIONS

  These functions operate only on a rectangular region of the array
  defined by a (left,top) corner (i.e. closer to the image origin) and
  (right,bottom) corner (i.e. further from the image origin).

  The region includes all the columns from [left, right-1] inclusive,
  and allthe rows from [top, bottom-1] inclusive.

  In every case, you may assume that left <= right and top <= bottom:
  do not need to test for this.

  The area of the region is right-left * bottom-top pixels, which
  implies that if left == right or top == bottom, the region has no
  area and is defined as "empty". Each function notes how to handle
  empty regions.

  In every function, use assert() to test bounds on the region
  corners.
*/

/* TASK 9 */

// Set every pixel in the region to color. If the region is empty, the
// image must be unchanged.
void region_set( uint8_t array[],
         unsigned int cols,
         unsigned int rows,
         unsigned int left,
         unsigned int top,
         unsigned int right,
         unsigned int bottom,
         uint8_t color )
{
for(int y=0; y<rows; y++){
if( y == bottom ){
break;
}
if( (y >= top) && (y < bottom)){
for(int x=0; x<cols; x++){
if( (x >= left) && (x < right)){
array[(x+y*cols)] = color;
}
}
}
}
}

/* TASK 10 */

// Return the sum of all the pixels in the region. Notice the large
// return type to handle potentially large numbers. Empty regions
// return the sum 0.
unsigned long int region_integrate( const uint8_t array[],
                    unsigned int cols,
                    unsigned int rows,
                    unsigned int left,
                    unsigned int top,
                    unsigned int right,
                    unsigned int bottom )
{
unsigned long int sum = 0;
for( int y=0; y<rows; y++){
if(y == bottom){
break;
}
if( (y>= top) && (y<bottom) ){
for(int x=0; x<cols; x++){
        if( (x >= left) && (x< right)){
     sum = sum + array[(x+y*cols)];
        }
}
}
}
return sum;
}

/* TASK 11 */

// Get a new image which is a copy of the region. Empty regions return
// a null pointer. If memory allocation fails, return a null
// pointer. The caller is responsible for freeing the returned array
// later.
uint8_t* region_copy( const uint8_t array[],
              unsigned int cols,
              unsigned int rows,
              unsigned int left,
              unsigned int top,
              unsigned int right,
              unsigned int bottom )
{
  uint8_t*arr = malloc(cols*rows*sizeof(uint8_t));
  int i =0;
  if (arr == 0){
    return NULL;
  }
  if ((left == right) || (top == bottom)){
    return NULL;
  }
  for( int y=0; y<rows; y++){
    if(y == bottom){
      break;
    }
    if( (y>= top) && (y<bottom) ){
      for(int x=0; x<cols; x++){
        if( (x >= left) && (x< right)){
              arr[i] = array[x+y*cols];
              i++;
        }
      }
    }
  }
  return arr;
}

No comments:

Post a Comment