yuv图片简介
YUV图片是一种采用YUV颜色编码方法的图像格式。YUV将亮度信息(Y)与色彩信息(U和V)分离,其中Y代表明亮度(灰度值),U和V代表色度,用于描述影像色彩及饱和度。这种编码方式基于人眼对亮度比色彩敏感度更高的特点,通过降低色度带宽来优化彩色视频信号的传输,占用存储空间少,数据传输效率高,且能兼容黑白与彩色显示。YUV图片广泛应用于电视系统、视频处理及计算机视觉领域
代码
image_convert.cpp, 使用ffmpeg库
extern "c"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavutil/avutil.h"
#include "libswscale/swscale.h"
#include "libavutil/imgutils.h"
}
#include <stdint.h>
//g++ ./image_convert.cpp -lswscale -lavutil -lavformat -lavcodec
//ffplay -f rawvideo -pix_fmt bgra -video_size 480x320 ./480_320_rgb.img.rgb
struct AVFrame;
struct SwsContext;
class ImageConvert
{
public:
ImageConvert(int srcW, int srcH, int dstW, int dstH, int srcPixFmtType, int dstPixFmtType);
void Init(int srcW, int srcH, int dstW, int dstH, int srcPixFmtType, int dstPixFmtType);
void Release();
~ImageConvert();
bool Convert(const uint8_t *src);
bool Convert(const uint8_t *src, int srcW, int srcH, int dstW,
int dstH, int srcPixFmtType, int dstPixFmtType);
const uint8_t *GetData() const;
void Save(const char *filename) const;
private:
AVFrame *m_pDstFrame;
uint8_t *m_dstBuffer;
struct SwsContext *m_pSwsContext;
int m_srcW;
int m_srcH;
int m_dstW;
int m_dstH;
int m_srcPixFmtType;
int m_dstPixFmtType;
};
imageconvert::imageconvert(int srcw, int srch, int dstw, int dsth, int srcpixfmttype, int dstpixfmttype)
{
init(srcw, srch, dstw, dsth, srcpixfmttype, dstpixfmttype);
}
void imageconvert::init(int srcw, int srch, int dstw, int dsth, int srcpixfmttype, int dstpixfmttype)
{
m_srcw = srcw;
m_srch = srch;
m_dstw = dstw;
m_dsth = dsth;
//av_pix_fmt_yuv420p, av_pix_fmt_rgb32
m_srcpixfmttype = srcpixfmttype;
m_dstpixfmttype = dstpixfmttype;
m_pdstframe = av_frame_alloc();
//int numbytes = avpicture_get_size(av_pix_fmt_rgb32, dstw, dsth);
int numbytes = av_image_get_buffer_size((avpixelformat)m_dstpixfmttype, dstw, dsth, 1);
m_dstbuffer = (uint8_t *) av_malloc(numbytes * sizeof(uint8_t));
//avpicture_fill((avpicture *)m_pdstframe, m_dstbuffer, av_pix_fmt_rgb32, dstw, dsth);
av_image_fill_arrays(m_pdstframe->data, m_pdstframe->linesize, m_dstbuffer, (avpixelformat)m_dstpixfmttype, dstw, dsth, 1);
m_pswscontext = sws_getcontext(srcw, srch, (avpixelformat)m_srcpixfmttype,
dstw, dsth, (avpixelformat)m_dstpixfmttype, sws_bicubic, null, null, null);
}
imageconvert::~imageconvert()
{
release();
}
void imageconvert::release()
{
av_frame_free(&m_pdstframe);
av_free(m_dstbuffer);
sws_freecontext(m_pswscontext);
}
bool imageconvert::convert(const uint8_t *src)
{
return convert(src, m_srcw, m_srch, m_dstw, m_dsth, m_srcpixfmttype, m_dstpixfmttype);
}
bool imageconvert::convert(const uint8_t *src, int srcw, int srch, int dstw,
int dsth, int srcpixfmttype, int dstpixfmttype)
{
if (srcw != m_srcw || srch != m_srch || dstw != m_dstw || dsth != m_dsth
|| srcpixfmttype != m_srcpixfmttype || dstpixfmttype != m_dstpixfmttype)
{
release();
init(srcw, srch, dstw, dsth, m_srcpixfmttype, m_dstpixfmttype);
}
avframe *psrcframe = av_frame_alloc();
//avpicture_fill((avpicture *)psrcframe, src, av_pix_fmt_yuv420p, srcw, srch);
av_image_fill_arrays(psrcframe->data, psrcframe->linesize, src, (avpixelformat)m_srcpixfmttype, srcw, srch, 1);
sws_scale(m_pswscontext,
psrcframe->data,
psrcframe->linesize,
0,
m_srch,
m_pdstframe->data,
m_pdstframe->linesize);
}
const uint8_t *imageconvert::getdata() const
{
return m_dstbuffer;
}
void imageconvert::save(const char *filename) const
{
file *pfile = fopen(filename, "wb");
if (pfile == null)
return;
const uint8_t *data = getdata();
if (m_dstpixfmttype == av_pix_fmt_rgb32)
{
//int size = avpicture_get_size(av_pix_fmt_rgb32, m_dstw, m_dsth);
int size = av_image_get_buffer_size((avpixelformat)m_dstpixfmttype, m_dstw, m_dsth, 1);
fwrite(data, 1, size, pfile);
// close file
fclose(pfile);
}
else
{
printf("not implement\n");
}
}
int main(int argc, char **argv)
{
int srcw = 700;
int srch = 700;
int dstw = 480;
int dsth = 320;
imageconvert c(srcw, srch, dstw, dsth, av_pix_fmt_yuv420p, av_pix_fmt_rgb32);
file *fp = fopen(argv[1], "rb");
if (fp == null)
{
return -1;
}
uint8_t yuv[srcw*srch*3/2];
fread(yuv, sizeof(yuv), 1, fp);
c.convert(yuv);
c.save("480_320_rgb.img");
return 0;
}
使用方法
编译:
g++ ./image_convert.cpp -lswscale -lavutil -lavformat -lavcodec
./a.out 770_770.img
查看结果:
ffplay -f rawvideo -pix_fmt bgra -video_size 480x320 ./480_320_rgb.img
作者:帅得不敢出门