Friday, October 11, 2019

Reading A CSV Into An Array of Structs In C

So one of my assignments for my C class involves creating a struct and populating it. Of course, I did this over a month ago and needed a challenge. One thing that I was trying to do is create a CSV of 802 Pokemon whose name, attack, special attack, defense, special defense, speed, HP, primary type, and secondary type are all then loaded into an array of structs. I tried using fscanf for this, but couldn't figure out how to tokenize it. I couldn't figure out how to use strtok either, so I decided today was the day I was going to figure out strtok.

Now I didn't quite write my Pokemon code just yet. That particular code I want to be able to run averages based on type, classify a Pokemon as pseudolegendary based on the sum of its base stats, etc. But this struct project acted as a proof of concept of the reading a CSV into a struct array.

The CSV is the following set of values.

Name,Developer,1,Genre1,Genre2,Perspective,1,1,DevEngine,
Tetris,Alexey Pajitnov,1984,Puzzle,Strategy,Static,1,1,Various,
Beat Saber,Beat Games,2018,Rhythm,Null,VR,0,0,Unity,
Portal,Valve,2011,Puzzle,Platformer,FPV,0,0,Source,
Portal 2,Valve,2007,Puzzle,Platformer,FPV,0,0,Source,
Fallout: New Vegas,Obsidian,2010,FPS,RPG,FPV,0,0,Gamebryo,
140,Carlsen Games,2013,Platformer,Rhythm,Sidescroller,0,0,Unity,
Antichamber,Demruth,2013,Puzzle,Platformer,FPV,0,0,Unreal,
The Stanley Parable,Galactic Cafe,2013,Interactive,Null,FPV,0,0,Source,
Transistor,Supergiant Games,2014,RPG,Turn-based,TPV,0,0,Custom,
VVVVVV,Terry Cavanagh,2010,Platformer,Null,Sidescroller,0,0,Flash,
Paper Mario: The Thousand Year Door,Nintendo,2004,RPG,Turn-based,TPV,0,0,custom,
Luigi's Mansion,Nintendo,2001,RPG,Null,TPV,0,0,custom,

The first line has the names of the categories except where there were integers, just because I didn't want to risk there being an error thrown if a string were attempted to be read into an integer (although I'd imagine that'd just read its ASCII value).

The game list isn't ordered (except for the first 4, where they're my top favorite games of all time), but they're all my faves list.

My struct is as follows:


typedef struct faveGames_struct {
    char name[40]; //Game Name
    char developer[20]; //Game Dev
    int release; //Release Year
    char genre1[20]; //Primary Genre
    char genre2[20]; //Secondary Genre
    char perspective[20]; //FPS, Sidescroller, TPV, Top-Down, etc.
    int multiplayer; //0 = isn't multiplayer, 1 = is multiplayer
    int online; //0 = local play, 1 = online play
    char devEngine[30]; //Unity, Unreal, Source (Valve), etc.
} Game;

So I explain in the following video how I implement strtok to tokenize my CSV and populate an array of structs of type Game.


My actual code is as follows. It requires that you have the CSV saved in the same directory with the title "favegames.csv" by pasting it into Notepad, and when you Save As, set it to "All Files" instead of just .txt, and just save it as favegames.csv.

Save the struct as structdef.h, or remove the include statement and paste it straight into the main C file.

Here's my tokenizer into an array of structs!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "structdef.h"

int j = 1;

int main()
{
    FILE *myFile;
    myFile = fopen("favegames.csv", "r");

    if (myFile == NULL){
        printf("File did not successfully open. \n");
    }

    rewind(myFile);

    char myLine[200];
    fgets(myLine,1024,myFile);
    char* delimiter = ",";

    int i = 0;

    for (char c = getc(myFile); c != EOF; c=getc(myFile)){
        if (c == '\n'){
            j++;
        }
    }

    Game games[j+1];
    rewind(myFile);

     while(fgets(myLine,200, (FILE*)myFile) != NULL ){

        strcpy(games[i].name,strtok(myLine, delimiter));

        strcpy(games[i].developer, strtok(NULL, delimiter));


        games[i].release = atoi(strtok(NULL, delimiter));

        strcpy(games[i].genre1, strtok(NULL, delimiter));

        strcpy(games[i].genre2, strtok(NULL, delimiter));

        strcpy(games[i].perspective, strtok(NULL, delimiter));

        games[i].multiplayer = atoi(strtok(NULL, delimiter));

        games[i].online = atoi(strtok(NULL, delimiter));

        strcpy(games[i].devEngine, strtok(NULL, delimiter));

        i++;
    }

    fclose(myFile);

    FILE* binStruct = NULL;

    binStruct = fopen("binStruct.bin", "wb");
    if (binStruct == NULL){
        printf("Couldn't open binStruct.\n");
    }

    fwrite(games,sizeof(Game),j,binStruct);
    fclose(binStruct);

    searchStruct (games);
}

