20250713 保存 PGM / PPM 图片 C++
测试结果
直接上代码
-std=c++17,记得编译时指定 C++17,创建文件夹的时候要用。不需要创建文件夹可以去掉。
// *********************************************
// Brief: save image as ppm, pbm, pgm
// Note:
// P1 - PBM_ASCII, P2 - PGM_ASCII, P3 - PPM_ASCII,
// P4 - PBM_BINARY, P5 - PGM_BINARY, P6 - PPM_BINARY
//
// Date: 13 Jul 2025
// *********************************************
#include <vector>
#include <iostream>
#include <filesystem>static void createPath(const std::string &fullPath)
{std::filesystem::path filePath(fullPath);// get filename without extensionstd::string filename = filePath.stem().string();// create new pathstd::filesystem::path dirPath = filePath.parent_path();// / filename;// create folderif (std::filesystem::exists(dirPath)){} else if (std::filesystem::create_directories(dirPath)){printf("Create Folder Success: %s\n", dirPath.c_str());} else{printf("Create Folder Failed, might already exists: %s\n", dirPath.c_str());}
}/*** PBM - Portable BitMap, 0 - White, 1 - Black**/
static void saveImgAsPBM(const std::string &dumpPath, uint8_t *data, size_t width, size_t height)
{// PBM is an image format, can open with default image viewer on ubuntu.std::string flow_ppm_filename = dumpPath + ".pbm";createPath(flow_ppm_filename);FILE *pOutFile = NULL;pOutFile = fopen(flow_ppm_filename.c_str(), "wb");fprintf(pOutFile, "P4\n");fprintf(pOutFile, "%ld %ld\n", (long) width, (long) height);// fprintf(pOutFile, "1\n"); // no max value for PBM// packing image data, MSB firstconst size_t rowBytes = (width + 7) / 8;std::vector<uint8_t> packed(rowBytes);for (size_t y = 0; y < height; ++y){std::fill(packed.begin(), packed.end(), 0); // clear bufferfor (size_t x = 0; x < width; ++x){const size_t byteIdx = x / 8;const size_t bitPos = 7 - (x % 8); // MSB firstif (data[y * width + x]){packed[byteIdx] |= (1 << bitPos);}}// write into filefwrite(packed.data(), 1, rowBytes, pOutFile);}fclose(pOutFile);
}/*** PGM - Portable GreyMap, 0 - Black, MaxNum - White*/
static void saveImgAsPGM(const std::string &dumpPath, uint8_t *data, size_t width, size_t height)
{// PGM is an image format, can open with default image viewer on ubuntu.std::string flow_ppm_filename = dumpPath + ".pgm";createPath(flow_ppm_filename);FILE *pOutFile = NULL;pOutFile = fopen(flow_ppm_filename.c_str(), "wb");fprintf(pOutFile, "P5\n");fprintf(pOutFile, "%ld %ld\n", (long) width, (long) height);fprintf(pOutFile, "255\n"); // set max value to 255fwrite(data, 1, 1 * width * height, pOutFile);fclose(pOutFile);
}/*** PPM - Portable PixMap*/
static void saveImgAsPPM(const std::string &dumpPath, uint8_t *data, size_t width, size_t height)
{// PPM is an image format, can open with default image viewer on ubuntu.std::string flow_ppm_filename = dumpPath + ".ppm";createPath(flow_ppm_filename);FILE *pOutFile = NULL;pOutFile = fopen(flow_ppm_filename.c_str(), "wb");fprintf(pOutFile, "P6\n");fprintf(pOutFile, "%ld %ld\n", (long) width, (long) height);fprintf(pOutFile, "255\n");fwrite(data, 1, 3 * width * height, pOutFile);fclose(pOutFile);
}int main() {const size_t width = 256;const size_t height = 256;const std::string basePath = "./output/test_image";// 1. PBM teststd::vector<uint8_t> pbmData(width * height, 1);for (size_t y = 0; y < height; ++y) {for (size_t x = 0; x < width; ++x) {pbmData[y * width + x] = (x / 16 + y / 16) % 2; // checkerboard pattern}}saveImgAsPBM(basePath + "_pbm", pbmData.data(), width, height);std::cout << "PBM Test finished.\n";// 2. PGM teststd::vector<uint8_t> pgmData(width * height);for (size_t y = 0; y < height; ++y) {for (size_t x = 0; x < width; ++x) {pgmData[y * width + x] = x % 256; // gradient}}saveImgAsPGM(basePath + "_pgm", pgmData.data(), width, height);std::cout << "PGM Test finished.\n";// 3. PPM teststd::vector<uint8_t> ppmData(3 * width * height);for (size_t y = 0; y < height; ++y) {for (size_t x = 0; x < width; ++x) {size_t pos = 3 * (y * width + x);ppmData[pos] = x % 256; // R, gradient valueppmData[pos + 1] = y % 256; // G, gradient valueppmData[pos + 2] = 128; // B}}saveImgAsPPM(basePath + "_ppm", ppmData.data(), width, height);std::cout << "PPM Test finished.\n";return 0;
}
Refference
- DeepSeek 内容
- Main 函数编写
- PBM Packing 代码实现
- PPM、PGM、PBM三种都是图像文件格式
- PBM Packing 原理