前言
在C++中很多地方需要用到图片,图片格式的转换成了难题。不过,可以使用一些库来实现图片格式的转换。其中,OpenCV 是一个广泛使用的计算机视觉库,它提供了许多图像处理和转换的功能。本文将用一些简单的实例来展示如何使用 OpenCV 进行图片格式的转换。
环境安装
如果你不想编译的话,如果你是在Ubuntu下可以使用apt命令安装opencv库:
sudo apt-get install libopencv-dev
大题步骤如下:
1、引入opencv的头文件:
#include <opencv2/opencv.hpp>
2、然后使用cv::imread()函数可以读取一张图片;
3、使用cv::imwrite()函数输出转换后的图片;
jpg转png 案例
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的:
// 保存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; | |
} |