void searchStruct(Game games[j]){
char gameName[40];
printf("Enter a video game: ");
fgets(gameName,40,stdin);
int len = strlen(gameName);

if (gameName[len-1] == '\n'){
    gameName[len-1] = 0;
}


int i = 0;

for (int a = 0; a <= j; a++){
    if(strcmp(gameName,games[a].name) == 0){
       break;
    }
    else {
        if(a == j){
            printf("Invalid entry.");
        return;
        }
    }
    i++;

}


    printf("%s was made in %d by %s.\n", games[i].name, games[i].release, games[i].developer);
    if (strcmp(games[i].genre2, "Null") == 0){
        printf("It is a %s game.\n", games[i].genre1);
    }
    else {
        printf("It is a %s and %s game.\n", games[i].genre1, games[i].genre2);
    }
    if (strcmp(games[i].devEngine, "custom") == 0){
        printf("It was made using a custom-built game engine.\n");
    }
    else {
        printf("It was made using the %s game engine.\n", games[i].devEngine);
    }
    printf("It has a %s type of perspective.\n", games[i].perspective);
    if (games[i].multiplayer == 1){
        printf("It has multiplayer capabilities and ");
    }
    else {
        printf("It does not have multiplayer capabilities and ");
    }
    if (games[i].online == 1){
        printf("has online capabilities.\n\n");
    }
    else {
        printf("does not have online capabilities.\n\n");
    }
}

Sunday, October 6, 2019

C# / Unity First Project

About a week ago I decided to toy around with Unity. I didn't upload anything to my blog because I did it on the downstairs computer. This is the Unity Roll-A-Ball project. Now that PC doesn't have a microphone so I couldn't record a code explanation but I did record a quick video demonstrating my project.


A Sorting Algorithm Visualization in Processing

Here's just a quick project I did on my phone when I was bored. The video contains the source code, but it's a bit of a pain to get Processing code off of my phone, so I won't be pasting it here.

I did this about 4 days back though.


Image Processing In C

So my teacher wrote code that essentially read a .pgm graymap file and would write it back to a file. We had to define the matrix that held it, and wrote code that processed it. Me being me I went through all the options and did all of the options because I thought it'd be an interesting project that'd help my coding skills, and more than that, understanding what the actual code behind certain filters and processes in Photoshop are.

I wrote code to invert, threshold, change luminosity, rotate, reflect, frame, box blur, Gaussian blur, sharpen, and edge detect an image.

I tried to write code to change the contrast but I couldn't manage to do it in a reliable manner.

Here's the explanation of the code.
Resource to explain convolving/kernels


The first section of the code is all my teacher's work, except where I define the arrays, put a loop on the theImageArrayDup to duplicate the array, and call my imageProcessing code. Aside from that the rest of it is my code.


Here's Default Irv (my professor's kitty), for comparison

Default Irv

Convolution UI

Convolution is essentially the idea of taking one pixel, and manipulating it based on the surrounding pixels. You use a matrix to manipulate the pixel based on its surrounding pixels. Because accounting for the edge is too much work, I simply let my loops start at 1 instead of 0 to ignore the outermost pixels.

Convolve UI

Box Blur

It's hard to notice on the small image but it's there. If you do this in Photoshop with a 1px box blur, you'll get the exact same effect.

Box Blur

Gaussian Blur

Again, hard to notice on the small image but it's there. Oddly enough doing this in Photoshop with a 1px Gaussian blur does not give the same effect.

Gaussian Blur

Edge Detection

Works a little differently than that in Photoshop. But still picks up on edges fairly well. Does not threshold despite looking like it did.

Edge Detection

Sharpen

This one got a little screwy and ended up being washed out and otherwise looking like the edge detection algorithm.

Sharpen

Framing UI

Framing UI

Framing

Framing

Invert UI

This one is literally 3 lines of code, if you're feeling lazy.

Invert UI

Invert

Invert

Luminosity UI

Luminosity UI

Lighten

Lighten

Darken

Darken

Transform UI

Transform UI

Reflect Horizontal

Reflect Horizontal

Reflect Vertical

Reflect Horizontal

Rotate 90 Degrees Clockwise

Rotate 90 Degrees Clockwise

Rotate 180 Degrees Clockwise

Rotate 180 Degrees Clockwise

Rotate 270 Degrees Clockwise

Rotate 270 Degrees Clockwise

Threshold UI

I tried to make this flexible but couldn't manage to do it with flexible if statements so I just hard coded these cases, as after 6 levels, it doesn't make much of a difference anyway.

Threshold UI

Threshold Lv 2

Threshold Level 2

Threshold Lv 3

Threshold Level 3

Threshold Lv 4

Threshold Level 4

Threshold Lv 5

Threshold Level 5

Threshold Lv 6

Threshold Level 6


// Read a PGM-format file into an array
// PGM file format is documented here:
// http://en.wikipedia.org/wiki/Netpbm_format
//
// Here's a short example:
//
// P2
// # a comment line
// 24 7
// 3
// 0 0 0 0 1 1 1 0 0 0 2 2 2 2 0 0 0 0 3 3 3 3 3 0
// ... 6 more rows of pixel data
//
// The P2 means a gray-scale image
// Comment lines start with # and can be ignored
// 24 means 24 wide
// 7 means 7 high
// 3 means the maximum pixel value is 3 in this example

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

//typedef unsigned short int word ;
//typedef unsigned char byte ;

// Maximum size image we will process (larger ones
// get truncated to the upper left corner), or may "wrap"
// in interesting ways...
#define MAX_HEIGHT 1025
#define MAX_WIDTH 1025

// allows writing multiple pixels per line to the
// output PGM file.  Looks like many programs that
// use the PGM format just keep this at one.  It
// should not be more than 70 in any event.
#define MAX_PIXELS_PER_LINE 25

// Useful macro def
#define MIN( x, y ) ( ( x ) < ( y ) ? ( x ) : ( y ) )

// This is the array that will contain the image
// within your program.
//*** ????????????????????????????????


// You will need an identical  array to use to hold
// the output of your image transformation
//*** ????????????????????????????????

// ME DEFINING THEIMAGEARRAY

int theImageArray[1025][MAX_WIDTH];
int theImageArrayDup[1025][MAX_WIDTH];

// Internal function to read the header information
// stored at the beginning of a PGM format file.
//
// Used by read_pgm_file_into_array to see set the
// height and width of the image
FILE* read_pgm_file_info
(
    int* height,    // output
    int* width,    // output
    int* maxPixel,  // output
    char* pgmFname   // input
)
{
    static FILE* fp = 0L ;
    char pgmFormatFlag[3] =  { '\0' } ;

    char trash[80] = { '\0' } ;
    memset ( ( void * ) trash, '\0', 80 ) ;

    fp = fopen ( pgmFname, "r" ) ;

    if ( fp )
    {
        // Check the signature
        fscanf ( fp, "%2c\n", pgmFormatFlag ) ;
        //printf ( "%s\n", pgmFormatFlag ) ;
        if ( ! strcmp ( pgmFormatFlag, "P2" ) )
        {
            // Skip the comment line
            //fscanf ( fp, "\n" ) ;
            fgets (  trash, 70, fp ) ;
            //printf ( "%s", trash ) ;

            // Read the width
            fscanf ( fp, "%i", width ) ;
            //printf ( "%i,", *width ) ;

            // Read the height
            fscanf ( fp, "%i", height ) ;
            //printf ( "%i\n", *height ) ;

            // Read the maximum pixel value
            fscanf ( fp, "%i", maxPixel ) ;
        }
        //fclose ( fp ) ;
    }


    return fp ;
}

// Write out an array as a PGM file (ascii).
// writes imageArray to the file named by pgmOutFileName.
// commentLine, height, width, and maxPixel must be
// set and passed to this function so they can
// be written correctly in the PGM file header and
// so this function will know how many rows (image height)
// and how many columns (image width) to write.
void write_pgm_file_from_array
(
    char* pgmOutFileName,     // input
    int imageArray[][MAX_WIDTH], // input
    char* commentLine,      // input
    int height,          // input
    int width,          // input
    int maxPixel         // input
)
{
    int row = 0 ;
    int col = 0 ;
    FILE* fp = fopen ( pgmOutFileName, "w" ) ;
    if ( fp )
    {
        // Generate the header info
        fprintf ( fp, "P2\n" ) ;
        fprintf ( fp, "%s\n", commentLine ) ;
        fprintf ( fp, "%u %u\n", width, height ) ;
        fprintf ( fp, "%u\n", maxPixel ) ;

        // Now write out the data, ensuring that at most 70
        // values appear on each line, even if width is > 70
        for ( row = 0 ; row < height ; row ++ )
        {
            for ( col = 0 ; col < width ; col ++ )
            {
                fprintf ( fp, "%u", imageArray[row][col] ) ;
                // break up long rows into multiple lines as needed
                if ( MAX_PIXELS_PER_LINE > 1 )
                {
                    fprintf ( fp, " " ) ;
                }
                if ( ( col % MAX_PIXELS_PER_LINE ) == 0 )
                {
                    fprintf ( fp, "\n" ) ;
                }
            }
            // Watch out of special case of width == 70
            if ( col % MAX_PIXELS_PER_LINE )
            {
                fprintf ( fp, "\n" ) ;
            }
        }
        fclose ( fp ) ;
    }
    return ;
}

// Read file named by pgmInFileName argument into
// the array imageArray. This function respects the
// MAX_HEIGHT and MAX_WIDTH values, so if you declare
// your target array using these bounds, even reading
// a large image file should not blow up your program.
// (but you will only get the upper left-hand corner
// of the image).  Checks that the file read is a PGM
// (gray scale, ascii) file.
//
// Sets height, width, and maxPixel according to the
// header read.
void read_pgm_file_into_array
(
    int imageArray[][MAX_WIDTH],          // output
    int* height,        // output
    int* width,        // output
    int* maxPixel,              // output
    char* pgmInFileName      // input
)
{
    int row = 0 ;
    int col = 0 ;
    FILE* fp = read_pgm_file_info ( height, width, maxPixel, pgmInFileName ) ;
    char trash = ' ';
    char yesThreshold = ' ';

    if ( fp )
    {
        printf ( "reading height=%d, width=%d\n", *height, *width ) ;
        for ( row = 0 ; row < MIN( MAX_HEIGHT - 1, *height ) ; row ++ )
        {
            for ( col = 0 ; col < MIN( MAX_WIDTH -1, *width ) ; col ++ )
            {
                fscanf ( fp, "%i", &imageArray[row][col]) ;
            }
        }
        fclose ( fp ) ;
    }

    return ;
}

int main( void )
{
    int height  = 0 ;
    int width = 0 ;
    int maxPixel = 0 ;

    //char* pgmInFileName = "lynx_central.pgm" ;
    //char* pgmOutFileName = "lynx_central_out.pgm" ;
    char* pgmInFileName = "irv.pgm" ;
    char* pgmOutFileName = "irv_out.pgm" ;

    // Read input file into array, then write it back out,
    // just to prove this all works.  Input file and output
    // file should look just the same.  (sizes on disk might
    // vary slightly)
    read_pgm_file_into_array (theImageArray, &height, &width, &maxPixel, pgmInFileName ) ;

    //****
    //**** Your code to transform the image goes here ...
    for(int i = 0; i < 1025; i++){
        for(int j = 0; j < MAX_WIDTH; j++){
            theImageArrayDup[i][j] = theImageArray[i][j];
        }
    }
    imageProcessing(theImageArray, theImageArrayDup,height,width);

    //Transfer the current values in theImageArray back to disk
    write_pgm_file_from_array ( pgmOutFileName, theImageArray, "# JR test file", height, width,
                                maxPixel ) ;

    printf ( "Copying %s to %s, height=%u, width=%u, maxPixel=%d\n", pgmInFileName,
             pgmOutFileName,
             height, width, maxPixel ) ;

    //system("pause");
    return 0 ;
}

    #define MAX_HEIGHT 1025
    #define MAX_WIDTH 1025
    #include <stdio.h>
    #include <math.h>
    #include <string.h>


void convolve(int theImageArray[1025][1025], int theImageArrayDup[1025][1025], int height, int width){
    int boxBlur[3][3] = {
        { 1, 1, 1 },
        { 1,  1, 1 },
        { 1, 1, 1 }
    };

    int gaussian[3][3] = {
        {1, 2, 1},
        {2, 4, 2},
        {1, 2, 1}
    };
     int edgeDetect[3][3] = {
        {-1, -1, -1},
        {-1,  5, -1},
        {-1, -1, -1}
    };

    int sharpen[3][3] = {
        {0, -1,  0},
        {-1, 5, -1},
        {0, -1,  0}
    };


    char convolution[30];
    printf("Would you like to run box blur, Gaussian blur, edge detection, or sharpen?\n(Box, Gaussian, Edge, Sharpen) \n");
    scanf("%s", convolution);
    lowerletter(convolution);

    if(strcmp(convolution, "box") == 0){
        for (int i = 1; i < MAX_HEIGHT; i++) {
            for (int j = 1; j < MAX_WIDTH; j++) {
                conMatrixMult(theImageArray, theImageArrayDup, boxBlur, i, j, 9, 0);

            }
        }
    }
    if(strcmp(convolution, "gaussian") == 0){
        for (int i = 1; i < MAX_HEIGHT; i++) {
            for (int j = 1; j < MAX_WIDTH; j++) {
                conMatrixMult(theImageArray, theImageArrayDup, gaussian, i, j, 16, 0);

            }
        }
    }
    if(strcmp(convolution, "edge") == 0){
        for (int i = 1; i < MAX_HEIGHT; i++) {
            for (int j = 1; j < MAX_WIDTH; j++) {
                conMatrixMult(theImageArray, theImageArrayDup, edgeDetect, i, j, 128, 0);

            }
        }
    }
    if(strcmp(convolution, "sharpen") == 0){
        for (int i = 1; i < MAX_HEIGHT; i++) {
            for (int j = 1; j < MAX_WIDTH; j++) {
                conMatrixMult(theImageArray, theImageArrayDup, sharpen, i, j, 8, -50);
                /*if((2*theImageArray[i][j])<= 255){
                    theImageArray[i][j] = (2*theImageArray[i][j]);
                }
                else{
                    theImageArray[i][j] = 255;
                }*/
                theImageArray[i][j] = 2*(theImageArray[i][j] -50) + 100;
                if (theImageArray[i][j] > 255) {
                    theImageArray[i][j] = 255;
                }
            }

        }
    printf("Image is washed out, sorry. Couldn't figure out a way around that. It is sharpened though.");
    }
}

void conMatrixMult(int theImageArray[1025][1025], int theImageArrayDup[1025][1025], int myMatrix[3][3], int i, int j, int divisor, int subtractor){
     theImageArray[i][j] = (theImageArray[i+1][j+1]*myMatrix[0][0] + theImageArray[i][j+1]*myMatrix[0][1]+ theImageArray[i-1][j+1]*myMatrix[0][2]+theImageArray[i+1][j]*myMatrix[1][0]+theImageArray[i][j]*myMatrix[1][1]+theImageArray[i-1][j]*myMatrix[1][2]+theImageArray[i+1][j-1]*myMatrix[2][0]+theImageArray[i][j+1]*myMatrix[2][1]+theImageArray[i-1][j-1]*myMatrix[2][2])/divisor - subtractor;
}

void invert(int theImageArray[1025][1025]){
    for (int i = 1; i < MAX_HEIGHT; i++) {
        for (int j = 1; j < MAX_WIDTH; j++) {
              theImageArray[i][j] = 255 - theImageArray[i][j];
        }
    }

}

void threshold(int theImageArray[1025][1025]) {


    int n;
    printf("Enter the number of levels you wish to threshold by. \n(Integer between 2-6 inclusive). \n");
    scanf("%d", &n);

    for (int i = 0; i < MAX_HEIGHT; i++) {
        for (int j = 0; j < MAX_WIDTH; j++) {
            switch (n){

            case 1:
                printf("Invalid response. Please start over. /n");
                break;

            case 2:
                if (theImageArray[i][j] > (n-1)*255/n) {
                    theImageArray[i][j] = 255;
                }
                else {
                    theImageArray[i][j] = 0;
                }
                break;
            case 3:
                if (theImageArray[i][j] > (n-1)*255/n) {
                    theImageArray[i][j] = 255;
                }
                else if (theImageArray[i][j] > (n-2)*(255/n)){
                    theImageArray[i][j] = (n-2)*(255/n);
                }
                else {
                    theImageArray[i][j] = 0;
                }
                break;
            case 4:
                if (theImageArray[i][j] > (n-1)*255/n) {
                    theImageArray[i][j] = 255;
                }
                else if (theImageArray[i][j] > (n-2)*(255/n)){
                    theImageArray[i][j] = (n-2)*(255/n);
                }
                else if (theImageArray[i][j] > (n-3)*(255/n)){
                    theImageArray[i][j] = (n-3)*(255/n);
                }
                else {
                    theImageArray[i][j] = 0;
                }
                break;
            case 5:
                if (theImageArray[i][j] > (n-1)*255/n) {
                    theImageArray[i][j] = 255;
                }
                else if (theImageArray[i][j] > (n-2)*(255/n)){
                    theImageArray[i][j] = (n-2)*(255/n);
                }
                else if (theImageArray[i][j] > (n-3)*(255/n)){
                    theImageArray[i][j] = (n-3)*(255/n);
                }
                else if (theImageArray[i][j] > (n-4)*(255/n)){
                    theImageArray[i][j] = (n-4)*(255/n);
                }
                else {
                    theImageArray[i][j] = 0;
                }
                break;
            case 6:
                if (theImageArray[i][j] > (n-1)*255/n) {
                    theImageArray[i][j] = 255;
                }
                else if (theImageArray[i][j] > (n-2)*(255/n)){
                    theImageArray[i][j] = (n-2)*(255/n);
                }
                else if (theImageArray[i][j] > (n-3)*(255/n)){
                    theImageArray[i][j] = (n-3)*(255/n);
                }
                else if (theImageArray[i][j] > (n-4)*(255/n)){
                    theImageArray[i][j] = (n-4)*(255/n);
                }
                else if (theImageArray[i][j] > (n-5)*(255/n)){
                    theImageArray[i][j] = (n-5)*(255/n);
                }
                else {
                    theImageArray[i][j] = 0;
                }
                break;
            default:
                printf("Invalid response. Please start over. /n");
                break;
            }
        }
    }
}

void luminosity(int theImageArray[1025][1025]) {
    char lum[10];
    double perc;
    printf("Do you want to lighten or darken the image? (Lighten, Darken) \n");
    scanf("%s", lum);
    lowerletter(lum);

    printf("Enter a percentage between 0 and 100 (without the %%) of how much you want\nthe luminosity to change by. \n");
    scanf("%lf", &perc);
    perc = 0.01* perc;


    if(strcmp(lum, "lighten") == 0){
        perc = 1.0 + perc;

        for (int i = 0; i < MAX_HEIGHT; i++) {
            for (int j = 0; j < MAX_WIDTH; j++) {
                if(perc*theImageArray[i][j]<= 255){
                    theImageArray[i][j] = perc*theImageArray[i][j];
                }
                else{
                    theImageArray[i][j] = 255;
                }
            }
        }
    }

    if(strcmp(lum, "darken") == 0){
        perc = 1.0 - perc;

        for (int i = 0; i < MAX_HEIGHT; i++) {
            for (int j = 0; j < MAX_WIDTH; j++) {
                theImageArray[i][j] = perc*theImageArray[i][j];

            }
        }
    }
}

void frame(int theImageArray[1025][1025], int width, int height){
    int startPosX;
    int endPosX;
    int startPosY;
    int endPosY;
    int lum;

    printf("Enter leftmost X position (0-%d): ", width);
    scanf("%d", &startPosX);
    printf("\nEnter rightmost X position (0-%d): ", width);
    scanf("%d", &endPosX);
    printf("\nEnter topmost Y position (0-%d): ", height);
    scanf("%d", &startPosY);
    printf("\nEnter bottommost Y position (0-%d): ", height);
    scanf("%d", &endPosY);
    printf("\n");
    printf("Enter frame luminosity (0-255): ");
    scanf("%d", &lum);
    printf("\n");

    for(int i = 0; i < MAX_WIDTH; i++){
        for(int j = 0; j < startPosY; j++){
            theImageArray[i][j] = lum;
        }
    }
    for(int i = 0; i < startPosX; i++){
        for(int j = startPosY; j < MAX_HEIGHT; j++){
            theImageArray[i][j] = lum;
        }
    }
    for(int i = startPosX; i < endPosX; i++){
        for(int j = endPosY; j < MAX_HEIGHT; j++){
            theImageArray[i][j] = lum;
        }
    }
    for(int i = endPosX; i < MAX_WIDTH; i++){
        for(int j = startPosY; j < MAX_HEIGHT; j++){
            theImageArray[i][j] = lum;
        }
    }

}

void transformation(int theImageArray[1025][1025], int theImageArrayDup[1025][1025], int width, int height){
    char tfm[10];
    int rotation;
    printf("Do you want to rotate the image or reflect the image? (Rotate, Reflect) \n");
    scanf("%s", tfm);
    lowerletter(tfm);

    if (strcmp(tfm, "reflect") == 0) {
        printf("Do you want the image to be reflected vertically or horizontally?\n(Vertical, Horizontal)\n");
        char direction[15];
        scanf("%s", direction);
        lowerletter(direction);


        if(strcmp(direction, "vertical") == 0){
            for(int i = 0; i < width; i++){
                for(int j = 0; j < height; j++){
                    theImageArrayDup[i][j] = theImageArray[width-i][j];
                }
            }

            for(int i = 0; i < width; i++){
                for(int j = 0; j < height; j++){
                    theImageArray[i][j] = theImageArrayDup[i][j];
                }
            }
        }

        if(strcmp(direction,"horizontal") == 0){
            for(int i = 0; i < width; i++){
                for(int j = 0; j < height; j++){
                    theImageArrayDup[i][j] = theImageArray[i][height-j];
                }
            }

            for(int i = 0; i < width; i++){
                for(int j = 0; j < height; j++){
                    theImageArray[i][j] = theImageArrayDup[i][j];
                }
            }
        }
    }

    if(strcmp(tfm, "rotate") == 0) {
        printf("Do you want the image rotated 90, 180, or 270 degrees clockwise? ");
        scanf("%d", &rotation);

        if (rotation == 90){
            for(int i = 0; i < MAX_WIDTH; i++){
                for(int j = 0; j < MAX_HEIGHT; j++){
                    theImageArrayDup[i][j] = theImageArray[j][i];
                }
            }

            for(int i = 0; i < MAX_WIDTH; i++){
                for(int j = 0; j < MAX_HEIGHT; j++){
                    theImageArray[i][j] = theImageArrayDup[i][j];
                }
            }
        }

         if(rotation ==  180) {
             for(int i = 0; i < width; i++){
                for(int j = 0; j < height; j++){
                    theImageArrayDup[i][j] = theImageArray[width-i][height-j];
                }
            }

            for(int i = 0; i < width; i++){
                for(int j = 0; j < height; j++){
                    theImageArray[i][j] = theImageArrayDup[i][j];
                }
            }
        }

        if (rotation == 270){
            for(int i = 0; i < width; i++){
                for(int j = 0; j < height; j++){
                    theImageArrayDup[i][j] = theImageArray[height-j][i];
                }
            }

            for(int i = 0; i < width; i++){
                for(int j = 0; j < height; j++){
                    theImageArray[i][j] = theImageArrayDup[i][j];
                }
            }
        }
    }
}

#include <ctype.h>>
#include <stdio.h>
#include <stdlib.h>

void imageProcessing(int theImageArray[1025][1025], int theImageArrayDup[1025][1025], int height, int width) {
    char inputFunc[30];

    printf("Enter the function you wish to apply to your image. (Threshold, Luminosity,\nFraming, Transform, Convolve, Invert) \n");
    scanf("%s", inputFunc);
    lowerletter(inputFunc);

    if(strcmp(inputFunc,"invert") == 0) {
        invert(theImageArray);
    }

    if(strcmp(inputFunc,"convolve") == 0) {
        convolve(theImageArray, height, width);
    }

    if(strcmp(inputFunc, "threshold") == 0){
        threshold(theImageArray);
    }

    if(strcmp(inputFunc, "luminosity") == 0){
        luminosity(theImageArray);
    }

    if(strcmp(inputFunc, "framing") == 0){
        frame(theImageArray, height, width);
    }

    if(strcmp(inputFunc,"transform") == 0) {
        transformation(theImageArray, theImageArrayDup, height, width);
    }


    printf("\nDone\n");
}


void lowerletter(char myString[30]){
    for(int i = 0; i < strlen(myString); i++){
        myString[i] = tolower(myString[i]);
    }

}