首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >C++实现图片格式转换

C++实现图片格式转换

原创
作者头像
手撕代码八百里
发布于 2023-12-28 16:31:01
发布于 2023-12-28 16:31:01
59700
代码可运行
举报
文章被收录于专栏:猿计划猿计划
运行总次数:0
代码可运行

前言

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

环境安装

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

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

大题步骤如下:

1、引入opencv的头文件:

#include <opencv2/opencv.hpp>

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

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

jpg转png 案例

代码语言:python
代码运行次数:0
运行
AI代码解释
复制
#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
代码运行次数:0
运行
AI代码解释
复制
#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;
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
FFmpeg4.0笔记:本地媒体文件解码、帧格式转换、重采样、编码、封装等例子
https://github.com/gongluck/FFmpeg4.0-study/blob/master/official%20example/my_example.cpp
gongluck
2019/05/22
2.5K0
Qt加载本地图片转为YUV420P格式数据
在流媒体应用中,视频编码是必不可少的一环。视频编码的作用是将高带宽、高码率的原始视频流压缩成低带宽、低码率的码流,以便于传输和存储。H264是一种高效的视频编码标准,具有良好的压缩性能和广泛的应用范围,在实时流媒体应用中得到了广泛的应用。
DS小龙哥
2023/09/13
6710
Qt加载本地图片转为YUV420P格式数据
类型转换与IO流:C++世界的变形与交互之道
在现代编程中,C++作为一种强大的面向对象编程语言,其灵活性和高效性在开发中得到了广泛应用。类型转换和输入输出流(IO流)是C++语言的两个重要组成部分。前者是数据处理与操作的桥梁,后者是数据交互的核心。掌握这些内容不仅可以提高代码的健壮性,还能显著提升开发效率与代码可读性。本文将深入探讨C++中的类型转换和IO流机制,助您在实际应用中游刃有余。
suye
2024/12/20
2770
分享用于学习C++图像处理的代码示例
为了便于学习图像处理并研究图像算法, 俺写了一个适合初学者学习的小小框架。 麻雀虽小五脏俱全。 采用Decoder:stb_image https://github.com/nothings/stb/blob/master/stb_image.h 采用Encoder:tiny_jpeg https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h stb_image.h用于解析图片格式:  JPG, PNG, TGA, BMP, PSD, GIF
cpuimage
2018/04/12
2.1K0
C++高级主题系列篇
函数 A 在执行过程中发现异常时可以不加处理,而只是“拋出一个异常”给 A 的调用者,假定为函数 B。
用户9831583
2022/06/16
5190
C++高级主题系列篇
【工程应用五】 opencv中linemod模板匹配算法诸多疑惑和自我解读。
        研究这个前前后后也有快两三个月了,因为之前也一直在弄模板匹配方面的东西,所以偶尔还是有不少朋友咨询或者问你有没有研究过linemod这个算法啊,那个效率啥的还不错啊,有段时间一直不以为然,觉得我现在用的那个匹配因该很不错的,没必要深究了。后来呢,还是忍不住手痒,把论文打出来看了看,又找了点资料研究了下,结果没想到一弄又是两个月过去了,中间也折腾了很久,浪费了不少时间。总算还是有点收获,稍微整理下做个交流。
用户1138785
2022/05/09
1.6K0
【工程应用五】 opencv中linemod模板匹配算法诸多疑惑和自我解读。
c++ mnist转化为opecv Mat
本文主要介绍如何使用C++将mnist 数据集转化为Opencv Mat,问题来源主要代码以及运行示例如下:
bear_fish
2019/02/25
6190
c++ mnist转化为opecv Mat
C++:Armadillo与OpenCV矩阵数据mat、vec、Mat的格式转换
  本文介绍在C++语言中,矩阵库Armadillo的mat、vec格式数据与计算机视觉库OpenCV的Mat格式数据相互转换的方法。
疯狂学习GIS
2023/06/26
4780
C++:Armadillo与OpenCV矩阵数据mat、vec、Mat的格式转换
基于OpenCV实现手写体数字训练与识别
OpenCV实现手写体数字训练与识别 机器学习(ML)是OpenCV模块之一,对于常见的数字识别与英文字母识别都可以做到很高的识别率,完成这类应用的主要思想与方法是首选对训练图像数据完成预处理与特征提取,根据特征数据组成符合OpenCV要求的训练数据集与标记集,然后通过机器学习的KNN、SVM、ANN等方法完成训练,训练结束之后保存训练结果,对待检测的图像完成分割、二值化、ROI等操作之后,加载训练好的分类数据,就可以预言未知分类。 一:数据集 这里使用的数据集是mnist 手写体数字数据集、关于数据集的具
OpenCV学堂
2018/04/04
2.6K0
基于OpenCV实现手写体数字训练与识别
你该知道的C++四种显式类型转换
在C语言中,我们需要做类型转换时,常常就是简单粗暴,在C++中也可以用C式强制类型转换,但是C++有它自己的一套类型转换方式。
编程珠玑
2019/10/28
2K0
BGRA RGBA YUV420互相转换
void ConvertBGRAtoRGBA(BYTE* data, int width, int height)
Tomas7571
2023/06/29
1.7K0
BGRA RGBA YUV420互相转换
【C++】类型转换 ③ ( 重新解释类型转换 reinterpret_cast | 指针类型数据转换 )
C++ 静态类型转换 static_cast 可以完成 数据类型 转换 , 如 将 int 转为 double , 将 bool 转为 char , 等场景 ;
韩曙亮
2023/11/27
8460
【C++】类型转换 ③ ( 重新解释类型转换 reinterpret_cast | 指针类型数据转换 )
TensorRT + YOLOv5第六版C++部署全解
点击上方↑↑↑“OpenCV学堂”关注我 OpenCV单目相机标定,图像畸变校正 前言 之前对YOLOv5第六版分别在OpenCV DNN、OpenVINO、ONNXRUNTIME 上做了测试,因为版本兼容问题,一直无法在TensorRT上做测试,我当时跑CUDA11.0 + cuDNN8.4.x时候给我报的错误如下: Could not load library cudnn_cnn_infer64_8.dll. Error code 126Please make sure cudnn_cnn_infe
OpenCV学堂
2022/04/08
5.8K2
TensorRT + YOLOv5第六版C++部署全解
【机器学习】与【数据挖掘】技术下【C++】驱动的【嵌入式】智能系统优化
嵌入式系统是一种专用计算机系统,通常嵌入到大型系统中,执行特定任务。典型的嵌入式系统包括微控制器(MCU)、单板计算机(SBC)和专用AI加速器。嵌入式系统的主要特点包括:
小李很执着
2024/06/15
2040
C++版OpenCV使用支持向量机svm进行mnist手写数字识别
支持向量机svm也是一种机器学习算法,采用空间超平面进行数据分割,在这篇博客中我们将使用svm进行手写数字的识别,使用该算法,识别率可以达到96.72%。 环境准备: vs2015 OpenCV4.5.0 下面的代码为svm模型训练代码:
全栈程序员站长
2022/10/05
1.2K0
C++版OpenCV使用支持向量机svm进行mnist手写数字识别
C++雾中风景11:厘清C++之中的类型转换
开门见山,先聊聊笔者对类型转换的看法吧。从设计上看,一门面向对象的语言是不一样提供类型转换的,这种方式破坏了类型系统。C++为了兼容C也不得不吞下这个苦果,在实际进行编程工作的过程之中,并不太推荐大家使用类型转换。(Java在这里就做了一些妥协,在基本类型之中提供了类型转换。对于对象类型则不提供类型转换这种黑魔法)
HappenLee
2018/09/29
5000
C++中的显式类型转化
该文摘要总结:利用C++的static_cast, const_cast, reinterpret_cast, 以及dynamic_cast进行类型转换。static_cast简单而实用,适合大多数情况。const_cast用于去除对象的const属性。reinterpret_cast用于类型转换,但可能会丢失信息。dynamic_cast在运行时进行类型检查,可以安全地跨越继承层次。
弗兰克的猫
2018/01/09
1.9K0
yuv420格式(微信图片存储路径)
YUV,分为三个分量,“Y”表示明亮度,也就是灰度值;“U”和”V”表示的则是色度,作用是描述影像色彩饱和度,用于指定像素的颜色。YUV主流的采样方式有三种:YUV4:4:4,YUV4:2:2,YUV4:2:0,这里主要介绍下YUV420。
全栈程序员站长
2022/07/28
2.2K0
yuv420格式(微信图片存储路径)
字符动画播放器,不止BadApple!
libvlc解码转码出RGBA和播放音频,再将RGBA量化为黑('*')白(' ')两个颜色并输出到屏幕。
gongluck
2020/04/08
6950
C++版OpenCV使用神经网络ANN进行mnist手写数字识别[通俗易懂]
说起神经网络,很多人以为只有Keras或者tensorflow才支持,其实OpenCV也支持神经网络的,下面就使用OpenCV的神经网络进行手写数字识别,训练10次的准确率就高达96%。 环境准备: vs2015 OpenCV4.5.0 以下为ANN神经网络的训练代码:
全栈程序员站长
2022/09/07
1.1K0
推荐阅读
相关推荐
FFmpeg4.0笔记:本地媒体文件解码、帧格式转换、重采样、编码、封装等例子
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验