Thread: Need help rotating a PPM image 90 degrees to the right!

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

    Need help rotating a PPM image 90 degrees to the right!

    I am trying to write a function rotate() that will rotate a PPM image 90 degrees to the right.

    So far this is what i have (which doesn't work):

    Code:
    void rotate(pixel_t *image, int x, int y)
    {
        int r, c, red, green, blue;
        for (c = 0; c < y; c++)
        {
            for (r = 0; r < x; r++)
            {
                 red = (x-c-1)+(r*3);
                 green = (x-c-1)+(r*3+1);
                 blue = (x-c-1)+(r*3+2);
                printf("%c%c%c", image[red].r, image[green].g, image[blue].b);
            }
        }
    }
    If you need to see the rest of the program let me know! Please help!
    Last edited by hbranum; 12-07-2012 at 04:28 PM.

  2. #2
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    Let's assume you use something like
    Code:
    typedef ... pixel_t;
    
    typedef struct {
        long     width;
        long     height;
        long     xstep;
        long     ystep;
        pixel_t *origin;
        void    *data;
    } image_t;
    
    #define PIXEL(image, x, y) ((image).pixel[(y) * (image).ystep + (x) * (image).xstep])
    with data pointing to the start of the dynamically allocated pixel data buffer, usually the same as origin, and usually xstep = 1 and ystep = width .

    To rotate such an image 90 degrees:
    Code:
    void image_rotate_clockwise(image_t *const image)
    {
        if (image) {
            pixel_t *const  origin = image->origin;
            const long      width  = image->width;
            const long      height = image->height;
            const long      xstep  = image->xstep;
            const long      ystep  = image->ystep;
    
            image->origin = origin + height * ystep;
            image->width  = height;
            image->height = width;
            image->xstep  = -ystep;
            image->ystep  = xstep;
        }
    }
    You can just as easily flip the image (mirroring x or y), as well as crop it and scale it down with any integer factor (i.e, 1:2, 1:3, 1:4, 1:5, and so on -- but using the poor "nearest neighbor" scaling algorithm, effectively).

    If you are experimenting with image manipulation, I warmly recommend the above image structure. You'll avoid unnecessary data copying, and can easily add all sorts of rotation and/or cropping as input filters.

    For filter effect experiments, I've used helper functions
    Code:
    static inline pixel_t getpixel(const image_t *const image, const long x, const long y, const pixel_t outside)
    {
        if (image && x >= 0L && y >= 0L && x < image->width && y < image->height)
            return image->origin[x * image->xstep + y * image->ystep];
        else
            return outside;
    }
    
    static inline void setpixel(image_t *const image, const long x, const long y, const pixel_t  pixel)
    {
        if (image && x >= 0L && y >= 0L && x < image->width && y < image->height)
            image->origin[x * image->xstep + y * image->ystep] = pixel;
    }
    The getpixel() returns the specified outside value whenever the coordinates are outside image, and setpixel() only manipulates the image pixels.

    I personally prefer uint32_t or uint64_t ARGB, with the most significant quarter of the bits specifying opacity. Using bit masks you can blend and mix color values much more efficiently than when color components are separate variables.


    Looking at your code, it seems you are really trying to save P6 format data when given a linear array containing RGB triplets, i.e.
    Code:
    typedef struct {
        unsigned char  red;
        unsigned char  green;
        unsigned char  blue;
    } pixel_t;
    
    /* Order is the same as in a PPM image, i.e.
     *   index = x + y * width
     * where
     *   0 <= index < width * height
     *   0 <= x < width
     *   0 <= y < height
    */
    A normal, non-rotated PPM (P6 format) save routine should probably be something like this:
    Code:
    void save_p6(const pixel_t *const image,
                 const int width,
                 const int height,
                 FILE *const out)
    {
        int  x, y;
    
        fprintf(out, "P6\n%d %d\n255\n", width, height);
    
        for (y = 0; y < height; y++) {
            for (x = 0; x < width; x++) {
                putc(image[x + y * width].red,   out);
                putc(image[x + y * width].green, out);
                putc(image[x + y * width].blue,  out);
            }
        }
    }
    Now, if you wanted to save the image rotated 90 degrees clockwise, all you modify is the PPM header (since width and height will be swapped), and the loop order and direction. The pixel component access within the loop does not change at all:
    Code:
    void save_p6_90(const pixel_t *const image,
                    const int width,
                    const int height,
                    FILE *const out)
    {
        int  x, y;
    
        fprintf(out, "P6\n%d %d\n255\n", height, width);
    
        for (x = 0; x < width; x++) {
            for (y = height - 1; y >= 0; y--) {
                putc(image[x + y * width].red,   out);
                putc(image[x + y * width].green, out);
                putc(image[x + y * width].blue,  out);
            }
        }
    }
    Questions?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 12-04-2012, 07:28 AM
  2. Pasting image to rotating billboard
    By funwey in forum Game Programming
    Replies: 1
    Last Post: 07-16-2009, 04:29 PM
  3. Degrees of seperation
    By MadCow257 in forum A Brief History of Cprogramming.com
    Replies: 18
    Last Post: 03-30-2006, 04:28 PM
  4. sin() and cos() that use degrees
    By dwks in forum C Programming
    Replies: 3
    Last Post: 05-14-2005, 04:29 PM
  5. radian to degrees
    By Mr.Pink in forum C++ Programming
    Replies: 8
    Last Post: 02-17-2005, 11:03 PM

Tags for this Thread