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

• 12-07-2012
hbranum
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!
• 12-07-2012
Nominal Animal
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?