我必须编写一个程序,我在其中获取PPM图像的用户输入,然后从左到右镜像(基本上在y轴上翻转)。因此,如果图像是<,则新图像现在将是>。这不应该是180度旋转,因为这会使图像颠倒。它应该仍然是相同的,只是反映出来。
我这里的代码是用来输入和输出PPM的,但我不知道如何镜像它。我做了一个理论上用于镜像代码的函数,但我不确定这是否是最好的方法。如果您知道更好的地方放置代码,请成为我的客人。
我已经对这个主题进行了相当多的研究,但只能找到人们需要旋转图像的问题。
这是我到目前为止所做的:
#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();
}
答案 0 :(得分:4)
您的mirror()函数可以一次处理一行图像。对于每一行,取行中最左侧的像素,并将其值与行中最右侧像素的值交换。然后取第二个最左边的像素并将其值与第二个最右边的像素交换,依此类推,直到你交换的像素的列位置“在中间相遇”。 (然后转到下一行并对其执行相同的操作,直到完成所有行为止。)
请注意,如果图像包含奇数列,则图像中心将有一列保持不变(因为它形成了发生镜像的轴)。使用偶数列,将交换所有列。
答案 1 :(得分: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);
}
}