Content-Aware-Image-Resizer / src / Image.cpp
Image.cpp
Raw
#include <cassert>
#include "Image.h"
#include <string>

// REQUIREMENTS: Pointer 'img' must reference a valid Image object
//              Dimensions must be within predefined bounds
// MODIFIES: The Image object referenced by 'img'
// PURPOSE:  Configures the Image with specified width and height.
// NOTE:     No dynamic memory allocation (new/delete) should be used.
void Image_init(Image* img, int width, int height) {
  assert(width > 0 && width <= MAX_MATRIX_WIDTH);
  assert(height > 0 && height <= MAX_MATRIX_HEIGHT);
  img->width = width;
  img->height = height;
  Matrix_init(&img->red_channel, width, height);
  Matrix_init(&img->green_channel, width, height);
  Matrix_init(&img->blue_channel, width, height);
}

// REQUIREMENTS: 'img' points to an Image
//               'is' provides a valid PPM image stream (no comments)
// MODIFIES: The Image object referenced by 'img'
// PURPOSE:  Reads a PPM image from the input stream and initializes 'img'
void Image_init(Image* img, std::istream& is) {
  std::string format;
  int width, height, max_value;
  is >> format >> width >> height >> max_value;
  Image_init(img, width, height);
  
  for (int r = 0; r < height; ++r) {
    for (int c = 0; c < width; ++c) {
      is >> *Matrix_at(&img->red_channel, r, c)
         >> *Matrix_at(&img->green_channel, r, c)
         >> *Matrix_at(&img->blue_channel, r, c);
    }
  }
}

// REQUIREMENTS: 'img' is a properly initialized Image
// PURPOSE:  Outputs the Image to the given stream in PPM format
//           Uses required whitespace formatting.
void Image_print(const Image* img, std::ostream& os) {
  os << "P3\n";
  os << img->width << " " << img->height << "\n255\n";
  
  for (int r = 0; r < img->height; ++r) {
    for (int c = 0; c < img->width; ++c) {
      Pixel px = Image_get_pixel(img, r, c);
      os << px.r << " " << px.g << " " << px.b << " ";
    }
    os << "\n";
  }
}

// REQUIREMENTS: 'img' is a valid Image instance
// PURPOSE:  Retrieves the width of the Image.
int Image_width(const Image* img) {
  return img->width;
}

// REQUIREMENTS: 'img' is a valid Image instance
// PURPOSE:  Retrieves the height of the Image.
int Image_height(const Image* img) {
  return img->height;
}

// REQUIREMENTS: 'img' points to an initialized Image
//               'row' and 'column' are within valid bounds
// PURPOSE:  Returns the pixel at the specified position.
Pixel Image_get_pixel(const Image* img, int row, int column) {
  assert(row >= 0 && row < img->height);
  assert(column >= 0 && column < img->width);
  
  return {
    *Matrix_at(&img->red_channel, row, column),
    *Matrix_at(&img->green_channel, row, column),
    *Matrix_at(&img->blue_channel, row, column)
  };
}

// REQUIREMENTS: 'img' is a valid Image instance
//               'row' and 'column' are within valid bounds
// MODIFIES: The Image at the specified location
// PURPOSE:  Updates the pixel at the given position.
void Image_set_pixel(Image* img, int row, int column, Pixel color) {
  assert(row >= 0 && row < img->height);
  assert(column >= 0 && column < img->width);

  *Matrix_at(&img->red_channel, row, column) = color.r;
  *Matrix_at(&img->green_channel, row, column) = color.g;
  *Matrix_at(&img->blue_channel, row, column) = color.b;
}

// REQUIREMENTS: 'img' is a valid Image instance
// MODIFIES: Entire Image
// PURPOSE:  Fills the Image with the specified color.
void Image_fill(Image* img, Pixel color) {
  for (int r = 0; r < img->height; ++r) {
    for (int c = 0; c < img->width; ++c) {
      Image_set_pixel(img, r, c, color);
    }
  }
}