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();
}
4

2 回答 2

4

您的 mirror() 函数可以一次处理一排图像。对于每一行,取该行中最左边的像素并将其值与该行中最右边像素的值交换。然后取第二个最左边的像素并将其值与第二个最右边的像素交换,依此类推,直到您要交换的像素的列位置“在中间相遇”。(然后移动到下一行并对其执行相同的操作,直到您完成所有行)。

请注意,如果图像包含奇数列,则图像中心将有一列保持不变(因为它形成了镜像发生的轴)。对于偶数列,所有列将被交换。

于 2013-04-22T14:21:31.120 回答
0

要垂直镜像图像,您可以使用此功能:

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;
        }
    }
}

并水平镜像:

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);
    }

}
于 2013-04-22T14:30:41.120 回答