#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/*
- Troy Muehlhausen
- tjmuehlh
- This program reads a text file and reads its content, converting that content
- into generated "ASCII Art." It is capable of executing point, rectangle, line,
- and fill commands.
*/
// Function to initialize the image with default color
void initImage(int width, int height, double image[width][height]) {
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
image[x][y] = 0.0;
}
}
}
// Function to print the image as ASCII art
void printImage(int width, int height, double image[width][height]) {
// Top row border
printf("+");
for (int x = 0; x <width; x++) {
printf("-");
}
printf("+\n");
// Middle rows, including both image and right and left borders
for (int y = 0; y < height; y++) {
printf("|");
for (int x = 0; x < width; x++) {
char pixelChar;
// Determine the character based on the color value
double color = image[x][y];
int range = (int)(color * 10);
switch (range) {
case 0: pixelChar = ' '; break;
case 1: pixelChar = '.'; break;
case 2: pixelChar = ':'; break;
case 3: pixelChar = '-'; break;
case 4: pixelChar = '='; break;
case 5: pixelChar = '+'; break;
case 6: pixelChar = '*'; break;
case 7: pixelChar = '#'; break;
case 8: pixelChar = '%'; break;
default: pixelChar = '@'; break;
}
printf("%c", pixelChar);
}
printf("|\n");
}
// Bottom row border
printf("+");
for (int x = 0; x < width; x++) {
printf("-");
}
printf("+\n");
}
// Function to draw a point at the specified location with the specified color
void drawPoint(int width, int height, double image[width][height],
int x, int y, double color) {
if (x >= 0 && x < width && y >= 0 && y < height) { // Check bounds
image[x][y] = color;
}
}
// Function to draw a filled rectangle
void drawRectangle(int width, int height, double image[width][height],
int left, int top, int rectangleWidth, int rectangleHeight, double color) {
for (int x = left; x < left + rectangleWidth; x++) {
for (int y = top; y < top + rectangleHeight; y++) {
drawPoint(width, height, image, x, y, color); // Checking for bounds is done within drawPoint already
}
}
}
// Function to draw a line using DDA algorithm
void drawLine(int width, int height, double image[width][height],
int x1, int y1, int x2, int y2, double color) {
int dx = abs(x2 - x1);
int dy = abs(y2 - y1);
int steps = dx > dy ? dx : dy;
// I like to think of this as finding the slope of the line function (i.e. 1/4x is a line where 1/4 is the slope)
double xIncrement = (double)(x2 - x1) / steps;
double yIncrement = (double)(y2 - y1) / steps;
double x = x1;
double y = y1;
// Incrementing by the "slope" we found earlier between pixels results in a pretty convincing line!
// (i.e. moving across 1 and up 4 for last example)
for (int i = 0; i <= steps; i++) {
drawPoint(width, height, image, round(x), round(y), color);
x += xIncrement;
y += yIncrement;
}
}
// Function to calculate image statistics
void getImageStats(int width, int height, double image[width][height],
double *minColor, double *maxColor, double *avgColor) {
*minColor = 1.0; // Initialize minColor to maximum value
*maxColor = 0.0; // Initialize maxColor to minimum value
double totalColor = 0.0;
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
double color = image[x][y];
totalColor += color;
if (color < *minColor) {
*minColor = color;
}
if (color > *maxColor) {
*maxColor = color;
}
}
}
*avgColor = totalColor / (width * height);
}
// Function to "flood fill" an area
void floodFill(int width, int height, double image[width][height], int x, int y, double color) {
if (x < 0 || x >= width || y < 0 || y >= height) {
return; // Outside the image bounds
}
if (image[x][y] >= color) {
return; // Stop if the current pixel is darker or equal to the fill color
}
image[x][y] = color; // Fill the current pixel
// Recursive flood fill in all four directions
floodFill(width, height, image, x + 1, y, color);
floodFill(width, height, image, x - 1, y, color);
floodFill(width, height, image, x, y + 1, color);
floodFill(width, height, image, x, y - 1, color);
}
// Print the resulting greyscale image as ASCII art.
int main(void)
{
// Read in the size of the drawing canvas
int width = 0;
int height = 0;
// Read the width and height
int result = scanf("%d %d", &width, &height);
// Program only supports images that are 1x1 or bigger
if ((width <= 0) || (height <= 0) || (result != 2))
{
printf("Failed to read a valid width and height from standard input!\n");
return 0;
}
// Create the 2D array and initialize all the greyscale values to 0.0
double image[width][height];
initImage(width, height, image);
char command = '\0';
double color = 0.0;
// Keep reading in drawing commands until we reach the end of the input
while (scanf(" %c", &command) == 1) {
switch (command) {
case 'p': {
// Draw a point, read in: x, y, color
int x = 0;
int y = 0;
// Read point parameters
result = scanf("%d %d %lf", &x, &y, &color);
if (result != 3) {
printf("Invalid point command!\n");
return 0;
}
drawPoint(width, height, image, x, y, color);
break;
}
case 'r': {
// Draw a rectangle, read in: x, y, w, h, color
int left = 0;
int top = 0;
int rectangleWidth = 0;
int rectangleHeight = 0;
// Read rectangle parameters
result = scanf("%d %d %d %d %lf", &left, &top, &rectangleWidth, &rectangleHeight, &color);
if (result != 5) {
printf("Invalid rectangle command!\n");
return 0;
}
drawRectangle(width, height, image, left, top, rectangleWidth, rectangleHeight, color);
break;
}
case 'l': {
// Draw a line, read in x1, y1, x2, y2, color
int x1 = 0;
int y1 = 0;
int x2 = 0;
int y2 = 0;
// Read line parameters
result = scanf("%d %d %d %d %lf", &x1, &y1, &x2, &y2, &color);
if (result != 5) {
printf("Invalid line command!\n");
return 0;
}
drawLine(width, height, image, x1, y1, x2, y2, color);
break;
}
case 'f': {
// Flood fill a color in, read in: x, y, color
int x = 0;
int y = 0;
// Read fill parameters
result = scanf("%d %d %lf", &x, &y, &color);
if (result != 3) {
printf("Invalid flood fill command!\n");
return 0;
}
floodFill(width, height, image, x, y, color);
break;
}
default: {
printf("Unknown command!\n");
return 0;
}
}
}
// Print the final image
printImage(width, height, image);
// Finally display some statistics about the image
double minColor = 0.0;
double maxColor = 0.0;
double avgColor = 0.0;
getImageStats(width, height, image, &minColor, &maxColor, &avgColor);
printf("Color range [%.2f, %.2f], average %.4f\n", minColor, maxColor, avgColor);
}
To embed this project on your website, copy the following code and paste it into your website's HTML: