C - Нужна помощь в замене красных и зеленых компонентов
Этот код (который я отредактировал из кода, который я нашел в предыдущем вопросе о переполнении стека) может принимать входные данные изображения в ppm и выводить то же изображение, но со всеми цветами, дополняющими друг друга. В моем задании меня просят сделать это, но затем поменять местами красный и зеленый компоненты (в основном, сделать img->data[i].red в img->data[i].green и наоборот). Однако я не уверен, как это сделать. Я не могу просто сделать два равных утверждения, так как первое по существу сведет на нет второе. Единственное, о чем я могу думать, это создать временный массив типа PPMImage (структура, созданная ранее). Тем не менее, я немного не уверен, как будет работать код и логика для этого.
Вот код Цикл 'for' в функции changecolorPPM - это место, где цвета дополняются, и где я почти уверен, что должен произойти обмен.
#include<stdio.h>
#include<stdlib.h>
typedef struct {
unsigned char red,green,blue;
} pixel_t;
typedef struct {
int x, y;
pixel_t *data;
} PPMImage;
#define CREATOR "RPFELGUEIRAS"
#define RGB_COMPONENT_COLOR 255
static PPMImage *readPPM(const char *filename)
{
char buff[16];
PPMImage *img;
FILE *fp;
int c, rgb_comp_color;
//open PPM file for reading
fp = fopen(filename, "rb");
if (!fp) {
fprintf(stderr, "Unable to open file '%s'\n", filename);
exit(1);
}
//read image format
if (!fgets(buff, sizeof(buff), fp)) {
perror(filename);
exit(1);
}
//check the image format
if (buff[0] != 'P' || buff[1] != '6') {
fprintf(stderr, "Invalid image format (must be 'P6')\n");
exit(1);
}
//alloc memory form image
img = (PPMImage *)malloc(sizeof(PPMImage));
if (!img) {
fprintf(stderr, "Unable to allocate memory\n");
exit(1);
}
//check for comments
c = getc(fp);
while (c == '#') {
while (getc(fp) != '\n') ;
c = getc(fp);
}
ungetc(c, fp);
//read image size information
if (fscanf(fp, "%d %d", &img->x, &img->y) != 2) {
fprintf(stderr, "Invalid image size (error loading '%s')\n", filename);
exit(1);
}
//read rgb component
if (fscanf(fp, "%d", &rgb_comp_color) != 1) {
fprintf(stderr, "Invalid rgb component (error loading '%s')\n", filename);
exit(1);
}
//check rgb component depth
if (rgb_comp_color!= RGB_COMPONENT_COLOR) {
fprintf(stderr, "'%s' does not have 8-bits components\n", filename);
exit(1);
}
while (fgetc(fp) != '\n') ;
//memory allocation for pixel data
img->data = (pixel_t*)malloc(img->x * img->y * sizeof(pixel_t));
if (!img) {
fprintf(stderr, "Unable to allocate memory\n");
exit(1);
}
//read pixel data from file
if (fread(img->data, 3 * img->x, img->y, fp) != img->y) {
fprintf(stderr, "Error loading image '%s'\n", filename);
exit(1);
}
fclose(fp);
return img;
}
void writePPM(const char *filename, PPMImage *img)
{
FILE *fp;
//open file for output
fp = fopen(filename, "wb");
if (!fp) {
fprintf(stderr, "Unable to open file '%s'\n", filename);
exit(1);
}
//write the header file
//image format
fprintf(fp, "P6\n");
//comments
fprintf(fp, "# Created by %s\n",CREATOR);
//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 changeColorPPM(PPMImage *img)
{
int i;
if(img){
for(i=0;i<img->x*img->y;i++){
img->data[i].red=RGB_COMPONENT_COLOR-img->data[i].red;
img->data[i].green=RGB_COMPONENT_COLOR-img->data[i].green;
img->data[i].blue=RGB_COMPONENT_COLOR-img->data[i].blue;
}
}
}
int main(int argc, char* argv[]){
PPMImage *image;
char* filename = argv[1];
image = readPPM(filename);
changeColorPPM(image);
writePPM("OutputFile.ppm",image);
printf("Press Enter");
getchar();
}
1 ответ
От вашего вопроса, я полагаю, вы ищете swap
функция, которая может быть легко реализована как
img->data[i].red = img->data[i].red + img->data[i].green;
img->data[i].green = img->data[i].red - img->data[i].green;
img->data[i].red = img->data[i].red - img->data[i].green;
Обновить:
Этот раздел хорош, если нет переполнения от операции сложения. Однако, если точность места назначения недостаточна для хранения битов, возможна потеря данных. Следовательно, в этих случаях, как предположили Мэтс и другие эксперты, лучшим способом продвижения вперед будет традиционный метод временных переменных.
temp = img->data[i].red;
img->data[i].red = img->data[i].green;
img->data[i].green = temp;
Замечания:
Если вы занимаетесь обработкой изображений, то этот обмен может не понравиться с визуальной точки зрения. Обычно зеленый содержит максимальную интенсивность, то есть количество информации о яркости по сравнению с красным и синим, и человеческий глаз может очень легко уловить изменения интенсивности. Интересно будет посмотреть, как выглядит финальная картинка после обмена.