PGM或可移植灰度图文件是一种灰度图像,其中每个像素都使用1或2个字节进行编码。它以矩阵形式包含标题信息和像素灰度值。
方法:遵循的思想是读取PGMB格式的图像如下:
- 打开PGMB(二进制格式的PGM图像)。
- 提取像素信息,然后可以将其用于进一步处理。
- 标头信息以ASCII格式存储,可以使用任何文本编辑器读取,但像素信息以二进制格式存储,并且文本编辑器将显示该文本为乱码。
以下是示例pgm图像。
标头信息:
- 标识文件类型的幻数:
- 二进制PGM文件(PGMB):“ P5”
- ASCII PGM文件(PGMA):“ P2”
- ASCII十进制格式的宽度
- ASCII十进制格式的高度
- 最大灰度值,ASCII十进制格式,介于0-255之间
- 可以包含注释,以“#”开头
- 全部用空格分隔(空格,制表符,CR,LF)
gfg_logo.pgm中的标题信息:
P5
# sample PGMB image
# gfg_logo.pgm
200 200
255
在标题信息之后,有一个尺寸为高度*重量的网格,其中包含二进制格式的图像的灰度像素值。
读取PGMB图片:
- 以读取的二进制rb模式打开图像。
- 检查是否存在任何注释,并忽略它们。
- 阅读魔幻数字。
- 阅读任何注释/空白行/空白。
- 读取宽度和高度,用空格隔开。
- 在任何空白/注释之前和之后读取最大灰度值。
- 读取像素值的网格(宽度*高度) ,以空格分隔。
下面是上述方法的程序:
C
// C Programe to read a PGMB image
// and print its parameters
#include
#include
#include
#include
#include
// Structure for storing the
// image data
typedef struct PGMImage {
char pgmType[3];
unsigned char** data;
unsigned int width;
unsigned int height;
unsigned int maxValue;
} PGMImage;
// Function to ignore any comments
// in file
void ignoreComments(FILE* fp)
{
int ch;
char line[100];
// Ignore any blank lines
while ((ch = fgetc(fp)) != EOF
&& isspace(ch))
;
// Recursively ignore comments
// in a PGM image commented lines
// start with a '#'
if (ch == '#') {
fgets(line, sizeof(line), fp);
ignoreComments(fp);
}
else
fseek(fp, -1, SEEK_CUR);
}
// Function to open the input a PGM
// file and process it
bool openPGM(PGMImage* pgm,
const char* filename)
{
// Open the image file in the
// 'read binary' mode
FILE* pgmfile
= fopen(filename, "rb");
// If file does not exist,
// then return
if (pgmfile == NULL) {
printf("File does not exist\n");
return false;
}
ignoreComments(pgmfile);
fscanf(pgmfile, "%s",
pgm->pgmType);
// Check for correct PGM Binary
// file type
if (strcmp(pgm->pgmType, "P5")) {
fprintf(stderr,
"Wrong file type!\n");
exit(EXIT_FAILURE);
}
ignoreComments(pgmfile);
// Read the image dimensions
fscanf(pgmfile, "%d %d",
&(pgm->width),
&(pgm->height));
ignoreComments(pgmfile);
// Read maximum gray value
fscanf(pgmfile, "%d", &(pgm->maxValue));
ignoreComments(pgmfile);
// Allocating memory to store
// img info in defined struct
pgm->data
= malloc(pgm->height
* sizeof(unsigned char*));
// Storing the pixel info in
// the struct
if (pgm->pgmType[1] == '5') {
fgetc(pgmfile);
for (int i = 0;
i < pgm->height; i++) {
pgm->data[i]
= malloc(pgm->width
* sizeof(unsigned char));
// If memory allocation
// is failed
if (pgm->data[i] == NULL) {
fprintf(stderr,
"malloc failed\n");
exit(1);
}
// Read the gray values and
// write on allocated memory
fread(pgm->data[i],
sizeof(unsigned char),
pgm->width, pgmfile);
}
}
// Close the file
fclose(pgmfile);
return true;
}
// Function to print the file details
void printImageDetails(PGMImage* pgm,
const char* filename)
{
FILE* pgmfile = fopen(filename, "rb");
// Retreiving the file extension
char* ext = strrchr(filename, '.');
if (!ext)
printf("No extension found"
"in file %s",
filename);
else
printf("File format"
" : %s\n",
ext + 1);
printf("PGM File type : %s\n",
pgm->pgmType);
// Print type of PGM file, in ascii
// and binary format
if (!strcmp(pgm->pgmType, "P2"))
printf("PGM File Format:"
"ASCII\n");
else if (!strcmp(pgm->pgmType,
"P5"))
printf("PGM File Format:"
" Binary\n");
printf("Width of img : %d px\n",
pgm->width);
printf("Height of img : %d px\n",
pgm->height);
printf("Max Gray value : %d\n",
pgm->maxValue);
// close file
fclose(pgmfile);
}
// Driver Code
int main(int argc, char const* argv[])
{
PGMImage* pgm = malloc(sizeof(PGMImage));
const char* ipfile;
if (argc == 2)
ipfile = argv[1];
else
ipfile = "gfg_logo.pgm";
printf("\tip file : %s\n", ipfile);
// Process the image and print
// its details
if (openPGM(pgm, ipfile))
printImageDetails(pgm, ipfile);
return 0;
}
输出:
解释:
- 创建用于存储PGMB图像详细信息的结构,并为其分配内存。
- 将文件名输入作为命令行参数或在程序中进行硬编码。
- openPGM()函数处理输入的图像文件,并获取内存指针和文件名。
- ignoreComments()函数用于跳过文件中的任何注释。注释通常出现在标题部分,因此,我们在读取每个属性后都会对其进行检查。
- 在openPGM()函数,读取文件头信息,即。文件类型,高度,重量等。
- 然后根据图像的高度分配内存,并针对每一行为图像的宽度分配内存。
- fread()方法读取灰度值,并将其存储在为pgm结构的2d字符矩阵分配的内存中。
- printImageDetails()用于打印从PGMB图像文件检索的值。
想要从精选的最佳视频中学习和练习问题,请查看《基础知识到高级C的C基础课程》。