20250713 保存 PBM / 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 extension
    std::string filename = filePath.stem().string();

    // create new path
    std::filesystem::path dirPath = filePath.parent_path();// / filename;

    // create folder
    if (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 first
    const 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 buffer
        for (size_t x = 0; x < width; ++x)
        {
            const size_t byteIdx = x / 8;
            const size_t bitPos  = 7 - (x % 8);  // MSB first

            if (data[y * width + x])
            {
                packed[byteIdx] |= (1 << bitPos);
            }
        }

        // write into file
        fwrite(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 255

    fwrite(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 test
    std::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 test
    std::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 test
    std::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 value
            ppmData[pos + 1] = y % 256;   // G, gradient value
            ppmData[pos + 2] = 128;       // B
        }
    }
    saveImgAsPPM(basePath + "_ppm", ppmData.data(), width, height);
    std::cout << "PPM Test finished.\n";

    return 0;
}


Refference

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值