二、基于QT
二、基于QT
本章目标:
RGB与YUV的原理SDL渲染图像的方法QT渲染图像的方法SDL与QT结合渲染图像的方法刷新SDL渲染的方式面向对象工厂模式封装方法窗口大小的变化与抗锯齿的处理
RGB像素格式原理
RGB与YUV像素格式基础
1. 渲染RGB像素格式
1.1 通过SDL渲染SDL窗口
创建SDL的窗口、渲染器、纹理创建RGB图像数据纹理通过渲染器渲染RGB数据
二、基于QT
本章目标:
- RGB与YUV的原理
- SDL渲染图像的方法
- QT渲染图像的方法
- SDL与QT结合渲染图像的方法
- 刷新SDL渲染的方式
- 面向对象工厂模式封装方法
- 窗口大小的变化与抗锯齿的处理
RGB像素格式原理
RGB与YUV像素格式基础
1. 渲染RGB像素格式
1.1 通过SDL渲染SDL窗口
- 创建SDL的窗口、渲染器、纹理
- 创建RGB图像数据
- 纹理通过渲染器渲染RGB数据到窗口
#include <iostream>
#include <sdl/SDL.h>
using namespace std;
#pragma comment(lib,SDL2.lib)
#undef main
int main(int argc, char* ar[])
{int w = 800;int h = 600;//1 初始化SDL video库if (SDL_Init(SDL_IIT_VIDEO)){cout << SDL_GetError() << endl;return -1;}//2 生成SDL 窗口auto screen = SDL_CreateWindow(test sdl ffmpeg,SDL_WIDOWPOS_CETERED,//窗口位置SDL_WIDOWPOS_CETERED,w,h,SDL_WIDOW_OPEGL|SDL_WIDOW_RESIZABLE);if (!screen){cout << SDL_GetError() << endl;return -2;}// 生成渲染器auto render = SDL_CreateRenderer(screen, -1, SDL_REDERER_ACCELERATED);if (!render){cout << SDL_GetError() << endl;return -;}//4 生成材质auto texture = SDL_CreateTexture(render, SDL_PIXELFORMAT_ARGB8888,SDL_TEXTUREACCESS_STREAMIG,// 可加锁w, h);if (!texture){cout << SDL_GetError() << endl;return -4;}// 存放图像的数据shared_ptr<unsigned char> rgb(new unsigned char[w * h * 4]);auto r = rgb.get();unsigned char tmp = 255;for (;;){//判断退出SDL_Event ev;SDL_WaitEventTimeout(&ev, 10);if ( == SDL_QUIT){SDL_DestroyWindow(screen);break;}tmp--;for (int j = 0; j < h; j){int b = j * w * 4;for (int i = 0; i < w*4; i = 4){r[b i] = 0; //Br[b i 1] = 0; //Gr[b i 2] = tmp; //Rr[b i ] = 0; //A}}//5 内存数据写入材质SDL_UpdateTexture(texture, ULL, r, w * 4);//6 清理屏幕SDL_RenderClear(render);SDL_Rect sdl_rect;sdl_rect.x = 0;sdl_rect.y = 0;sdl_rect.w = w;sdl_rect.h = h;//7 复制材质到渲染器SDL_RenderCopy(render, texture,ULL,//原图位置和尺寸ULL//&sdl_rect//目标位置和尺寸);//8 渲染SDL_RenderPresent(render);}getchar();return 0;
}
1.2 通过SDL渲染QT控件、通过定时器刷新渲染窗口
- 创建QT Lebel控件,及设置其标题、尺寸等属性
- SDL的窗口创建参数改自定义为Leble控件
- 重载定时器处理事件,内容为渲染图像
- 设置并启动定时器
#include sdlqtrgb.h
#include <sdl/SDL.h>
#pragma comment(lib,SDL2.lib)
static SDL_Window* sdl_win = ULL;
static SDL_Renderer* sdl_render = ULL;
static SDL_Texture* sdl_texture = ULL;
static int sdl_width = 0;
static int sdl_height = 0;
static unsigned char* rgb = ULL;
static int pix_size = 4;
void SdlQtRGB::timerEvent(QTimerEvent* ev)
{static unsigned char tmp = 255;tmp--;for (int j = 0; j < sdl_height; j){int b = j * sdl_width* pix_size;for (int i = 0; i < sdl_width * pix_size; i = pix_size){rgb[b i] = 0; //Brgb[b i 1] = tmp; //Grgb[b i 2] = 0; //Rrgb[b i ] = 0; //A}}SDL_UpdateTexture(sdl_texture, ULL, rgb, sdl_width * pix_size);SDL_RenderClear(sdl_render);SDL_Rect rect;rect.x = 0;rect.y = 0;rect.w = sdl_width;rect.h = sdl_height;SDL_RenderCopy(sdl_render,sdl_texture,ULL,&rect);SDL_RenderPresent(sdl_render);
}SdlQtRGB::SdlQtRGB(QWidget *parent): QWidget(parent)
{ui.setupUi(this);sdl_width = ui.label->width();sdl_height = ui.label->height();//初始化SDLSDL_Init(SDL_IIT_VIDEO);//创建窗口sdl_win = SDL_CreateWindowFrom((void*)ui.label->winId());//创建渲染器sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_REDERER_ACCELERATED);//创建材质sdl_texture = SDL_CreateTexture(sdl_render,SDL_PIXELFORMAT_ARGB8888,SDL_TEXTUREACCESS_STREAMIG,sdl_width,sdl_height);rgb = new unsigned char[sdl_width * sdl_height * pix_size];startTimer(10);
}
1. 合并两幅RGB图像
- 重新定义要渲染的纹理大小:宽为两张图相加,高为最高的图高度。
- 遍历两张图片的每一行,将B图片的第n行像素拷贝到A图片的第n行之后
- 保存合并的图片,并渲染显示。
#include sdlqtrgb.h
#include <QMessageBox>
#include <sdl/SDL.h>
#pragma comment(lib,SDL2.lib)
static SDL_Window* sdl_win = ULL;
static SDL_Renderer* sdl_render = ULL;
static SDL_Texture* sdl_texture = ULL;
static int sdl_width = 0;
static int sdl_height = 0;
static unsigned char* rgb = ULL;
static int pix_size = 4;
void SdlQtRGB::timerEvent(QTimerEvent* ev)
{static unsigned char tmp = 255;tmp--;for (int j = 0; j < sdl_height; j){int b = j * sdl_width* pix_size;for (int i = 0; i < sdl_width * pix_size; i = pix_size){//rgb[b i] = 0; //B//rgb[b i 1] = tmp; //G//rgb[b i 2] = 0; //R//rgb[b i ] = 0; //A}}SDL_UpdateTexture(sdl_texture, ULL, rgb, sdl_width * pix_size);SDL_RenderClear(sdl_render);SDL_Rect rect;rect.x = 0;rect.y = 0;rect.w = sdl_width;rect.h = sdl_height;SDL_RenderCopy(sdl_render,sdl_texture,ULL,&rect);SDL_RenderPresent(sdl_render);
}SdlQtRGB::SdlQtRGB(QWidget *parent): QWidget(parent)
{ui.setupUi(this);sdl_width = ui.label->width();sdl_height = ui.label->height();//初始化SDLSDL_Init(SDL_IIT_VIDEO);//创建窗口sdl_win = SDL_CreateWindowFrom((void*)ui.label->winId());//创建渲染器sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_REDERER_ACCELERATED);QImage img1(001.png);QImage img2(002.png);if (img1.isull() || img2.isull()){QMessageBox::information(this, , open image failed!);return;}int out_w = img1.width() img2.width();int out_h = img1.height();if (out_h < img2.height())out_h = img2.height();sdl_width = out_w;sdl_height = out_h;resize(sdl_width, sdl_height);ui.label->move(0, 0);ui.label->resize(sdl_width, sdl_height);//创建材质sdl_texture = SDL_CreateTexture(sdl_render,SDL_PIXELFORMAT_ARGB8888,SDL_TEXTUREACCESS_STREAMIG,sdl_width,sdl_height);rgb = new unsigned char[sdl_width * sdl_height * pix_size];//默认设置为透明memset(rgb, 0, sdl_width * sdl_height * pix_size);//合并两幅图像for (int i = 0; i < sdl_height; i){int b = i * sdl_width * pix_size;if (i < img1.height())memcpy(rgb b, img1.scanLine(i), img1.width() * pix_size);b = img1.width() * pix_size;if (i < img2.height())memcpy(rgb b, img2.scanLine(i), img2.width() * pix_size);}QImage out(rgb, sdl_width, sdl_height, QImage::Format_ARGB2);out.save(out.png);startTimer(10);
}
2. 渲染YUV像素格式
2.1 通过刷新渲染来播放YUV数据
注意:渲染YUV与渲染RGB的区别
- 读取YUV数据时的数据量与YUV不同
- 更新纹理时,每一行的数据两也不同
- 上面的区别主要因为RGB与YUV再内存中的存储方式不同。
#include sdlqtrgb.h
#include <sdl/SDL.h>
#include <fstream>
#include <QMessageBox>
using namespace std;
#pragma comment(lib,SDL2.lib)
static SDL_Window* sdl_win = ULL;
static SDL_Renderer* sdl_render = ULL;
static SDL_Texture* sdl_texture = ULL;
static int sdl_width = 0;
static int sdl_height = 0;
static unsigned char* yuv = ULL;
static int pix_size = 2;
static ifstream yuv_file;
void SdlQtRGB::timerEvent(QTimerEvent* ev)
{yuv_file.read((char*)yuv, sdl_width * sdl_height * 1.5);//yuv 平面存储存储// yyyyyyyy uu vvSDL_UpdateTexture(sdl_texture, ULL, yuv, sdl_width //一行 y的字节数);SDL_RenderClear(sdl_render);SDL_Rect rect;rect.x = 0;rect.y = 0;rect.w = sdl_width;rect.h = sdl_height;SDL_RenderCopy(sdl_render,sdl_texture,ULL,&rect);SDL_RenderPresent(sdl_render);
}SdlQtRGB::SdlQtRGB(QWidget *parent): QWidget(parent)
{//打开yuv文件yuv_(400_00_25.yuv, ios::binary);if (!yuv_file){QMessageBox::information(this, , open yuv failed!);return;}ui.setupUi(this);sdl_width = 400; sdl_height = 00;ui.label->resize(sdl_width, sdl_height);//初始化SDLSDL_Init(SDL_IIT_VIDEO);//创建窗口sdl_win = SDL_CreateWindowFrom((void*)ui.label->winId());//创建渲染器sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_REDERER_ACCELERATED);//创建材质 支持YUVsdl_texture = SDL_CreateTexture(sdl_render,SDL_PIXELFORMAT_IYUV,SDL_TEXTUREACCESS_STREAMIG,sdl_width,sdl_height);yuv = new unsigned char[sdl_width * sdl_height * pix_size];startTimer(10);
}
2.2 随窗口自动缩放、抗锯齿、SDL窗口退出
自动缩放画面
需要搞清楚窗口、Qt label、SDL_Rect之间的关系
- 窗口可以根据Qt Label来创建,也可以通过SDL自定义窗口
- 若是根据Qt的winId创建的窗口,则渲染画面显示在窗口中;若SDL自定义的窗口,则渲染在单独画面,而不是再自定义的窗口中
- SDL_Rect的大小代表画面的大小,ULL表示渲染全部。
- Qt Lable只有通过winId创建的窗口才有效,代表渲染的尺寸。
若是根据Qt的winId创建的窗口:创建一个resize事件处理函数,当触发时,让lable的大小随窗口的大小变化,让SDL_Rect为ULL,画面就会随着label大小变化,lable也随着窗口大小变化,实现画面随着窗口大小变化;也可以让QtLable和SDL_Rect的width和height都随窗口的大小直接变化。
若是SDL自定义的窗口:渲染画面与窗口不在同一个窗口,而且QtLable无意义,所以直接让SDL_Rect为ULL即可。因为二者不是在同一个窗口,所以虽然可以让SDL_Rect的width和height随着自定义窗口变化,但无法控制SDL_Rect本身渲染的窗口大小。
抗锯齿:在创建纹理之前,设置渲染的质量
SDL窗口退出:若是根据QtWinID创建的窗口,退出时可直接窗口;但SDL自定义的窗口和渲染窗口不是一个窗口,因此点击渲染窗口退出无效,只有点击自定义窗口才能推出。为了解决这个问题,可以通过SDL事件来解决,当sdl的事件是退出事件时,就销毁创建的窗口、渲染器、纹理。
#include sdlqtrgb.h
#include <sdl/SDL.h>
#include <fstream>
#include <iostream>
#include <QMessageBox>
using namespace std;
#pragma comment(lib,SDL2.lib)
static SDL_Window* sdl_win = ULL;
static SDL_Renderer* sdl_render = ULL;
static SDL_Texture* sdl_texture = ULL;
static int sdl_width = 0;
static int sdl_height = 0;
static unsigned char* yuv = ULL;
static int pix_size = 2;
static ifstream yuv_file;
static bool isExit;void SdlQtRGB::timerEvent(QTimerEvent* ev)
{if (isExit){return;}//SDL窗口推出SDL_Event qev;SDL_WaitEventTimeout(&qev, 1);if (q == SDL_QUIT){SDL_DestroyTexture(sdl_texture);sdl_texture = nullptr;SDL_DestroyRenderer(sdl_render);sdl_render = nullptr;SDL_DestroyWindow(sdl_win);sdl_win = nullptr;isExit = true;return;}yuv_file.read((char*)yuv, sdl_width * sdl_height * 1.5);//yuv 平面存储存储// yyyyyyyy uu vvSDL_UpdateTexture(sdl_texture, ULL, yuv, sdl_width //一行 y的字节数);SDL_RenderClear(sdl_render);//SDL_Rect rect;//rect.x = 0;//rect.y = 0;//rect.w = sdl_width;//rect.h = sdl_height;//随窗口自动缩放画面SDL_RenderCopy(sdl_render,sdl_texture,ULL, ULL);SDL_RenderPresent(sdl_render);
}void SdlQtRGB::resizeEvent(QResizeEvent* ev)
{ui.label->move(0, 0);ui.label->resize(size());
}SdlQtRGB::SdlQtRGB(QWidget *parent): QWidget(parent)
{//打开yuv文件yuv_(400_00_25.yuv, ios::binary);if (!yuv_file){QMessageBox::information(this, , open yuv failed!);return;}ui.setupUi(this);sdl_width = 400; sdl_height = 00;ui.label->move(0, 0);ui.label->resize(size());//初始化SDLSDL_Init(SDL_IIT_VIDEO);//抗锯齿SDL_SetHint(SDL_HIT_REDER_SCALE_QUALITY, 1);//创建窗口//sdl_win = SDL_CreateWindowFrom((void*)ui.label->winId());sdl_win = SDL_CreateWindow(,SDL_WIDOWPOS_CETERED,SDL_WIDOWPOS_CETERED,sdl_width, sdl_height,SDL_WIDOW_OPEGL | SDL_WIDOW_RESIZABLE);//创建渲染器sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_REDERER_ACCELERATED);//创建材质 支持YUVsdl_texture = SDL_CreateTexture(sdl_render,SDL_PIXELFORMAT_IYUV,SDL_TEXTUREACCESS_STREAMIG,sdl_width,sdl_height);yuv = new unsigned char[sdl_width * sdl_height * pix_size];isExit = false;startTimer(10);
}
. 面向对象封装
#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格
上传时间: 2024-02-10 07:37:16
下一篇:抠图再也不用ps啦
推荐阅读
留言与评论(共有 10 条评论) |
本站网友 尚都 | 16分钟前 发表 |
SDL2.lib) static SDL_Window* sdl_win = ULL; static SDL_Renderer* sdl_render = ULL; static SDL_Texture* sdl_texture = ULL; static int sdl_width = 0; static int sdl_height = 0; static unsigned char* rgb = ULL; static int pix_size = 4; void SdlQtRGB | |
本站网友 文华苑一期 | 5分钟前 发表 |
w | |
本站网友 天域凯莱 | 21分钟前 发表 |
timerEvent(QTimerEvent* ev) {yuv_file.read((char*)yuv | |
本站网友 士郎正宗 | 5分钟前 发表 |
ULL | |
本站网友 葛博士 | 29分钟前 发表 |
sdl_width //一行 y的字节数);SDL_RenderClear(sdl_render);//SDL_Rect rect;//rect.x = 0;//rect.y = 0;//rect.w = sdl_width;//rect.h = sdl_height;//随窗口自动缩放画面SDL_RenderCopy(sdl_render | |
本站网友 益智仁的功效与作用 | 15分钟前 发表 |
sdl_texture | |
本站网友 阴鸷 | 25分钟前 发表 |
resizeEvent(QResizeEvent* ev) {ui.label->move(0 | |
本站网友 snh | 9分钟前 发表 |
sdl_height);ui.label->move(0 | |
本站网友 慧芝湖花园三期 | 5分钟前 发表 |
open yuv failed!);return;}ui.setupUi(this);sdl_width = 400; sdl_height = 00;ui.label->resize(sdl_width |