C++实现图片格式转换

2023-12-29 00:31:01 浏览数 (3)

前言

在C 中很多地方需要用到图片,图片格式的转换成了难题。不过,可以使用一些库来实现图片格式的转换。其中,OpenCV 是一个广泛使用的计算机视觉库,它提供了许多图像处理和转换的功能。本文将用一些简单的实例来展示如何使用 OpenCV 进行图片格式的转换。

环境安装

如果你不想编译的话,如果你是在Ubuntu下可以使用apt命令安装opencv库:

代码语言:shell复制
sudo apt-get install libopencv-dev

大题步骤如下:

1、引入opencv的头文件:

#include <opencv2/opencv.hpp>

2、然后使用cv::imread()函数可以读取一张图片;

3、使用cv::imwrite()函数输出转换后的图片;

jpg转png 案例

代码语言:python代码运行次数:0复制
#include <opencv2/opencv.hpp>

int main() {
    // 读取输入图片
    cv::Mat inputImage = cv::imread("input.jpg");

    // 检查图片是否成功加载
    if (inputImage.empty()) {
        std::cerr << "Error: Could not read input image." << std::endl;
        return -1;
    }

    // 定义输出图片的文件名和格式
    std::string outputFileName = "output.png";

    // 将图片格式从 JPEG 转换为 PNG
    cv::imwrite(outputFileName, inputImage);

    std::cout << "Image conversion completed. Output file: " << outputFileName << std::endl;

    return 0;
}

YUV直接转BMP

C/C 也可以直接将YUV等数据转成想要的图片,这个时候就需要了解这些编码格式的原理了。例如下面我举例子为YUV转BMP的:

代码语言:c复制
#include <iostream>
#include <fstream>
#include <vector>

// 保存YUV数据的结构体
struct YUVData {
    std::vector<unsigned char> y;
    std::vector<unsigned char> u;
    std::vector<unsigned char> v;
    int width;
    int height;
};

// 从YUV文件中读取数据
YUVData readYUV(const char* filename, int width, int height) {
    std::ifstream file(filename, std::ios::binary);

    if (!file.is_open()) {
        std::cerr << "Error: Could not open YUV file." << std::endl;
        exit(-1);
    }

    YUVData data;
    data.width = width;
    data.height = height;

    // 计算YUV数据的大小
    size_t size = width * height * 3 / 2;

    // 读取YUV数据
    data.y.resize(width * height);
    file.read(reinterpret_cast<char*>(data.y.data()), width * height);

    data.u.resize(width * height / 4);
    file.read(reinterpret_cast<char*>(data.u.data()), width * height / 4);

    data.v.resize(width * height / 4);
    file.read(reinterpret_cast<char*>(data.v.data()), width * height / 4);

    file.close();

    return data;
}

// 将YUV数据写入BMP文件
void writeBMP(const char* filename, const YUVData& data) {
    std::ofstream file(filename, std::ios::binary);

    if (!file.is_open()) {
        std::cerr << "Error: Could not open BMP file." << std::endl;
        exit(-1);
    }

    // BMP文件头
    const char bmpHeader[] = {
        'B', 'M', // 文件类型
        0, 0, 0, 0, // 文件大小(待填充)
        0, 0, 0, 0, // 保留字段
        54, 0, 0, 0, // 数据偏移

        40, 0, 0, 0, // 信息头大小
        0, 0, 0, 0, // 图像宽度
        0, 0, 0, 0, // 图像高度
        1, 0, // 颜色平面数
        24, 0, // 每像素位数
        0, 0, 0, 0, // 压缩类型
        0, 0, 0, 0, // 图像数据大小
        0, 0, 0, 0, // 水平分辨率
        0, 0, 0, 0, // 垂直分辨率
        0, 0, 0, 0, // 颜色表大小
        0, 0, 0, 0, // 重要颜色数
    };

    // 填充文件大小和图像宽度、高度字段
    *reinterpret_cast<int*>(&bmpHeader[2]) = 54   data.width * data.height * 3;
    *reinterpret_cast<int*>(&bmpHeader[18]) = data.width;
    *reinterpret_cast<int*>(&bmpHeader[22]) = data.height;

    // 写入BMP文件头
    file.write(bmpHeader, sizeof(bmpHeader));

    // 写入BMP数据(BGR格式)
    for (int y = data.height - 1; y >= 0; --y) {
        for (int x = 0; x < data.width;   x) {
            unsigned char Y = data.y[y * data.width   x];
            unsigned char U = data.u[(y / 2) * (data.width / 2)   (x / 2)];
            unsigned char V = data.v[(y / 2) * (data.width / 2)   (x / 2)];

            // 转换YUV到BGR
            int C = Y - 16;
            int D = U - 128;
            int E = V - 128;

            int R = std::clamp((298 * C   409 * E   128) >> 8, 0, 255);
            int G = std::clamp((298 * C - 100 * D - 208 * E   128) >> 8, 0, 255);
            int B = std::clamp((298 * C   516 * D   128) >> 8, 0, 255);

            // 写入BGR数据
            file.put(static_cast<char>(B));
            file.put(static_cast<char>(G));
            file.put(static_cast<char>(R));
        }
    }

    file.close();
}

int main() {
    // 设置图像的宽度和高度
    int width = 640;
    int height = 480;

    // 读取YUV数据
    YUVData yuvData = readYUV("input.yuv", width, height);

    // 将YUV数据写入BMP文件
    writeBMP("output.bmp", yuvData);

    std::cout << "Conversion completed. Output file: output.bmp" << std::endl;

    return 0;
}

0 人点赞