如何在C语言生成的PPM文件中叠加多图形制作南瓜图像?
如何在同一PPM文件中叠加多个图形制作南瓜主题图像
我正在开发一款C语言程序,目标是生成带有方形眼睛、鼻子和矩形嘴巴的南瓜主题PPM图像。当前代码可生成橙色圆形,通过修改RGB值可调整图形颜色,修改命令行参数(如./SpookyImageGenerator output.ppm 800 600 100)可切换生成的图形类型(圆、正方形、矩形),但目前只能将不同图形输出到不同PPM文件。请问如何在同一PPM文件中叠加多个图形以完成完整图像制作?
当前主程序代码
#include <stdlib.h> #include <stdio.h> #include "MyFunctions.h" int main(int argc, char *argv[]) { int numRows; // Number of rows in our image. int numCols; // Number of columns in our image. int imageSize; // The total numberof rows * columns in the image int Radius; // The radius of the circle added to image. int row, col; // The marker to know where we are in the image int InOrOut; // Flag for in or outside of the circle unsigned char *outImage; /* Pixel Pointer */ unsigned char *ptr; /* Pointer */ FILE *outputFP; /* My out put file pointer */ printf("=======================================\n"); printf(" This will make an image \n"); printf("=======================================\n"); // Read in some command line arguments. if(argc != 5) { printf("Usage: ./[1]SpookyImageMaker [2]OutFile [3]numRows [4]numCols [5]Radius \n"); exit(1); } if((numRows = atoi(argv[2])) <= 0) { printf("The given number rows is not positive!\n"); } if((numCols = atoi(argv[3])) <= 0) { printf("The given number of columns is not positive!\n"); } if((Radius = atoi(argv[4])) <= 0) { printf("Check your radius -- it should be positive!\n"); } printf("=============================================\n"); printf(" Now working to set up sizes. \n"); printf("=============================================\n"); imageSize = numRows*numCols*3; outImage = (unsigned char *) malloc(imageSize); /* Open the image for writing. */ if ( (outputFP = fopen(argv[1],"w")) == NULL) { perror("output open error"); printf("Error in opening your given output file!\n"); exit(2); } printf("=============================================\n"); printf(" Index Through the given image. \n"); printf("=============================================\n"); ptr = outImage; for( row = 0 ; row < numRows ; row++) { for( col = 0 ; col < numCols ; col++){ printf("Row and Col (%d,%d)\n",row,col); InOrOut = CheckRadius(numRows, numCols, Radius, row, col); if(InOrOut == 1) { *ptr = 255; // red pixel *(ptr+1) = 117; // green pixel *(ptr+2) = 24; // blue pixel } else { *ptr = 0; // red pixel *(ptr+1) = 0; // green pixel *(ptr+2) = 0; // blue pixel } // Advance the pixel pointer ptr += 3; } } printf("============================================\n"); printf(" Write it all out to a file for viewing. \n"); printf("============================================\n"); fprintf(outputFP, "P6 %d %d 255\n", numCols, numRows); fwrite(outImage, 1, imageSize, outputFP); /* Done */ fclose(outputFP); return 0; }
HelperFunctions.c 代码
#include <math.h> int CheckRadius(int TotRows, int TotCols, int Radius, int CurPixRow, int CurPixCol){ int InOrOut = 0; // Returns 0 or 1 for out and in side the circle respectively. int CenterRow = TotRows/2; // Place holder for the center with regard to rows. int CenterCol = TotCols/2; // Place holder for the center column. int dist = 0; // Place in memory for the distance between CurPix and Center. // printf("I'm in CheckRadius\n"); // Compute The distance. dist = pow((pow(CenterRow-CurPixRow,2.0)+pow(CenterCol-CurPixCol,2.0)),0.5); // Check is dist < Radius and set flag. if( dist < Radius){ InOrOut = 1; } return InOrOut; }
MyFunctions.h(当前内容)
#ifndef MYFUNCTIONS_H #define MYFUNCTIONS_H int CheckRadius(int TotRows, int TotCols, int Radius, int CurPixRow, int CurPixCol); #endif
实现多图形叠加的步骤
1. 初始化图像为背景色
先将整个图像数组初始化为背景色(比如黑色),后续绘制的图形会直接覆盖对应位置的像素:
// 初始化所有像素为黑色背景 ptr = outImage; for (row = 0; row < numRows; row++) { for (col = 0; col < numCols; col++) { *ptr = 0; *(ptr+1) = 0; *(ptr+2) = 0; ptr += 3; } }
2. 绘制底层南瓜(橙色圆形)
遍历像素,只修改圆形范围内的像素为南瓜橙色,保留背景色不变:
ptr = outImage; for (row = 0; row < numRows; row++) { for (col = 0; col < numCols; col++) { if (CheckRadius(numRows, numCols, Radius, row, col) == 1) { *ptr = 255; // 红色通道 *(ptr+1) = 117; // 绿色通道 *(ptr+2) = 24; // 蓝色通道 } ptr += 3; } }
3. 添加新的图形判断函数
在HelperFunctions.c中添加方形、矩形的像素判断函数,用于绘制五官:
// 判断像素是否在指定中心和尺寸的方形内(眼睛、鼻子) int CheckSquare(int centerRow, int centerCol, int size, int curRow, int curCol) { int halfSize = size / 2; if (curRow >= centerRow - halfSize && curRow <= centerRow + halfSize && curCol >= centerCol - halfSize && curCol <= centerCol + halfSize) { return 1; } return 0; } // 判断像素是否在指定中心、宽高的矩形内(嘴巴) int CheckRectangle(int centerRow, int centerCol, int width, int height, int curRow, int curCol) { int halfWidth = width / 2; int halfHeight = height / 2; if (curRow >= centerRow - halfHeight && curRow <= centerRow + halfHeight && curCol >= centerCol - halfWidth && curCol <= centerCol + halfWidth) { return 1; } return 0; }
同时更新MyFunctions.h的函数声明:
#ifndef MYFUNCTIONS_H #define MYFUNCTIONS_H int CheckRadius(int TotRows, int TotCols, int Radius, int CurPixRow, int CurPixCol); int CheckSquare(int centerRow, int centerCol, int size, int curRow, int curCol); int CheckRectangle(int centerRow, int centerCol, int width, int height, int curRow, int curCol); #endif
4. 叠加绘制五官
在南瓜绘制完成后,再次遍历像素,将五官位置的像素修改为黑色:
ptr = outImage; int imageCenterRow = numRows / 2; int imageCenterCol = numCols / 2; // 五官尺寸与位置参数 int eyeSize = 20; int eyeOffset = 50; // 眼睛与中心的横向偏移 int noseSize = 15; int mouthWidth = 80; int mouthHeight = 30; int mouthOffset = 40; // 嘴巴与中心的纵向偏移 for (row = 0; row < numRows; row++) { for (col = 0; col < numCols; col++) { // 左眼 if (CheckSquare(imageCenterRow - eyeOffset, imageCenterCol - eyeOffset, eyeSize, row, col) == 1) { *ptr = 0; *(ptr+1) = 0; *(ptr+2) = 0; } // 右眼 else if (CheckSquare(imageCenterRow - eyeOffset, imageCenterCol + eyeOffset, eyeSize, row, col) == 1) { *ptr = 0; *(ptr+1) = 0; *(ptr+2) = 0; } // 鼻子 else if (CheckSquare(imageCenterRow, imageCenterCol, noseSize, row, col) == 1) { *ptr = 0; *(ptr+1) = 0; *(ptr+2) = 0; } // 嘴巴 else if (CheckRectangle(imageCenterRow + mouthOffset, imageCenterCol, mouthWidth, mouthHeight, row, col) == 1) { *ptr = 0; *(ptr+1) = 0; *(ptr+2) = 0; } ptr += 3; } }
5. 优化命令行参数(可选)
可以去掉手动输入半径的参数,改为自动计算南瓜大小:
if(argc != 4) { printf("Usage: ./SpookyImageMaker OutFile numRows numCols\n"); exit(1); } numRows = atoi(argv[2]); numCols = atoi(argv[3]); // 自动设置南瓜半径为图像较小边的1/3 int Radius = (numRows < numCols) ? numRows/3 : numCols/3;
核心原理
图形叠加的本质是分层覆盖:先绘制底层的南瓜图形,再在上层绘制五官图形。由于直接修改像素数组的数值,后续绘制的像素会覆盖之前的数值,从而实现多个图形在同一文件中的叠加效果。
内容的提问来源于stack exchange,提问作者TheSwampyBogbeard
相关产品推荐
相关产品推荐

