如何正确将RGB颜色保存到PPM文件?红色渐变变黄色问题排查
问题:C语言PPM程序预期生成红色渐变,实际得到黄色渐变
我正在制作一个教学项目,尝试用C语言编写一个基于一维数组将RGB颜色保存到PPM文件的简单程序。提供的代码运行正常,但原本应生成单色红色渐变,实际却得到黄色渐变,请问问题出在哪里?
#include <complex.h> #include <math.h> #include <omp.h> //OpenM #include <stdio.h> #include <stdlib.h> /* fork of mandelbrot-book how to write a book about the Mandelbrot set by Claude Heiland-Alle https://code.mathr.co.uk/mandelbrot-book/blob/HEAD:/book/ https://stackoverflow.com/questions/77135883/why-do-my-functions-not-work-in-parallel gcc c.c -lm -Wall -fopenmp ./a.out > rgb.ppm // P6 = binary Portable PixMap see https://en.wikipedia.org/wiki/Netpbm#File_formats convert rgb.ppm rgb.png */ double aspect_ratio = 16.0 / 9.0; // = w/h const int h = 200; int w; // = h * aspect_ratio; const double r = 2.0; // plane radius const double px = r / (h / 2); double width; double xMin; // https://stackoverflow.com/questions/2594913/getting-the-fractional-part-of-a-float-without-using-modf double frac(double d) { return d - (int)d; } // rgb in [0,1] range void giveRGBColor(const complex double z, double *r, double *g, double *b) { *r = frac(abs((creal(z) - xMin)) / width); // *g = 1.0; *b = 1.0; } int main() { w = h * aspect_ratio; // The aspect ratio of an image is the ratio of its // width to its height, and is expressed with two // numbers separated by a colon, such as 16:9, unsigned char *img = malloc(3 * w * h); // image width = r * 2.0 * aspect_ratio; double height = r * 2.0; xMin = (0 + 0.5 - w / 2) / (h / 2) * r; fprintf(stderr, "image width = %.2f in world coordinate\n", width); fprintf(stderr, "image height = %.2f in world coordinate\n", height); fprintf(stderr, "image aspect ratio = width:height = %d:%d = %f = %f = %f\n", w, h, w / (1.0 * h), width / (1.0 * height), aspect_ratio); #pragma omp parallel for schedule(dynamic) for (int j = 0; j < h; ++j) { double y = (h / 2 - (j + 0.5)) / (h / 2) * r; for (int i = 0; i < w; ++i) { double x = (i + 0.5 - w / 2) / (h / 2) * r; // for q=2 add -0.5 double _Complex z = x + I * y; // color double red, grn, blu; giveRGBColor(z, &red, &grn, &blu); // compute rgb // convert to [0,255] integer and save rgb color to array img[3 * (j * w + i) + 0] = (int)(255 * red); img[3 * (j * w + i) + 1] = (int)(255 * grn); img[3 * (j * w + i) + 2] = (int)(255 * blu); } } // printf("P6\n%d %d\n255\n", w, h); fwrite(img, 3 * w * h, 1, stdout); free(img); return 0; }
问题根源
黄色是红色+绿色的混合色,你的代码里giveRGBColor函数将绿色(*g)和蓝色(*b)都固定设为1.0(即满值255),而红色(*r)在[0,1]范围内渐变:
- 当
red=0时,颜色为(0,255,255),是亮黄色; - 当
red=1时,颜色为(255,255,255),是白色;
所以整体呈现从黄到白的渐变,而非预期的红色渐变。
解决方案
要实现单色红色渐变,需要将绿色和蓝色通道设为0.0,让只有红色通道随位置变化:
修改giveRGBColor函数:
// rgb in [0,1] range void giveRGBColor(const complex double z, double *r, double *g, double *b) { *r = frac(abs((creal(z) - xMin)) / width); *g = 0.0; // 关闭绿色通道 *b = 0.0; // 关闭蓝色通道 }
修改后,颜色会从(0,0,0)黑色渐变到(255,0,0)纯红色,符合你要的单色红色渐变效果。如果需要其他红色系渐变(比如从浅红到深红),可以调整红色通道的计算逻辑,但核心是保证绿蓝通道不参与显色。
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

