Thread: PPM Image Manipulations

  1. #1
    Registered User
    Join Date
    Dec 2012
    Posts
    10

    Post PPM Image Manipulations

    Hello, I need help flipping a PPM image vertically. The code I have is below, but the flipImage function does not work correctly. Any help would be appreciated!

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    
    typedef struct
    {
        unsigned char r;
        unsigned char b;
        unsigned char g;
    }     pixel_t;
    
    
    pixel_t *image;
    
    
    #define RGB_COMPONENT_COLOR 255
    
    
    void flipImage(pixel_t *image, int x, int y);
    void grayscale(pixel_t *image, int x, int y);
    void rotate(pixel_t *image, int x, int y);
    
    
    int main(int argc, char *argv[])
    {
        int width;
        int height;
        int numPixels;
        int i, rgb_comp_color = 255;
        char c;
    
    
        FILE *inFile;
        inFile = fopen(argv[2], "r");
    
    
        //check for comments
        c = getc(inFile);
        while (c == '#')
        {
            do
            {
                c = getc(inFile);
            } while (c != '\n');
            c = getc(inFile);
        }
    
    
        ungetc(c, inFile);
    
    
        //read width and height
        if (fscanf(inFile, "P6 %d %d", &width, &height) != 2)
        {
            fprintf(stderr, "Invalid image size.\n");
            exit(1);
        }
        
        //read RGB component
        if (fscanf(inFile, "%d\n", &rgb_comp_color) != 1)
        {
            fprintf(stderr, "Invalid RGB component.\n");
            exit(1);
        }
    
    
        //check RGB depth
        if (rgb_comp_color != RGB_COMPONENT_COLOR)
        {
            fprintf(stderr, "Invalid RGB value.\n");
            exit(1);
        }
    
    
        numPixels = width*height;
    
    
        //allocate space
        image = malloc (numPixels * sizeof(pixel_t));
    
    
        //read in pixel data
        for (i = 0; i < numPixels; i++)
        {
            fscanf(inFile, "%c%c%c", &image[i].r, &image[i].g, &image[i].b);
        }
    
    
        //print new header
        printf ("P6\n");
        printf ("%d %d 255\n", width, height);
    
    
        switch (*argv[1])
        {
            case '1':
                    flipImage(image, width, height);
                    break;
            case '2':
                    grayscale(image, width, height);
                    break;
            case '3':
                    //rotate(image, height, width);
                    break;
            default:
                    printf("Invalid command line argument. User must enter a 1, 2, or 3.\n");
                    break;
        }
        
        return 0;
    }
        
    void grayscale(pixel_t *image, int x, int y)
    {
        int i, average = 0;
        for (i = 0; i < x*y; i++)
        {
            average = (image[i].r + image[i].g + image[i].b) / 3;
            printf("%c%c%c", average, average, average);
        }
    }
    
    
    void flipImage(pixel_t *image, int x, int y)
    {
        int r, c;
        for (c = y-1; c >= 0; c--)
        {
            for (r = 0; r < x; r++)
            {
                printf("%c%c%c", image[r].r, image[r].g, image[r].b);
            }
        }
    }
    Last edited by hbranum; 12-07-2012 at 12:45 PM.

  2. #2
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Can you edit your post, and type [*code] and [*/code] tags around your program? (but without the *'s).

    It's very hard to study code that is all smashed over to the left hand side like html text. (No C coloring, no line numbers, no indentation, and wrong font).

    ALWAYS USE CODE TAGS around your code
    Last edited by Adak; 12-07-2012 at 12:42 PM.

  3. #3
    Registered User
    Join Date
    Dec 2012
    Posts
    10
    There we go! Sorry, I am new to this!

  4. #4
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    You need to treat the pixels as an array with width x height dimensions. So your flip fuinction would be more like this:
    Code:
    void flipImage(pixel_t *image, int x, int y) {
    int r, c, i;
    for (c = y-1; c >= 0; c--)
        {
            for (r = 0; r < x; r++)
            {
                i = c * width + r;
                printf("%c%c%c", image[i].r, image[i].g, image[i].b);
            }
        }
    }
    As long as you have 'width' available, or pass it as a paramater.
    Last edited by nonoob; 12-07-2012 at 01:26 PM. Reason: I just noticed you said you wanted image flipped vertically. So I reoriented r and c for the calculation.

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Code:
            for (r = 0; r < x; r++)
            {
                printf("%c%c%c", image[r].r, image[r].g, image[r].b);
            }
    You're just outputting the first row over and over.

    You need to construct a single pixel index from the row and column positions of your input parameters.
    index = c * x + r;
    kind of thing.

    grayscale didn't care about the rectangular grid, so you could get away with just processing
    for (i = 0; i < x*y; i++)
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User
    Join Date
    Dec 2012
    Posts
    10
    Quote Originally Posted by nonoob View Post
    You need to treat the pixels as an array with width x height dimensions. So your flip fuinction would be more like this:
    Code:
    void flipImage(pixel_t *image, int x, int y) {
    int r, c, i;
    for (c = y-1; c >= 0; c--)
        {
            for (r = 0; r < x; r++)
            {
                i = r * width + c;
                printf("%c%c%c", image[i].r, image[i].g, image[i].b);
            }
        }
    }
    As long as you have 'width' available, or pass it as a paramater.
    When I tried this the compiler gave me a segmentation fault.

  7. #7
    Registered User
    Join Date
    Dec 2012
    Posts
    10
    Also @salem I don't know what you mean? Could you show me what the code would look like?

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Do you understand what these lines mean?

    > if (fscanf(inFile, "P6 %d %d", &width, &height) != 2)
    > numPixels = width*height;

    If your image is 6 x 4
    111111
    222222
    333333
    444444


    It is stored in memory as
    111111222222333333444444

    The point of the maths in the for loops is to "reconstruct" the rectangular arrangement from the linear data structure.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  9. #9
    Registered User
    Join Date
    Dec 2012
    Posts
    10
    Quote Originally Posted by Salem View Post
    Do you understand what these lines mean?

    > if (fscanf(inFile, "P6 %d %d", &width, &height) != 2)
    > numPixels = width*height;

    If your image is 6 x 4
    111111
    222222
    333333
    444444


    It is stored in memory as
    111111222222333333444444

    The point of the maths in the for loops is to "reconstruct" the rectangular arrangement from the linear data structure.
    Ah, I get it now.

  10. #10
    Registered User
    Join Date
    Dec 2012
    Posts
    10
    Ok also I need help with my function rotate(). The function is supposed to rotate the image 90 degrees to the right. How would I do this?

  11. #11
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Don't you need to move the pixels in the matrix, from say, top left corner, to the top right corner? Each pixels distance from the left side, will now be it's distance from the top, and their distance from the right side, will become their distance from the bottom edge.

    You need to express that mathematically, with simple addition or subtraction. I haven't done this, but I would certain practice a bit, using a very simple 4x4 matrix of integers, first. Get the math refined, and THEN use that on the ppm matrix of pixels.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. C String manipulations with switch statement
    By sp85202 in forum C Programming
    Replies: 4
    Last Post: 09-17-2012, 02:11 PM
  2. Replies: 4
    Last Post: 03-13-2010, 05:10 AM
  3. Replies: 13
    Last Post: 11-20-2009, 04:43 PM
  4. Bitwise Manipulations in c
    By MrWannabe in forum C Programming
    Replies: 1
    Last Post: 09-22-2009, 11:02 PM
  5. Using mask in bit manipulations...
    By Nutshell in forum C Programming
    Replies: 8
    Last Post: 01-28-2002, 01:00 AM

Tags for this Thread