Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <math.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include "helpers.h"
- int clamp_value(float val);
- void add_pixel(RGBTRIPLE pixel, int reds[], int greens[], int blues[], int *numPixels);
- RGBTRIPLE get_average_pixel(int reds[], int greens[], int blues[], int numPixels);
- RGBTRIPLE get_convolution(int reds[], int greens[], int blues[], char type);
- // Convert image to grayscale
- void grayscale(int height, int width, RGBTRIPLE image[height][width])
- {
- for (int r = 0; r < height; r++)
- {
- for (int c = 0; c < width; c++)
- {
- // Get initial pixel values
- int red = image[r][c].rgbtRed;
- int green = image[r][c].rgbtGreen;
- int blue = image[r][c].rgbtBlue;
- // Get average value
- int avg = clamp_value((red + green + blue) / 3.0);
- // Set this pixel's colors to the average
- image[r][c].rgbtRed = avg;
- image[r][c].rgbtGreen = avg;
- image[r][c].rgbtBlue = avg;
- }
- }
- }
- // Reflect image horizontally
- void reflect(int height, int width, RGBTRIPLE image[height][width])
- {
- // Create a temporary row to store the flipped values in
- RGBTRIPLE *row = calloc(width, sizeof(RGBTRIPLE));
- for (int r = 0; r < height; r++)
- {
- // Store the current row in the temp row
- memcpy(row, image[r], width * sizeof(RGBTRIPLE));
- // Flip the temp and stick it in the original row
- for (int c = 0; c < width; c++)
- {
- image[r][c].rgbtRed = row[width - c - 1].rgbtRed;
- image[r][c].rgbtGreen = row[width - c - 1].rgbtGreen;
- image[r][c].rgbtBlue = row[width - c - 1].rgbtBlue;
- }
- }
- }
- // Blur image
- void blur(int height, int width, RGBTRIPLE image[height][width])
- {
- // Copy the image
- RGBTRIPLE(*tmp)[width] = calloc(height, width * sizeof(RGBTRIPLE));
- memcpy(tmp, image, height * width * sizeof(RGBTRIPLE));
- // Create arrays to store the color values of each neighboring pixel
- int numPixels = 0;
- int reds[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
- int greens[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
- int blues[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
- for (int r = 0; r < height; r++)
- {
- for (int c = 0; c < width; c++)
- {
- // Zero out garbage values in the color arrays
- numPixels = 0;
- for (int i = 0; i < 9; i++) {reds[i] = 0;}
- for (int i = 0; i < 9; i++) {greens[i] = 0;}
- for (int i = 0; i < 9; i++) {blues[i] = 0;}
- // Add pixels to average
- // 1. Top left
- if (r > 0 && c > 0)
- {
- add_pixel(tmp[r-1][c-1], reds, greens, blues, &numPixels);
- }
- // 2. Top center
- if (r > 0)
- {
- add_pixel(tmp[r-1][c], reds, greens, blues, &numPixels);
- }
- // 3. Top right
- if (r > 0 && c < width - 1)
- {
- add_pixel(tmp[r-1][c+1], reds, greens, blues, &numPixels);
- }
- // 4. Left
- if (c > 0)
- {
- add_pixel(tmp[r][c-1], reds, greens, blues, &numPixels);
- }
- // 5. Center
- add_pixel(tmp[r][c], reds, greens, blues, &numPixels);
- // 6. Right
- if (c < width - 1)
- {
- add_pixel(tmp[r][c+1], reds, greens, blues, &numPixels);
- }
- // 7. Bottom left
- if (r < height - 1 && c > 0)
- {
- add_pixel(tmp[r+1][c-1], reds, greens, blues, &numPixels);
- }
- // 8. Bottom
- if (r < height - 1)
- {
- add_pixel(tmp[r+1][c], reds, greens, blues, &numPixels);
- }
- // 9. Bottom right
- if (r < height - 1 && c < width - 1)
- {
- add_pixel(tmp[r+1][c+1], reds, greens, blues, &numPixels);
- }
- // Set the current pixel to the average
- RGBTRIPLE avg = get_average_pixel(reds, greens, blues, numPixels);
- image[r][c] = avg;
- }
- }
- // Clean up
- free(tmp);
- }
- // Detect edges
- void edges(int height, int width, RGBTRIPLE image[height][width])
- {
- // Make a copy of the original
- RGBTRIPLE(*tmp)[width] = calloc(height, width * sizeof(RGBTRIPLE));
- memcpy(tmp, image, height * width * sizeof(RGBTRIPLE));
- // Create arrays to store the color values of each neighboring pixel
- int numPixels = 0;
- int reds[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
- int greens[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
- int blues[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
- for (int r = 0; r < height; r++)
- {
- for (int c = 0; c < width; c++)
- {
- // Zero out garbage values in the color arrays
- numPixels = 0;
- for (int i = 0; i < 9; i++) {reds[i] = 0;}
- for (int i = 0; i < 9; i++) {greens[i] = 0;}
- for (int i = 0; i < 9; i++) {blues[i] = 0;}
- // Add pixels to average
- // 1. Top left
- if (r > 0 && c > 0)
- {
- add_pixel(tmp[r-1][c-1], reds, greens, blues, &numPixels);
- }
- else
- {
- // By simply incrementing the counter, we add a black pixel to the list
- numPixels++;
- }
- // 2. Top center
- if (r > 0)
- {
- add_pixel(tmp[r-1][c], reds, greens, blues, &numPixels);
- }
- else
- {
- numPixels++;
- }
- // 3. Top right
- if (r > 0 && c < width - 1)
- {
- add_pixel(tmp[r-1][c+1], reds, greens, blues, &numPixels);
- }
- else
- {
- numPixels++;
- }
- // 4. Left
- if (c > 0)
- {
- add_pixel(tmp[r][c-1], reds, greens, blues, &numPixels);
- }
- else
- {
- numPixels++;
- }
- // 5. Center
- add_pixel(tmp[r][c], reds, greens, blues, &numPixels);
- // 6. Right
- if (c < width - 1)
- {
- add_pixel(tmp[r][c+1], reds, greens, blues, &numPixels);
- }
- else
- {
- numPixels++;
- }
- // 7. Bottom left
- if (r < height - 1 && c > 0)
- {
- add_pixel(tmp[r+1][c-1], reds, greens, blues, &numPixels);
- }
- else
- {
- numPixels++;
- }
- // 8. Bottom
- if (r < height - 1)
- {
- add_pixel(tmp[r+1][c], reds, greens, blues, &numPixels);
- }
- else
- {
- numPixels++;
- }
- // 9. Bottom right
- if (r < height - 1 && c < width - 1)
- {
- add_pixel(tmp[r+1][c+1], reds, greens, blues, &numPixels);
- }
- else
- {
- numPixels++;
- }
- // Get the convolutions of this pixel
- RGBTRIPLE gx = get_convolution(reds, greens, blues, 'x');
- RGBTRIPLE gy = get_convolution(reds, greens, blues, 'y');
- // Calculate the new pixel
- RGBTRIPLE new_pixel = {0, 0, 0};
- new_pixel.rgbtRed = clamp_value(sqrt(pow(gx.rgbtRed, 2) + pow(gy.rgbtRed, 2)));
- new_pixel.rgbtGreen = clamp_value(sqrt(pow(gx.rgbtGreen, 2) + pow(gy.rgbtGreen, 2)));
- new_pixel.rgbtBlue = clamp_value(sqrt(pow(gx.rgbtBlue, 2) + pow(gy.rgbtBlue, 2)));
- image[r][c] = new_pixel;
- }
- }
- // Clean up
- free(tmp);
- }
- int clamp_value(float val)
- {
- // Max clamp = 255
- if (val > 255)
- {
- val = 255;
- }
- // Min clamp = 0
- if (val < 0)
- {
- val = 0;
- }
- // Integer rounding
- return round(val);
- }
- void add_pixel(RGBTRIPLE pixel, int reds[], int greens[], int blues[], int *numPixels)
- {
- reds[*numPixels] = pixel.rgbtRed;
- greens[*numPixels] = pixel.rgbtGreen;
- blues[*numPixels] = pixel.rgbtBlue;
- (*numPixels)++;
- }
- RGBTRIPLE get_average_pixel(int reds[], int greens[], int blues[], int numPixels)
- {
- float avgRed = 0.0;
- float avgGreen = 0.0;
- float avgBlue = 0.0;
- for (int i = 0; i < numPixels; i++)
- {
- avgRed += reds[i] / (float) numPixels;
- avgGreen += greens[i] / (float) numPixels;
- avgBlue += blues[i] / (float) numPixels;
- }
- RGBTRIPLE result;
- result.rgbtRed = clamp_value(avgRed);
- result.rgbtGreen = clamp_value(avgGreen);
- result.rgbtBlue = clamp_value(avgBlue);
- return result;
- }
- RGBTRIPLE get_convolution(int reds[], int greens[], int blues[], char type)
- {
- int gx[9] = {-1, 0, 1,
- -2, 0, 2,
- -1, 0, 1};
- int gy[9] = {-1, -2, -1,
- 0, 0, 0,
- 1, 2, 1};
- RGBTRIPLE convolution = {0, 0, 0};
- // Ensure we have a valid value for `type`
- if (type != 'x' && type != 'y')
- {
- printf("Invalid convolution type - should be 'x' or 'y'\n");
- exit(1);
- }
- // Do the convolution
- if (type == 'x')
- {
- for (int i = 0; i < 9; i++)
- {
- convolution.rgbtRed += gx[i] * reds[i];
- convolution.rgbtGreen += gx[i] * greens[i];
- convolution.rgbtBlue += gx[i] * blues[i];
- }
- }
- else if (type == 'y')
- {
- for (int i = 0; i < 9; i++)
- {
- convolution.rgbtRed += gy[i] * reds[i];
- convolution.rgbtGreen += gy[i] * greens[i];
- convolution.rgbtBlue += gy[i] * blues[i];
- }
- }
- return convolution;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement