+1 (315) 557-6473 

Process PPM Images And Perform Simple Graphic Manipulation Assignment Solutions.


Instructions

Objective
Write a C homework program to process PPM images and perform simple graphic manipulation.

Requirements and Specifications

Before you start working on the assignment, do the following:
mkdir hw7
cd hw7
cp ˜eecs10/hw7/PhotoLab.c ./
cp ˜eecs10/hw7/catalina.ppm ./
cp ˜eecs10/hw7/anteater.ppm ./
mkdir ˜/public_html/
chmod 755 ˜/public_html/
cp ˜eecs10/hw7/index.html ˜/public_html/
NOTE: Please execute the above setup commands only once before you start working on the assignment! Do not execute them after you start the implementation, otherwise your code will be overwritten!
The file PhotoLab.c is the template file where you get started. It provides the functions for image file reading and saving, test automation, as well as the DIP function prototypes and some variables. Please do not change the provided function prototypes or variable definitions. You are free to add more variables and functions to the program at the places indicated by provided comments.
The file catalina.ppm is the PPM image that we will use to test the DIP operations. Once a DIP operation is done, you can save the modified image. You will be prompted for a name of the image. The saved image name.ppm will be automatically converted to a JPEG image and sent to the folder public html in your home directory. You are then able to view your images in a web browser at: http://bondi.eecs.uci.edu/˜yourUCInetID/index.html,
where yourUCInetID is your UCI network ID. For a specific image, you may either click on the icon, or access it directly at this URL: http://bondi.eecs.uci.edu/˜yourUCInetID/name.jpg, where name is the basename of the image file.
NOTE: Each file you put into your public html directory will be publicly accessible! Make sure you do not put files there that you don’t want to share, i.e. do not put your source code into that directory.
Screenshots of output
Process PPM images and perform simple graphic manipulation in C languageProcess PPM images and perform simple graphic manipulation in C language 1
Source Code
#include
#include
#include
#include
/*** global definitions ***/
#define WIDTH 640 /* image width */
#define HEIGHT 480 /* image height */
#define SLEN 80 /* maximum length of file names */
/*** function declarations ***/
/* print a menu */
void PrintMenu(void);
/* read image from a file */
int LoadImage(const char fname[SLEN], unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT]);
/* save a processed image */
int SaveImage(const char fname[SLEN], unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT]);
/* change a color image to black & white */
void BlackNWhite(unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT]);
/* reverse image color */
void Negative(unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT]);
/* flip image horizontally */
void HFlip(unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT]);
/* mirror image horizontally */
void HMirror(unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT]);
/* Zoom into an image */
void Zoomin(unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT]);
/* sharpen the image */
void Sharpen(unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT]);
/* exchange R and G color channels */
void ExRG(unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT]);
/* add salt-and-pepper noise to image */
void AddNoise(unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT], int percentage);
/* add overlay image */
void Overlay(unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT]);
/* add a border to the image */
void AddBorder(unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT], int r, int g, int b, int bwidth);
/* Example: aging the photo */
void Aging(unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT]);
/* test all functions */
void AutoTest(unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT]);
int main(void)
{
    /* Two dimensional arrays to hold the current image data, */
    /* one array for each color component. */
    unsigned char R[WIDTH][HEIGHT];
    unsigned char G[WIDTH][HEIGHT];
    unsigned char B[WIDTH][HEIGHT];
    char fname[SLEN];
    float result;
    int choice;
    int r, g, b, w;
    /* Please replace the following code with proper menu with function calls for DIP operations */
    srand(time(0));
    choice = 0;
    while (choice != 14)
    {
        PrintMenu();
        scanf("%d", &choice);
        switch (choice)
        {
        case 1:
            printf("Please input the file name to load: ");
            scanf("%s", fname);
            LoadImage(fname, R, G, B);
            break;
        case 2:
            printf("Please input the file name to save: ");
            scanf("%s", fname);
            SaveImage(fname, R, G, B);
            break;
        case 3:
            BlackNWhite(R, G, B);
            break;
        case 4:
            Negative(R, G, B);
            break;
        case 5:
            HFlip(R, G, B);
            break;
        case 6:
            HMirror(R, G, B);
            break;
        case 7:
            Zoomin(R, G, B);
            break;
        case 8:
            Sharpen(R, G, B);
            break;
        case 9:
            ExRG(R, G, B);
            break;
        case 10:
            AddNoise(R, G, B, 20);
            break;
        case 11:
            Overlay(R, G, B);
            break;
        case 12:
            printf("Enter the R value of the border color(0 to 255): ");
            scanf("%d", &r);
            printf("Enter the G value of the border color(0 to 255): ");
            scanf("%d", &g);
            printf("Enter the B value of the border color(0 to 255): ");
            scanf("%d", &b);
            printf("Enter the width of the border: ");
            scanf("%d", &w);
            AddBorder(R, G, B, r, g, b, w);
            break;
        case 13:
            AutoTest(R, G, B);
            break;
        case 14:
            break;
        default:
            printf("wrong Input\n");
        }
    }
    /* End of replacing */
    return 0;
}
/* print a menu */
void PrintMenu(void)
{
    printf("----------------------------------------------\n");
    printf("1: Load a PPM image\n");
    printf("2: Save the image in PPM and JPEG format\n");
    printf("3: Change the image to black and white color\n");
    printf("4: Make a negative of the image\n");
    printf("5: Flip the image horizontally\n");
    printf("6: Mirror the image horizontally\n");
    printf("7: Zoom into the image\n");
    printf("8: Sharpen the image\n");
    printf("9: Exchange red and green color channels\n");
    printf("10: Add noise to an image\n");
    printf("11: Add overlay to an image\n");
    printf("12: Add border to an image\n");
    printf("13: Test all functions\n");
    printf("14: Exit\n");
    printf("----------------------------------------------\n");
    printf("Please make your choice: ");
}
int LoadImage(const char fname[SLEN], unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT])
{
    FILE *File;
    char Type[SLEN];
    int Width, Height, MaxValue;
    int x, y;
    char ftype[] = ".ppm";
    char fname_ext[SLEN + sizeof(ftype)];
    strcpy(fname_ext, fname);
    strcat(fname_ext, ftype);
    File = fopen(fname_ext, "r");
    if (!File)
    {
        printf("\nCannot open file \"%s\" for reading!\n", fname);
        return 1;
    }
    fscanf(File, "%79s", Type);
    if (Type[0] != 'P' || Type[1] != '6' || Type[2] != 0)
    {
        printf("\nUnsupported file format!\n");
        return 2;
    }
    fscanf(File, "%d", &Width);
    if (Width != WIDTH)
    {
        printf("\nUnsupported image width %d!\n", Width);
        return 3;
    }
    fscanf(File, "%d", &Height);
    if (Height != HEIGHT)
    {
        printf("\nUnsupported image height %d!\n", Height);
        return 4;
    }
    fscanf(File, "%d", &MaxValue);
    if (MaxValue != 255)
    {
        printf("\nUnsupported image maximum value %d!\n", MaxValue);
        return 5;
    }
    if ('\n' != fgetc(File))
    {
        printf("\nCarriage return expected!\n");
        return 6;
    }
    for (y = 0; y < HEIGHT; y++)
    {
        for (x = 0; x < WIDTH; x++)
        {
            R[x][y] = fgetc(File);
            G[x][y] = fgetc(File);
            B[x][y] = fgetc(File);
        }
    }
    if (ferror(File))
    {
        printf("\nFile error while reading from file!\n");
        return 7;
    }
    printf("%s was read successfully!\n", fname_ext);
    fclose(File);
    return 0;
}
int SaveImage(const char fname[SLEN], unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT])
{
    FILE *File;
    char ftype[] = ".ppm";
    char fname_ext[SLEN + sizeof(ftype)];
    char SysCmd[SLEN * 5];
    int x, y;
    strcpy(fname_ext, fname);
    strcat(fname_ext, ftype);
    File = fopen(fname_ext, "w");
    if (!File)
    {
        printf("\nCannot open file \"%s\" for writing!\n", fname);
        return 1;
    }
    fprintf(File, "P6\n");
    fprintf(File, "%d %d\n", WIDTH, HEIGHT);
    fprintf(File, "255\n");
    for (y = 0; y < HEIGHT; y++)
    {
        for (x = 0; x < WIDTH; x++)
        {
            fputc(R[x][y], File);
            fputc(G[x][y], File);
            fputc(B[x][y], File);
        }
    }
    if (ferror(File))
    {
        printf("\nFile error while writing to file!\n");
        return 2;
    }
    fclose(File);
    printf("%s was saved successfully. \n", fname_ext);
    /*
     * rename file to image.ppm, convert it to ~/public_html/.jpg
     * and make it world readable
     */
    sprintf(SysCmd, "~eecs10/bin/pnmtojpeg.tcsh %s", fname_ext);
    if (system(SysCmd) != 0)
    {
        printf("\nError while converting to JPG:\nCommand \"%s\" failed!\n", SysCmd);
        return 3;
    }
    printf("%s.jpg was stored for viewing. \n", fname);
    return 0;
}
/* Example: age the image to make it look like old picture */
void Aging(unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT])
{
    int x, y;
    for( y = 0; y < HEIGHT; y++ )
    {
        for( x = 0; x < WIDTH; x++ )
        {
            B[x][y] = ( R[x][y]+G[x][y]+B[x][y] )/5;
            R[x][y] = (unsigned char) (B[x][y]*1.6);
            G[x][y] = (unsigned char) (B[x][y]*1.6);
        }
    }
}
/* Test all functions */
void AutoTest(unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT])
{
    LoadImage("catalina", R, G, B);
    Aging(R, G, B);
    SaveImage("aging", R, G, B);
    printf("Aging tested!\n\n");
    /* add more tests here */
    LoadImage("catalina", R, G, B);
    BlackNWhite(R, G, B);
    SaveImage("bw", R, G, B);
    printf("Black & White tested!\n\n");
    LoadImage("catalina", R, G, B);
    Negative(R, G, B);
    SaveImage("negative", R, G, B);
    printf("Negative tested!\n\n");
    LoadImage("catalina", R, G, B);
    HFlip(R, G, B);
    SaveImage("hflip", R, G, B);
    printf("HFlip tested!\n\n");
    LoadImage("catalina", R, G, B);
    HMirror(R, G, B);
    SaveImage("hmirror", R, G, B);
    printf("HMirror tested!\n\n");
    LoadImage("catalina", R, G, B);
    Zoomin(R, G, B);
    SaveImage("zoomin", R, G, B);
    printf("Zoom tested!\n\n");
    LoadImage("catalina", R, G, B);
    Sharpen(R, G, B);
    SaveImage("sharpen", R, G, B);
    printf("Sharpen tested!\n\n");
    LoadImage("catalina", R, G, B);
    ExRG(R, G, B);
    SaveImage("xRG", R, G, B);
    printf("Exchange RG tested!\n\n");
    LoadImage("catalina", R, G, B);
    AddNoise(R, G, B, 20);
    SaveImage("noise", R, G, B);
    printf("Add noise tested!\n\n");
    LoadImage("catalina", R, G, B);
    Overlay(R, G, B);
    SaveImage("overlay", R, G, B);
    printf("Add overlay tested!\n\n");
    LoadImage("catalina", R, G, B);
    AddBorder(R, G, B, 0, 0, 0, 20);
    SaveImage("border", R, G, B);
    printf("Add Border tested!\n\n");
}
/* change a color image to black & white */
void BlackNWhite(unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT])
{
    int row, col;
    unsigned intensity;
    for (col = 0; col < WIDTH; col++)
        for (row = 0; row < HEIGHT; row++)
        {
            intensity = (R[col][row] + G[col][row] + B[col][row]) / 3;
            R[col][row] = intensity;
            G[col][row] = intensity;
            B[col][row] = intensity;
        }
    printf("\"Black & White\" operation is done!\n");
}
/* reverse image color */
void Negative(unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT])
{
    int row, col;
    for (col = 0; col < WIDTH; col++)
        for (row = 0; row < HEIGHT; row++)
        {
            R[col][row] = 255 - R[col][row];
            G[col][row] = 255 - G[col][row];
            B[col][row] = 255 - B[col][row];
        }
    printf("\"Negative\" operation is done!\n");
}
/* flip image horizontally */
void HFlip(unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT])
{
    int row, col;
    unsigned color;
    for (col = 0; col < WIDTH / 2; col++)
        for (row = 0; row < HEIGHT; row++)
        {
            color = R[col][row];
            R[col][row] = R[WIDTH - 1 - col][row];
            R[WIDTH - 1 - col][row] = color;
            color = G[col][row];
            G[col][row] = G[WIDTH - 1 - col][row];
            G[WIDTH - 1 - col][row] = color;
            color = B[col][row];
            B[col][row] = B[WIDTH - 1 - col][row];
            B[WIDTH - 1 - col][row] = color;
        }
    printf("\"HFlip\" operation is done!\n");
}
/* mirror image horizontally */
void HMirror(unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT])
{
    int row, col;
    unsigned color;
    for (col = 0; col < WIDTH / 2; col++)
        for (row = 0; row < HEIGHT; row++)
        {
            R[WIDTH - 1 - col][row] = R[col][row];
            G[WIDTH - 1 - col][row] = G[col][row];
            B[WIDTH - 1 - col][row] = B[col][row];
        }
    printf("\"HMirror\" operation is done!\n");
}
/* Zoom into an image */
void Zoomin(unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT])
{
    unsigned char RT[WIDTH][HEIGHT];
    unsigned char GT[WIDTH][HEIGHT];
    unsigned char BT[WIDTH][HEIGHT];
    int row, col;
    int r, c;
    for (c = 0, col = 160; col <= 479; col++, c += 2)
        for (r = 0, row = 120; row <= 359; row++, r += 2)
        {
            RT[c][r] = R[col][row];
            RT[c + 1][r] = R[col][row];
            RT[c][r + 1] = R[col][row];
            RT[c + 1][r + 1] = R[col][row];
            GT[c][r] = G[col][row];
            GT[c + 1][r] = G[col][row];
            GT[c][r + 1] = G[col][row];
            GT[c + 1][r + 1] = G[col][row];
            BT[c][r] = B[col][row];
            BT[c + 1][r] = B[col][row];
            BT[c][r + 1] = B[col][row];
            BT[c + 1][r + 1] = B[col][row];
        }
    for (col = 0; col < WIDTH; col++)
        for (row = 0; row < HEIGHT; row++)
        {
            R[col][row] = RT[col][row];
            G[col][row] = GT[col][row];
            B[col][row] = BT[col][row];
        }
    printf("\"Zoom\" operation is done!\n");
}
/* sharpen the image */
void Sharpen(unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT])
{
    unsigned char RT[WIDTH][HEIGHT];
    unsigned char GT[WIDTH][HEIGHT];
    unsigned char BT[WIDTH][HEIGHT];
    int row, col;
    int r, c;
    int intensityR, intensityG, intensityB;
    int filter[3][3] = {{ -1, -1, -1}, { -1, 9, -1}, { -1, -1, -1}};
    for (col = 0; col < WIDTH; col++)
        for (row = 0; row < HEIGHT; row++)
        {
            intensityR = 0;
            intensityG = 0;
            intensityB = 0;
            for (c = -1; c <= 1; c++)
                for (r = -1; r <= 1; r++)
                {
                    intensityR += R[col + c][row + r] * filter[c + 1][r + 1];
                    intensityG += G[col + c][row + r] * filter[c + 1][r + 1];
                    intensityB += B[col + c][row + r] * filter[c + 1][r + 1];
                }
            if (intensityR < 0)
                intensityR = 0;
            else if (intensityR > 255)
                intensityR = 255;
            if (intensityG < 0)
                intensityG = 0;
            else if (intensityG > 255)
                intensityG = 255;
            if (intensityB < 0)
                intensityB = 0;
            else if (intensityB > 255)
                intensityB = 255;
            RT[col][row] = intensityR;
            GT[col][row] = intensityG;
            BT[col][row] = intensityB;
        }
    for (col = 0; col < WIDTH; col++)
        for (row = 0; row < HEIGHT; row++)
        {
            R[col][row] = RT[col][row];
            G[col][row] = GT[col][row];
            B[col][row] = BT[col][row];
        }
    printf("\"Sharpen\" operation is done!\n");
}
/* exchange R and G color channels */
void ExRG(unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT])
{
    int row, col;
    int intensity;
    for (col = 0; col < WIDTH; col++)
        for (row = 0; row < HEIGHT; row++)
        {
            intensity = R[col][row];
            R[col][row] = G[col][row];
            G[col][row] = intensity;
        }
    printf("\"Exchange RG\" operation is done!\n");
}
/* add salt-and-pepper noise to image */
void AddNoise(unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT], int percentage)
{
    int npixels;
    int pixel;
    int row, col;
    unsigned intensity;
    npixels = percentage * WIDTH * HEIGHT / 100;
    for (pixel = 0; pixel < npixels; pixel++)
    {
        col = rand() % WIDTH;
        row = rand() % HEIGHT;
        intensity = rand() & 1;
        R[col][row] = intensity * 255;
        G[col][row] = intensity * 255;
        B[col][row] = intensity * 255;
    }
    printf("\"Add noise\" operation is done!\n");
}
/* add overlay image */
void Overlay(unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT])
{
    unsigned char RT[WIDTH][HEIGHT];
    unsigned char GT[WIDTH][HEIGHT];
    unsigned char BT[WIDTH][HEIGHT];
    int row, col;
    LoadImage("anteater", RT, GT, BT);
    for (col = 0; col < WIDTH; col++)
        for (row = 0; row < HEIGHT; row++)
        {
            if (RT[col][row] != 255 || GT[col][row] != 255 || BT[col][row] != 255)
            {
                R[col][row] = RT[col][row];
                G[col][row] = GT[col][row];
                B[col][row] = BT[col][row];
            }
        }
    printf("\"Add overlay\" operation is done!\n");
}
/* add a border to the image */
void AddBorder(unsigned char R[WIDTH][HEIGHT], unsigned char G[WIDTH][HEIGHT], unsigned char B[WIDTH][HEIGHT], int r, int g, int b, int bwidth)
{
    int row, col;
    unsigned intensity;
    for (col = 0; col < WIDTH; col++)
        for (row = 0; row < bwidth; row++)
        {
            R[col][row] = r;
            G[col][row] = g;
            B[col][row] = b;
            R[col][row + HEIGHT - bwidth] = r;
            G[col][row + HEIGHT - bwidth] = g;
            B[col][row + HEIGHT - bwidth] = b;
        }
    for (col = 0; col < bwidth; col++)
        for (row = bwidth; row < HEIGHT - bwidth; row++)
        {
            R[col][row] = r;
            G[col][row] = g;
            B[col][row] = b;
            R[col + WIDTH - bwidth][row] = r;
            G[col + WIDTH - bwidth][row] = g;
            B[col + WIDTH - bwidth][row] = b;
        }
    printf("\"Add Border\" operation is done!\n");
}