C++批量图片转换工具:多种格式转WebP

这是一个刚写的 C++ 实现的批量图片转换工具,能够将文件夹中的 JPG、JPEG、PNG 等格式图片转换为 WebP 格式。还可以,将就着用呗。

方案选择

有以下几种方案:

  1. OpenCV 方案:简单易用,适合快速开发

  2. FreeImage 方案:专为图像处理设计,支持多种格式

  3. CxImage 方案:功能强大,支持多种格式转换

但是我懒,就只使用OpenCV来实现呗,因为这玩意安装简单、文档丰富,且能满足基本需求。如果需要更专业的解决方案,可以考虑 FreeImage 或 CxImage。

实现代码

#include <iostream>
#include <vector>
#include <filesystem>
#include <opencv2/opencv.hpp>

namespace fs = std::filesystem;

// 转换单张图片为WebP格式
bool convertToWebP(const fs::path& inputPath, const fs::path& outputPath, int quality = 80) {
    try {
        // 读取原始图片
        cv::Mat image = cv::imread(inputPath.string());
        if (image.empty()) {
            std::cerr << "无法读取图片: " << inputPath << std::endl;
            return false;
        }

        // 准备输出参数
        std::vector<int> compression_params;
        compression_params.push_back(cv::IMWRITE_WEBP_QUALITY);
        compression_params.push_back(quality); // 质量参数(0-100)

        // 写入WebP格式
        bool success = cv::imwrite(outputPath.string(), image, compression_params);
        if (!success) {
            std::cerr << "转换失败: " << inputPath << std::endl;
            return false;
        }

        return true;
    } catch (const cv::Exception& e) {
        std::cerr << "OpenCV异常: " << e.what() << std::endl;
        return false;
    }
}

// 批量转换文件夹中的图片
void batchConvertToWebP(const fs::path& inputDir, const fs::path& outputDir, int quality = 80) {
    // 确保输出目录存在
    if (!fs::exists(outputDir)) {
        fs::create_directories(outputDir);
    }

    // 支持的图片扩展名
    const std::vector<std::string> supportedExtensions = {".jpg", ".jpeg", ".png", ".bmp", ".tif", ".tiff"};

    // 遍历输入目录
    int convertedCount = 0;
    for (const auto& entry : fs::directory_iterator(inputDir)) {
        if (entry.is_regular_file()) {
            fs::path inputPath = entry.path();
            std::string extension = inputPath.extension().string();

            // 转换为小写比较
            std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);

            // 检查是否支持该格式
            if (std::find(supportedExtensions.begin(), supportedExtensions.end(), extension) != supportedExtensions.end()) {
                // 构造输出路径
                fs::path outputPath = outputDir / inputPath.stem();
                outputPath += ".webp";

                // 转换图片
                if (convertToWebP(inputPath, outputPath, quality)) {
                    std::cout << "转换成功: " << inputPath << " -> " << outputPath << std::endl;
                    convertedCount++;
                }
            }
        }
    }

    std::cout << "转换完成! 共转换了 " << convertedCount << " 张图片." << std::endl;
}

int main(int argc, char* argv[]) {
    // 检查参数
    if (argc < 3) {
        std::cout << "用法: " << argv[0] << " <输入目录> <输出目录> [质量(0-100), 默认80]" << std::endl;
        return 1;
    }

    // 获取参数
    fs::path inputDir(argv[1](@ref);
    fs::path outputDir(argv[2](@ref);
    int quality = 80;

    if (argc >= 4) {
        quality = std::atoi(argv[3](@ref);
        quality = std::max(0, std::min(100, quality)); // 确保质量在0-100范围内
    }

    // 检查输入目录是否存在
    if (!fs::exists(inputDir) || !fs::is_directory(inputDir)) {
        std::cerr << "错误: 输入目录不存在或不是一个目录: " << inputDir << std::endl;
        return 1;
    }

    // 执行批量转换
    batchConvertToWebP(inputDir, outputDir, quality);

    return 0;
}

使用说明

  1. 编译要求

    • C++17 或更高版本

    • OpenCV 库(建议 4.x 版本)

    • 支持 filesystem 的编译器

  2. 编译命令(以 g++ 为例):

    g++ -std=c++17 -o image_converter image_converter.cpp `pkg-config --cflags --libs opencv4`
  3. 运行命令

    ./image_converter 输入目录 输出目录 [质量参数]
    • 质量参数可选,范围 0-100,默认 80

  4. 支持的输入格式

    • JPG/JPEG

    • PNG

    • BMP

    • TIFF/TIF

替代方案

如果你需要更专业的解决方案,可以考虑以下替代实现:

1. 使用FreeImage库

#include <iostream>
#include <vector>
#include <filesystem>
#include <FreeImage.h>

namespace fs = std::filesystem;

bool convertToWebP(const fs::path& inputPath, const fs::path& outputPath, int quality = 80) {
    // 初始化FreeImage
    FreeImage_Initialise();

    // 确定文件格式
    FREE_IMAGE_FORMAT fif = FreeImage_GetFileType(inputPath.string().c_str());
    if (fif == FIF_UNKNOWN) {
        fif = FreeImage_GetFIFFromFilename(inputPath.string().c_str());
    }

    if (fif == FIF_UNKNOWN) {
        std::cerr << "未知的图像格式: " << inputPath << std::endl;
        return false;
    }

    // 加载图像
    FIBITMAP* dib = FreeImage_Load(fif, inputPath.string().c_str());
    if (!dib) {
        std::cerr << "无法加载图像: " << inputPath << std::endl;
        return false;
    }

    // 设置WebP质量
    FreeImage_SetMetadata(FIMD_WEBP_QUALITY, dib, "quality", std::to_string(quality).c_str());

    // 保存为WebP
    BOOL success = FreeImage_Save(FIF_WEBP, dib, outputPath.string().c_str());
    FreeImage_Unload(dib);

    // 释放FreeImage资源
    FreeImage_DeInitialise();

    return success;
}

// batchConvertToWebP和main函数与OpenCV版本类似

2. 使用CxImage库

#include <iostream>
#include <vector>
#include <filesystem>
#include "ximage.h"

namespace fs = std::filesystem;

bool convertToWebP(const fs::path& inputPath, const fs::path& outputPath, int quality = 80) {
    CxImage image;
    if (!image.Load(inputPath.string().c_str())) {
        std::cerr << "无法加载图像: " << inputPath << std::endl;
        return false;
    }

    image.SetCodecOption(quality); // 设置质量
    return image.Save(outputPath.string().c_str(), CXIMAGE_FORMAT_WEBP);
}

// batchConvertToWebP和main函数与OpenCV版本类似

性能优化建议

  1. 多线程处理:对于大量图片,可以使用多线程加速转换过程

  2. 批量处理:如 OpenCL 方案所示,可以利用 GPU 加速处理

  3. 内存优化:对于大图片,考虑分块处理

  4. 错误处理增强:添加更详细的错误日志和恢复机制

总结

以上代码提供了一个完整的 C++ 解决方案,用于将文件夹中的多种图片格式批量转换为 WebP 格式。OpenCV 版本简单易用,适合大多数场景。如果需要更专业的处理或更好的格式支持,可以考虑 FreeImage 或 CxImage 方案。


C++批量图片转换工具:多种格式转WebP
https://uniomo.com/archives/c-pi-liang-tu-pian-zhuan-huan-gong-ju-duo-zhong-ge-shi-zhuan-webp
作者
雨落秋垣
发布于
2025年10月21日
许可协议