homer512 icon

PBM

homer512 | PRO | 11/06/15 03:12:00 PM UTC | 0 ⭐ | 647 👁️ | Never ⏰ | []
C |

4.34 KB

|

None

|

0 👍

/

0 👎

#include <stdio.h>
/* using fopen, fprintf, fclose, fputs, perror */
#include <string.h>
/* using strcmp, memset */
#include <errno.h>
/* using errno */
 
 
/**
 * Array of fixed size representing a pixel row
 */
typedef int image_line[10];
 
 
/**
 * Draws a horizontal line in the image
 *
 * \param line points to the pixel row that is to be filled
 * \param left offset of the line from the left border
 * \param length number of pixels in the line
 */
static void draw_horizontal_line(image_line* line, int left, int length)
{
  int i;
  for(i = left; i < length; ++i)
    (*line)[i] = 1;
}
 
/**
 * Draws a vertical line in the image
 *
 * \param top_line points to the row in the image where the line starts
 * \param horizontal_offset distance of the line from the left border
 * \param length number of pixels in the line
 */
static void draw_vertical_line(image_line* top_line, int horizontal_offset,
                   int length)
{
  int i;
  for(i = 0; i < length; ++i)
    top_line[i][horizontal_offset] = 1;
}
 
/**
 * Draws a diagonal line in the image
 *
 * TODO: Use Bresenham's line algorithm
 *
 * \param top_line points to the row in the image where the line starts
 * \param horizontal_offset distance of the top point of the line from the
 *                          left border
 * \param length number of pixels in the line
 * \param slope direction of the diagonal. +1 is from top left to bottom right,
 *              -1 is from top right to bottom left
 */
static void draw_diagonal_line(image_line* top_line, int horizontal_offset,
                   int length, int slope)
{
  int i;
  for(i = 0; i < length; ++i) {
    top_line[i][horizontal_offset] = 1;
    horizontal_offset += slope;
  }
}
 
static void draw_rectangle(image_line* pixels, int image_dimensions)
{
  /* centered 8 x 4 rectangle */
  const int vertical_size = 4;
  const int horizontal_size = 8;
  const int top = image_dimensions / 2 - vertical_size / 2;
  const int left = image_dimensions / 2 - horizontal_size / 2;
  draw_horizontal_line(pixels + top, left, horizontal_size + 1);
  draw_horizontal_line(pixels + top + vertical_size - 1, left,
               horizontal_size + 1);
  draw_vertical_line(pixels + top + 1, left, vertical_size - 2);
  draw_vertical_line(pixels + top + 1, left + horizontal_size - 1,
             vertical_size - 2);
}
 
static int print_image(image_line* pixels, int image_dimensions,
               const char* filename, const char* pattern_name)
{
  int tmp_errno;
  FILE* output;
  if(! (output = fopen(filename, "w")))
    goto err_rtrn;
  if(fprintf(output, "P1\n"
         "# This is a %1$s\n"
         "%2$d %2$d\n",
         pattern_name, image_dimensions) < 0)
    goto err_fclose;
  int i;
  for(i = 0; i < image_dimensions; ++i) {
    int j;
    for(j = 0; j < image_dimensions; ++j) {
      const int separator = j == image_dimensions - 1 ? '\n' : ' ';
      if(fprintf(output, "%d%c", pixels[i][j], separator) < 0)
    goto err_fclose;
    }
  }
  if(fclose(output))
    goto err_rtrn;
  return 0;
 err_fclose:
  tmp_errno = errno;
  fclose(output);
  errno = tmp_errno;
 err_rtrn:
  return 1;
}
 
 
int main(int argc, char** argv)
{
  if(argc != 3)
    goto err_usage;
  enum pattern_t { _INVALID_, RECTANGLE, TRIANGLE, CIRCLE, SQUARE };
  static const char* const pattern_names[] = {
    "rectangle", "triangle", "circle", "square"
  };
  const int pattern_n = sizeof(pattern_names) / sizeof(*pattern_names);
  const char* pattern_name = argv[1];
  enum pattern_t pattern = _INVALID_;
  int i;
  for(i = 0; i < pattern_n; ++i) {
    if(! strcmp(pattern_name, pattern_names[i])) {
      pattern = i + 1;
      break;
    }
  }
  const int image_dimensions = 10;
  image_line pixels[10];
  memset(pixels, 0, sizeof(pixels));
  switch(pattern) {
  case _INVALID_:
    goto err_usage;
  case RECTANGLE:
    draw_rectangle(pixels, image_dimensions);
    break;
  case TRIANGLE:
  case CIRCLE:
  case SQUARE:
  default:
    goto err_unsupported;
  }
  if(print_image(pixels, image_dimensions, argv[2], pattern_name)) {
    perror("Saving image");
    goto err_rtrn;
  }
  return 0;
 err_rtrn:
  return 1;
 err_unsupported:
  fputs("Operation not implemented, yet\n", stderr);
  return 2;
 err_usage:
  fprintf(stderr, "Usage: %s [rectangle|triangle|circle|square] OUTPUT.pbm\n",
      argv[0]);
  return 3;
}

Comments