Advertisement
dylanm312

helpers.c

Dec 18th, 2023 (edited)
750
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.96 KB | None | 0 0
  1. #include <math.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5.  
  6. #include "helpers.h"
  7.  
  8. int clamp_value(float val);
  9. void add_pixel(RGBTRIPLE pixel, int reds[], int greens[], int blues[], int *numPixels);
  10. RGBTRIPLE get_average_pixel(int reds[], int greens[], int blues[], int numPixels);
  11. RGBTRIPLE get_convolution(int reds[], int greens[], int blues[], char type);
  12.  
  13. // Convert image to grayscale
  14. void grayscale(int height, int width, RGBTRIPLE image[height][width])
  15. {
  16.     for (int r = 0; r < height; r++)
  17.     {
  18.         for (int c = 0; c < width; c++)
  19.         {
  20.             // Get initial pixel values
  21.             int red = image[r][c].rgbtRed;
  22.             int green = image[r][c].rgbtGreen;
  23.             int blue = image[r][c].rgbtBlue;
  24.  
  25.             // Get average value
  26.             int avg = clamp_value((red + green + blue) / 3.0);
  27.  
  28.             // Set this pixel's colors to the average
  29.             image[r][c].rgbtRed = avg;
  30.             image[r][c].rgbtGreen = avg;
  31.             image[r][c].rgbtBlue = avg;
  32.         }
  33.     }
  34. }
  35.  
  36. // Reflect image horizontally
  37. void reflect(int height, int width, RGBTRIPLE image[height][width])
  38. {
  39.     // Create a temporary row to store the flipped values in
  40.     RGBTRIPLE *row = calloc(width, sizeof(RGBTRIPLE));
  41.  
  42.     for (int r = 0; r < height; r++)
  43.     {
  44.         // Store the current row in the temp row
  45.         memcpy(row, image[r], width * sizeof(RGBTRIPLE));
  46.  
  47.         // Flip the temp and stick it in the original row
  48.         for (int c = 0; c < width; c++)
  49.         {
  50.             image[r][c].rgbtRed = row[width - c - 1].rgbtRed;
  51.             image[r][c].rgbtGreen = row[width - c - 1].rgbtGreen;
  52.             image[r][c].rgbtBlue = row[width - c - 1].rgbtBlue;
  53.         }
  54.     }
  55. }
  56.  
  57. // Blur image
  58. void blur(int height, int width, RGBTRIPLE image[height][width])
  59. {
  60.     // Copy the image
  61.     RGBTRIPLE(*tmp)[width] = calloc(height, width * sizeof(RGBTRIPLE));
  62.     memcpy(tmp, image, height * width * sizeof(RGBTRIPLE));
  63.  
  64.     // Create arrays to store the color values of each neighboring pixel
  65.     int numPixels = 0;
  66.  
  67.     int reds[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
  68.     int greens[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
  69.     int blues[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
  70.  
  71.     for (int r = 0; r < height; r++)
  72.     {
  73.         for (int c = 0; c < width; c++)
  74.         {
  75.             // Zero out garbage values in the color arrays
  76.             numPixels = 0;
  77.  
  78.             for (int i = 0; i < 9; i++) {reds[i] = 0;}
  79.             for (int i = 0; i < 9; i++) {greens[i] = 0;}
  80.             for (int i = 0; i < 9; i++) {blues[i] = 0;}
  81.  
  82.             // Add pixels to average
  83.  
  84.             // 1. Top left
  85.             if (r > 0 && c > 0)
  86.             {
  87.                 add_pixel(tmp[r-1][c-1], reds, greens, blues, &numPixels);
  88.             }
  89.  
  90.             // 2. Top center
  91.             if (r > 0)
  92.             {
  93.                 add_pixel(tmp[r-1][c], reds, greens, blues, &numPixels);
  94.             }
  95.  
  96.             // 3. Top right
  97.             if (r > 0 && c < width - 1)
  98.             {
  99.                 add_pixel(tmp[r-1][c+1], reds, greens, blues, &numPixels);
  100.             }
  101.  
  102.             // 4. Left
  103.             if (c > 0)
  104.             {
  105.                 add_pixel(tmp[r][c-1], reds, greens, blues, &numPixels);
  106.             }
  107.  
  108.             // 5. Center
  109.             add_pixel(tmp[r][c], reds, greens, blues, &numPixels);
  110.  
  111.             // 6. Right
  112.             if (c < width - 1)
  113.             {
  114.                 add_pixel(tmp[r][c+1], reds, greens, blues, &numPixels);
  115.             }
  116.  
  117.             // 7. Bottom left
  118.             if (r < height - 1 && c > 0)
  119.             {
  120.                 add_pixel(tmp[r+1][c-1], reds, greens, blues, &numPixels);
  121.             }
  122.  
  123.             // 8. Bottom
  124.             if (r < height - 1)
  125.             {
  126.                 add_pixel(tmp[r+1][c], reds, greens, blues, &numPixels);
  127.             }
  128.  
  129.             // 9. Bottom right
  130.             if (r < height - 1 && c < width - 1)
  131.             {
  132.                 add_pixel(tmp[r+1][c+1], reds, greens, blues, &numPixels);
  133.             }
  134.  
  135.             // Set the current pixel to the average
  136.             RGBTRIPLE avg = get_average_pixel(reds, greens, blues, numPixels);
  137.             image[r][c] = avg;
  138.         }
  139.     }
  140.  
  141.     // Clean up
  142.     free(tmp);
  143. }
  144.  
  145. // Detect edges
  146. void edges(int height, int width, RGBTRIPLE image[height][width])
  147. {
  148.     // Make a copy of the original
  149.     RGBTRIPLE(*tmp)[width] = calloc(height, width * sizeof(RGBTRIPLE));
  150.     memcpy(tmp, image, height * width * sizeof(RGBTRIPLE));
  151.  
  152.     // Create arrays to store the color values of each neighboring pixel
  153.     int numPixels = 0;
  154.  
  155.     int reds[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
  156.     int greens[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
  157.     int blues[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
  158.  
  159.     for (int r = 0; r < height; r++)
  160.     {
  161.         for (int c = 0; c < width; c++)
  162.         {
  163.             // Zero out garbage values in the color arrays
  164.             numPixels = 0;
  165.  
  166.             for (int i = 0; i < 9; i++) {reds[i] = 0;}
  167.             for (int i = 0; i < 9; i++) {greens[i] = 0;}
  168.             for (int i = 0; i < 9; i++) {blues[i] = 0;}
  169.  
  170.             // Add pixels to average
  171.  
  172.             // 1. Top left
  173.             if (r > 0 && c > 0)
  174.             {
  175.                 add_pixel(tmp[r-1][c-1], reds, greens, blues, &numPixels);
  176.             }
  177.             else
  178.             {
  179.                 // By simply incrementing the counter, we add a black pixel to the list
  180.                 numPixels++;
  181.             }
  182.  
  183.             // 2. Top center
  184.             if (r > 0)
  185.             {
  186.                 add_pixel(tmp[r-1][c], reds, greens, blues, &numPixels);
  187.             }
  188.             else
  189.             {
  190.                 numPixels++;
  191.             }
  192.  
  193.             // 3. Top right
  194.             if (r > 0 && c < width - 1)
  195.             {
  196.                 add_pixel(tmp[r-1][c+1], reds, greens, blues, &numPixels);
  197.             }
  198.             else
  199.             {
  200.                 numPixels++;
  201.             }
  202.  
  203.             // 4. Left
  204.             if (c > 0)
  205.             {
  206.                 add_pixel(tmp[r][c-1], reds, greens, blues, &numPixels);
  207.             }
  208.             else
  209.             {
  210.                 numPixels++;
  211.             }
  212.  
  213.             // 5. Center
  214.             add_pixel(tmp[r][c], reds, greens, blues, &numPixels);
  215.  
  216.             // 6. Right
  217.             if (c < width - 1)
  218.             {
  219.                 add_pixel(tmp[r][c+1], reds, greens, blues, &numPixels);
  220.             }
  221.             else
  222.             {
  223.                 numPixels++;
  224.             }
  225.  
  226.             // 7. Bottom left
  227.             if (r < height - 1 && c > 0)
  228.             {
  229.                 add_pixel(tmp[r+1][c-1], reds, greens, blues, &numPixels);
  230.             }
  231.             else
  232.             {
  233.                 numPixels++;
  234.             }
  235.  
  236.             // 8. Bottom
  237.             if (r < height - 1)
  238.             {
  239.                 add_pixel(tmp[r+1][c], reds, greens, blues, &numPixels);
  240.             }
  241.             else
  242.             {
  243.                 numPixels++;
  244.             }
  245.  
  246.             // 9. Bottom right
  247.             if (r < height - 1 && c < width - 1)
  248.             {
  249.                 add_pixel(tmp[r+1][c+1], reds, greens, blues, &numPixels);
  250.             }
  251.             else
  252.             {
  253.                 numPixels++;
  254.             }
  255.  
  256.             // Get the convolutions of this pixel
  257.             RGBTRIPLE gx = get_convolution(reds, greens, blues, 'x');
  258.             RGBTRIPLE gy = get_convolution(reds, greens, blues, 'y');
  259.  
  260.             // Calculate the new pixel
  261.             RGBTRIPLE new_pixel = {0, 0, 0};
  262.             new_pixel.rgbtRed = clamp_value(sqrt(pow(gx.rgbtRed, 2) + pow(gy.rgbtRed, 2)));
  263.             new_pixel.rgbtGreen = clamp_value(sqrt(pow(gx.rgbtGreen, 2) + pow(gy.rgbtGreen, 2)));
  264.             new_pixel.rgbtBlue = clamp_value(sqrt(pow(gx.rgbtBlue, 2) + pow(gy.rgbtBlue, 2)));
  265.  
  266.             image[r][c] = new_pixel;
  267.         }
  268.     }
  269.  
  270.     // Clean up
  271.     free(tmp);
  272. }
  273.  
  274. int clamp_value(float val)
  275. {
  276.     // Max clamp = 255
  277.     if (val > 255)
  278.     {
  279.         val = 255;
  280.     }
  281.  
  282.     // Min clamp = 0
  283.     if (val < 0)
  284.     {
  285.         val = 0;
  286.     }
  287.  
  288.     // Integer rounding
  289.     return round(val);
  290. }
  291.  
  292. void add_pixel(RGBTRIPLE pixel, int reds[], int greens[], int blues[], int *numPixels)
  293. {
  294.     reds[*numPixels] = pixel.rgbtRed;
  295.     greens[*numPixels] = pixel.rgbtGreen;
  296.     blues[*numPixels] = pixel.rgbtBlue;
  297.     (*numPixels)++;
  298. }
  299.  
  300. RGBTRIPLE get_average_pixel(int reds[], int greens[], int blues[], int numPixels)
  301. {
  302.     float avgRed = 0.0;
  303.     float avgGreen = 0.0;
  304.     float avgBlue = 0.0;
  305.  
  306.     for (int i = 0; i < numPixels; i++)
  307.     {
  308.         avgRed += reds[i] / (float) numPixels;
  309.         avgGreen += greens[i] / (float) numPixels;
  310.         avgBlue += blues[i] / (float) numPixels;
  311.     }
  312.  
  313.     RGBTRIPLE result;
  314.  
  315.     result.rgbtRed = clamp_value(avgRed);
  316.     result.rgbtGreen = clamp_value(avgGreen);
  317.     result.rgbtBlue = clamp_value(avgBlue);
  318.  
  319.     return result;
  320. }
  321.  
  322. RGBTRIPLE get_convolution(int reds[], int greens[], int blues[], char type)
  323. {
  324.     int gx[9] = {-1, 0, 1,
  325.                  -2, 0, 2,
  326.                  -1, 0, 1};
  327.  
  328.     int gy[9] = {-1, -2, -1,
  329.                  0, 0, 0,
  330.                  1, 2, 1};
  331.  
  332.     RGBTRIPLE convolution = {0, 0, 0};
  333.  
  334.     // Ensure we have a valid value for `type`
  335.     if (type != 'x' && type != 'y')
  336.     {
  337.         printf("Invalid convolution type - should be 'x' or 'y'\n");
  338.         exit(1);
  339.     }
  340.  
  341.     // Do the convolution
  342.     if (type == 'x')
  343.     {
  344.         for (int i = 0; i < 9; i++)
  345.         {
  346.             convolution.rgbtRed += gx[i] * reds[i];
  347.             convolution.rgbtGreen += gx[i] * greens[i];
  348.             convolution.rgbtBlue += gx[i] * blues[i];
  349.         }
  350.     }
  351.     else if (type == 'y')
  352.     {
  353.         for (int i = 0; i < 9; i++)
  354.         {
  355.             convolution.rgbtRed += gy[i] * reds[i];
  356.             convolution.rgbtGreen += gy[i] * greens[i];
  357.             convolution.rgbtBlue += gy[i] * blues[i];
  358.         }
  359.     }
  360.  
  361.     return convolution;
  362. }
  363.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement