2

I have to write a program where I take user input for a PPM image and then mirror the image from left to right (basically flipping it over the y-axis). So if the image was <, the new image would now be >. This should not be a 180 degree rotation, as that would make the image upside down. It should still be the same, just reflected.

I have the code here that I used to input and output the PPM, but I don't know how to mirror it. I made a function that would theoretically be used for the mirror code, but I'm not sure if that's the best way to do it either. If you know a better place to put the code, be my guest.

I have researched this topic quite a bit, but was only able to find issues where people needed to rotate the image.

Here is what I have so far:

#include<stdio.h>
#include<stdlib.h> //for fopen()

typedef struct {
     unsigned char red,green,blue;
} pixel_t; //struct for pixels

typedef struct {
     int x, y;
     pixel_t *data;
} PPMImage; //struct for creating the image

#define RGB_COMPONENT_COLOR 255

static PPMImage *readPPM(const char *filename)
{
     char buff[16];
     PPMImage *img;
     FILE *fp;
     int c, rgb_comp_color;

     fp = fopen(filename, "rb");
     if (!fp) {
         fprintf(stderr, "Unable to open file '%s'\n", filename);
         exit(1);} //opens the ppm and checks to make sure it can be opened

     if (!fgets(buff, sizeof(buff), fp)) {
         perror(filename);
         exit(1);} //read the format of the image

    if (buff[0] != 'P' || buff[1] != '6') {
         fprintf(stderr, "Invalid image format (must be 'P6')\n");
         exit(1);} //checks to see if the format is ppm

    img = (PPMImage *)malloc(sizeof(PPMImage));
    if (!img) {
         fprintf(stderr, "Unable to allocate memory\n");
         exit(1);} //allocates the memory needed to form the input image

    c = getc(fp);
    while (c == '#') {
    while (getc(fp) != '\n') ;
         c = getc(fp);
    }//checks for comments

    ungetc(c, fp);

    if (fscanf(fp, "%d %d", &img->x, &img->y) != 2) {
         fprintf(stderr, "Invalid image size (error loading '%s')\n", filename);
         exit(1);} //reads the size of the image, height becomes img->y, and width becomes img->x

    if (fscanf(fp, "%d", &rgb_comp_color) != 1) {
         fprintf(stderr, "Invalid rgb component (error loading '%s')\n", filename);
         exit(1);} //reads how much of each color there is

    if (rgb_comp_color!= RGB_COMPONENT_COLOR) {
         fprintf(stderr, "'%s' does not have 8-bits components\n", filename);
         exit(1);} //makes sure the the component is 8 bits

    while (fgetc(fp) != '\n') ;

    img->data = (pixel_t*)malloc(img->x * img->y * sizeof(pixel_t));

    if (!img) {
         fprintf(stderr, "Unable to allocate memory\n");
         exit(1);} //allocates the memory need for the pixel data

    if (fread(img->data, 3 * img->x, img->y, fp) != img->y) {
         fprintf(stderr, "Error loading image '%s'\n", filename);
         exit(1);} //reads the pixel data

    fclose(fp);
    return img;
}
void writePPM(const char *filename, PPMImage *img)
{
    FILE *fp;

    fp = fopen(filename, "wb");
    if (!fp) {
         fprintf(stderr, "Unable to open file '%s'\n", filename);
         exit(1);} //opens the file for output

    //write the header file
    //image format
    fprintf(fp, "P6\n");

    //image size
    fprintf(fp, "%d %d\n",img->x,img->y);

    // rgb component depth
    fprintf(fp, "%d\n",RGB_COMPONENT_COLOR);

    // pixel data
    fwrite(img->data, 3 * img->x, img->y, fp);
    fclose(fp);
}

void mirror(PPMImage *img)
{

//this is where I want to insert the code for mirroring the image

}

int main(int argc, char* argv[]){ //takes command line parameters
    PPMImage *image;
    char* filename = argv[1];
    image = readPPM(filename);
    mirror(image);
    writePPM("OutputFile.ppm",image); //creates the output file
    printf("Press Enter");
    getchar();
}
GRAYgoose124
  • 621
  • 5
  • 24
Austin
  • 73
  • 1
  • 5
  • This is identical to the common problem of reversing the characters in a string. Shame on you for not being able to solve it yourself. – Mark Ransom Apr 22 '13 at 14:27
  • Even though this question presents a skeleton program, it asks for a chunk of code to be inserted into that program without any attempted solution or demonstration of understanding, so it is basically a "write code for me" question. – Kaz Nov 14 '13 at 20:24

2 Answers2

4

Your mirror() function can work on the image one row at a time. For each row, take the left-most pixel in the row and swap its value with the value of the right-most pixel in the row. Then take the second-left-most pixel and swap its value with the second-right-most pixel, and so on, until the column-positions of the pixels you are swapping "meet in the middle". (Then move on to the next row and do the same thing to it, until you've done all the rows).

Note that if the image contains an odd number of columns, there will be one column in the center of the image that stays unmodified (since it forms the axis around which the mirroring occurs). With an even number of columns, all columns will be swapped.

Jeremy Friesner
  • 70,199
  • 15
  • 131
  • 234
0

To mirror image vertically you can use this function:

void mirrorVert(PPMImage *img)
{
    int y;
    int x;
    const int middleX = img->x / 2;
    pixel_t tmp;
    pixel_t* p;

    for (y = 0; y < img->y; ++y)
    {
        p = img->data + y * img->x;
        for (x = 0; x < middleX; ++x)
        {
            // swap pixels
            tmp = p[x];
            p[x] = p[img->x - 1 - x];
            p[img->x - 1 - x] = tmp;
        }
    }
}

And to mirror it horizontally:

void mirrorHoriz(PPMImage *img)
{
    const int line_size = img->x * sizeof(pixel_t);
    const int middle = img->y / 2;
    int y;

    // allocate swap buffer
    pixel_t* buff = (pixel_t*)malloc(line_size);
    pixel_t* top;
    pixel_t* bottom;

    for (y = 0; y < middle; ++y)
    {
        // swap lines from top and bottom
        top = img->data + (y * img->x);
        bottom = img->data + ((img->y - y - 1) * img->x);

        memcpy(buff, top, line_size);
        memcpy(top, bottom, line_size);
        memcpy(bottom, buff, line_size);
    }

}
loentar
  • 5,111
  • 1
  • 24
  • 25