简体   繁体   English

C-从左到右镜像PPM

[英]C - Mirror a PPM from left to right

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). 我必须编写一个程序,在其中接受用户输入的PPM图像,然后从左向右镜像(基本上在y轴上翻转)。 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. 这不应该是180度旋转,因为那样会使图像上下颠倒。 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. 我这里有用于输入和输出PPM的代码,但是我不知道如何镜像它。 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();
}

Your mirror() function can work on the image one row at a time. 您的mirror()函数可以一次处理一行图像。 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. 如果列数为偶数,则将交换所有列。

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

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM