PFM 图片格式
参考: https://linux.die.net/man/5/pfm
1. 描述
本文档描述了Netpbm转换器pamtopfm(1)和pfmtopam(1)所理解的PFM图形图像文件格式。
世界上有多种称为PFM的相似格式,它们都没有权威的记录。这里描述的格式是布赖恩亨德森从一个他发现处理'PFM'格式的程序中推断出来的格式。
PFM格式受Netpbm格式的启发,您会看到很多相似之处。不过,它不是官方的Netpbm格式。其目标与Netpbm格式不一致。
2. 格式
PFM图像是一个字节流。该流包含一个标题,紧接着是一个光栅。下面介绍这两个组件。所描述的部分之前或之后没有分隔符。
(1) PFM标题 PFM header
PFM标题是ASCII文本的连续3行'行'。每行之后是一个空格字符。该字符通常是换行符,因此是“行”,但不一定是。
pamtopfm在它生成的PFM中使用换行符。
(2) Identifier Line
标识符行包含字符'PF'或'Pf'。 PF意味着它是一种彩色PFM。 Pf表示这是一个灰度PFM。
(3) 尺寸线 Dimensions Line
尺寸线包含两个正整数,用空格分隔。首先是图像的宽度;第二个是图像的高度。两者都以像素为单位。
(4) 比例因子/字节顺序 Scale Factor / Endianness
比例因子/字节顺序线是一个奇怪的线,它将字节顺序信息压缩成一个合理的尺度描述。该行由非零十进制数组成,不一定是整数。如果数字是负数,那意味着PFM栅格是小端。否则,它是大端。数字的绝对值是图像的比例因子。
比例因子告诉栅格中样本的单位。你用某种方式将它与一些单独理解的单位信息一起用来将样本值转化为有意义的值,例如每平方米的瓦数。
(5) PFM光栅 PFM raster
栅格是一系列像素,一个接一个地打包,没有任何类型的分隔符。它们采用标准的西方阅读顺序:从图像中的左到右和从上到下。
每个像素由1或3个样本组成,一个接一个地打包,没有任何类型的分隔符。 1个样本用于灰度PFM,3个用于彩色PFM(请参阅PFM标头的标识行)。
每个样本由4个连续的字节组成。这些字节表示一个32位字符串,采用大端或小端格式,由PFM标头的比例因子/字节顺序线确定。该字符串是IEEE 32位浮点数字代码。由于这与大多数CPU和编译器使用的格式相同,因此在处理字节序变化后,通常可以让程序直接将字节用作浮点数。
PFM 图片写入
参考: https://github.com/Microsoft/AirSim common_utils/Utils.hpp
static void writePfmFile(const float * const image_data, int width, int height, std::string path, float scalef=1) { std::fstream file(path.c_str(), std::ios::out | std::ios::binary); std::string bands; float fvalue; // scale factor and temp value to hold pixel value bands = "Pf"; // grayscale // sign of scalefact indicates endianness, see pfm specs if(isLittleEndian()) scalef = -scalef; // insert header information file << bands << " "; file << width << " "; file << height << " "; file << scalef << " "; if(bands == "Pf"){ // handle 1-band image for (int i=0; i < height; i++) { for(int j=0; j < width; ++j){ fvalue = image_data[i * width + j]; file.write(reinterpret_cast<char *>(&fvalue), sizeof(fvalue)); } } } }