Advertisement
homer512

PBM

Nov 6th, 2015
145
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.34 KB | None | 0 0
  1. #include <stdio.h>
  2. /* using fopen, fprintf, fclose, fputs, perror */
  3. #include <string.h>
  4. /* using strcmp, memset */
  5. #include <errno.h>
  6. /* using errno */
  7.  
  8.  
  9. /**
  10.  * Array of fixed size representing a pixel row
  11.  */
  12. typedef int image_line[10];
  13.  
  14.  
  15. /**
  16.  * Draws a horizontal line in the image
  17.  *
  18.  * \param line points to the pixel row that is to be filled
  19.  * \param left offset of the line from the left border
  20.  * \param length number of pixels in the line
  21.  */
  22. static void draw_horizontal_line(image_line* line, int left, int length)
  23. {
  24.   int i;
  25.   for(i = left; i < length; ++i)
  26.     (*line)[i] = 1;
  27. }
  28.  
  29. /**
  30.  * Draws a vertical line in the image
  31.  *
  32.  * \param top_line points to the row in the image where the line starts
  33.  * \param horizontal_offset distance of the line from the left border
  34.  * \param length number of pixels in the line
  35.  */
  36. static void draw_vertical_line(image_line* top_line, int horizontal_offset,
  37.                    int length)
  38. {
  39.   int i;
  40.   for(i = 0; i < length; ++i)
  41.     top_line[i][horizontal_offset] = 1;
  42. }
  43.  
  44. /**
  45.  * Draws a diagonal line in the image
  46.  *
  47.  * TODO: Use Bresenham's line algorithm
  48.  *
  49.  * \param top_line points to the row in the image where the line starts
  50.  * \param horizontal_offset distance of the top point of the line from the
  51.  *                          left border
  52.  * \param length number of pixels in the line
  53.  * \param slope direction of the diagonal. +1 is from top left to bottom right,
  54.  *              -1 is from top right to bottom left
  55.  */
  56. static void draw_diagonal_line(image_line* top_line, int horizontal_offset,
  57.                    int length, int slope)
  58. {
  59.   int i;
  60.   for(i = 0; i < length; ++i) {
  61.     top_line[i][horizontal_offset] = 1;
  62.     horizontal_offset += slope;
  63.   }
  64. }
  65.  
  66. static void draw_rectangle(image_line* pixels, int image_dimensions)
  67. {
  68.   /* centered 8 x 4 rectangle */
  69.   const int vertical_size = 4;
  70.   const int horizontal_size = 8;
  71.   const int top = image_dimensions / 2 - vertical_size / 2;
  72.   const int left = image_dimensions / 2 - horizontal_size / 2;
  73.   draw_horizontal_line(pixels + top, left, horizontal_size + 1);
  74.   draw_horizontal_line(pixels + top + vertical_size - 1, left,
  75.                horizontal_size + 1);
  76.   draw_vertical_line(pixels + top + 1, left, vertical_size - 2);
  77.   draw_vertical_line(pixels + top + 1, left + horizontal_size - 1,
  78.              vertical_size - 2);
  79. }
  80.  
  81. static int print_image(image_line* pixels, int image_dimensions,
  82.                const char* filename, const char* pattern_name)
  83. {
  84.   int tmp_errno;
  85.   FILE* output;
  86.   if(! (output = fopen(filename, "w")))
  87.     goto err_rtrn;
  88.   if(fprintf(output, "P1\n"
  89.          "# This is a %1$s\n"
  90.          "%2$d %2$d\n",
  91.          pattern_name, image_dimensions) < 0)
  92.     goto err_fclose;
  93.   int i;
  94.   for(i = 0; i < image_dimensions; ++i) {
  95.     int j;
  96.     for(j = 0; j < image_dimensions; ++j) {
  97.       const int separator = j == image_dimensions - 1 ? '\n' : ' ';
  98.       if(fprintf(output, "%d%c", pixels[i][j], separator) < 0)
  99.     goto err_fclose;
  100.     }
  101.   }
  102.   if(fclose(output))
  103.     goto err_rtrn;
  104.   return 0;
  105.  err_fclose:
  106.   tmp_errno = errno;
  107.   fclose(output);
  108.   errno = tmp_errno;
  109.  err_rtrn:
  110.   return 1;
  111. }
  112.  
  113.  
  114. int main(int argc, char** argv)
  115. {
  116.   if(argc != 3)
  117.     goto err_usage;
  118.   enum pattern_t { _INVALID_, RECTANGLE, TRIANGLE, CIRCLE, SQUARE };
  119.   static const char* const pattern_names[] = {
  120.     "rectangle", "triangle", "circle", "square"
  121.   };
  122.   const int pattern_n = sizeof(pattern_names) / sizeof(*pattern_names);
  123.   const char* pattern_name = argv[1];
  124.   enum pattern_t pattern = _INVALID_;
  125.   int i;
  126.   for(i = 0; i < pattern_n; ++i) {
  127.     if(! strcmp(pattern_name, pattern_names[i])) {
  128.       pattern = i + 1;
  129.       break;
  130.     }
  131.   }
  132.   const int image_dimensions = 10;
  133.   image_line pixels[10];
  134.   memset(pixels, 0, sizeof(pixels));
  135.   switch(pattern) {
  136.   case _INVALID_:
  137.     goto err_usage;
  138.   case RECTANGLE:
  139.     draw_rectangle(pixels, image_dimensions);
  140.     break;
  141.   case TRIANGLE:
  142.   case CIRCLE:
  143.   case SQUARE:
  144.   default:
  145.     goto err_unsupported;
  146.   }
  147.   if(print_image(pixels, image_dimensions, argv[2], pattern_name)) {
  148.     perror("Saving image");
  149.     goto err_rtrn;
  150.   }
  151.   return 0;
  152.  err_rtrn:
  153.   return 1;
  154.  err_unsupported:
  155.   fputs("Operation not implemented, yet\n", stderr);
  156.   return 2;
  157.  err_usage:
  158.   fprintf(stderr, "Usage: %s [rectangle|triangle|circle|square] OUTPUT.pbm\n",
  159.       argv[0]);
  160.   return 3;
  161. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement