当前位置: 首页 > news >正文

ubuntu18.04 OpenGL开发(显示YUV)

源码参考:https://download.csdn.net/download/weixin_55163060/88382816

安装opengl库

sudo apt install libglu1-mesa-dev freeglut3-dev mesa-common-dev
安装opengl工具包
sudo apt install mesa-utils
检查opengl版本信息(桌面终端执行)
sudo glxinfo | grep "OpenGL version"
显示:OpenGL version string: 3.3 (Compatibility Profile) Mesa 20.0.8
安装glfw窗口管理器
sudo apt-get install cmake xorg-dev libglu1-mesa-dev
wget https://sourceforge.net/projects/glfw/files/glfw/3.3.5/glfw-3.3.5.zip(wget https://github.com/glfw/glfw/releases/download/3.3.5/glfw-3.3.5.zip)
unzip glfw-3.3.5.zip
cd glfw-3.3.5
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX=/usr/local ..
make -j8
sudo make install
【window.c】 
#include <GLFW/glfw3.h>
#include <stdio.h>int main(void)
{GLFWwindow* window;/* Initialize the library */if (!glfwInit())return -1;/* Create a windowed mode window and its OpenGL context */window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);if (!window){glfwTerminate();return -1;}/* Make the window's context current */glfwMakeContextCurrent(window);/* Loop until the user closes the window */while (!glfwWindowShouldClose(window)){//glClearColor()命令指定了清除背景时用的颜色值,这里的(1,0,0,1)代表RGB中的红色,末尾的1表示不透明度glClearColor(1.0, 0.0, 0.0, 1.0);
        /* Render here */glClear(GL_COLOR_BUFFER_BIT);/* Swap front and back buffers */glfwSwapBuffers(window);/* Poll for and process events */glfwPollEvents();}glfwTerminate();return 0;
}
编译
gcc -o window window.c -lglfw3 -lGL -lX11 -lm -lpthread -ldl
执行显示一个红色窗口
【linmath.h】
https://github.com/datenwolf/linmath.h/blob/master/linmath.h
一个精简的线性数学库,旨在进行图形编程。 支持vec3,vec4,mat4x4和四元数
【GLAD库】(初始化后调用gl函数编译不会报错)
https://glad.dav1d.de/
GLAD是用来管理OpenGL的函数指针的,所以在调用任何OpenGL的函数之前我们需要初始化GLAD。GLAD也可以使OpenGL基础渲染变得简单。
【triangle.c】
//! [code]
#include "glad.h"
#define GLAD_GL_IMPLEMENTATION
#include <GL/gl.h>
//#include "glad.h"
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>#include "linmath.h"#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>typedef struct Vertex
{vec2 pos;vec3 col;
} Vertex;static const Vertex vertices[3] =
{{ { -0.6f, -0.4f }, { 1.f, 0.f, 0.f } },{ {  0.6f, -0.4f }, { 0.f, 1.f, 0.f } },{ {   0.f,  0.6f }, { 0.f, 0.f, 1.f } }
};static const char* vertex_shader_text =
"#version 330\n"
"uniform mat4 MVP;\n"
"in vec3 vCol;\n"
"in vec2 vPos;\n"
"out vec3 color;\n"
"void main()\n"
"{\n"
"    gl_Position = MVP * vec4(vPos, 0.0, 1.0);\n"
"    color = vCol;\n"
"}\n";static const char* fragment_shader_text =
"#version 330\n"
"in vec3 color;\n"
"out vec4 fragment;\n"
"void main()\n"
"{\n"
"    fragment = vec4(color, 1.0);\n"
"}\n";static void error_callback(int error, const char* description)
{fprintf(stderr, "Error: %s\n", description);
}static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)glfwSetWindowShouldClose(window, GLFW_TRUE);
}int main(void)
{glfwSetErrorCallback(error_callback);if (!glfwInit())exit(EXIT_FAILURE);glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);GLFWwindow* window = glfwCreateWindow(640, 480, "OpenGL Triangle", NULL, NULL);if (!window){glfwTerminate();exit(EXIT_FAILURE);}glfwSetKeyCallback(window, key_callback);glfwMakeContextCurrent(window);
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){return -1;}glfwSwapInterval(1);// NOTE: OpenGL error checks have been omitted for brevityGLuint vertex_buffer;glGenBuffers(1, &vertex_buffer);glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);const GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL);glCompileShader(vertex_shader);const GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL);glCompileShader(fragment_shader);const GLuint program = glCreateProgram();glAttachShader(program, vertex_shader);glAttachShader(program, fragment_shader);glLinkProgram(program);const GLint mvp_location = glGetUniformLocation(program, "MVP");const GLint vpos_location = glGetAttribLocation(program, "vPos");const GLint vcol_location = glGetAttribLocation(program, "vCol");GLuint vertex_array;glGenVertexArrays(1, &vertex_array);glBindVertexArray(vertex_array);glEnableVertexAttribArray(vpos_location);glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE,sizeof(Vertex), (void*) offsetof(Vertex, pos));glEnableVertexAttribArray(vcol_location);glVertexAttribPointer(vcol_location, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex), (void*) offsetof(Vertex, col));while (!glfwWindowShouldClose(window)){int width, height;glfwGetFramebufferSize(window, &width, &height);const float ratio = width / (float) height;glViewport(0, 0, width, height);glClear(GL_COLOR_BUFFER_BIT);mat4x4 m, p, mvp;mat4x4_identity(m);mat4x4_rotate_Z(m, m, (float) glfwGetTime());mat4x4_ortho(p, -ratio, ratio, -1.f, 1.f, 1.f, -1.f);mat4x4_mul(mvp, p, m);glUseProgram(program);glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) &mvp);glBindVertexArray(vertex_array);glDrawArrays(GL_TRIANGLES, 0, 3);glfwSwapBuffers(window);glfwPollEvents();}glfwDestroyWindow(window);glfwTerminate();exit(EXIT_SUCCESS);
}//! [code]
编译
gcc -o triangle glad.c triangle.c -lglfw3 -lGL -lX11 -lm -lpthread -ldl
执行程序显示旋转的三角形
【YUV描述】
一般RGB用于渲染,YUV用于传输。
YUV4:4:4:完全采用表示每个像素点都有一个Y,U,V。一个YUV占 8+8+8 = 24bits,3个字节。
YUV4:2:2: 就是2:1的水平取样,垂直完全采样,表示水平的两个像素有两个Y但是只有一个U一个V的采用格式。一个YUV占 8+4+4 = 16bits 2个字节。
YUV4:2:0:就是2:1的水平取样,2:1的垂直采样,表示上下左右四个像素点有4个Y但是只取一个U和一个V,一个YUV占 8+2+2 = 12bits 1.5个字节
planar的YUV格式表示先连续存储所有像素点的Y,再紧接着存储所有的U,再就是V。Y、U和V组件存储为三个独立的数组中。
packed的YUV格式表示每个像素点的YUV是连续交替存储的,先存储像素点1的YUV再存在像素点2的YUV像素点。Y、U和V组件存储在一个数组中。每个像素点的Y,U,V是连续交错存储的
YUV420P(YU12和YV12)格式
YU12:安卓的模式。存储顺序是先存Y,再存U,最后存V。YYYYYYYY UUVV (I420格式)
YV12:存储顺序是先存Y,再存V,最后存U。YYYYYYYY VVUU
YUV420SP(NV12和NV21)格式
NV12 是 IOS 中有的模式,它的存储顺序是先存 Y 分量,再 UV 进行交替存储。
NV21 是 安卓 中有的模式,它的存储顺序是先存 Y 分量,在 VU 交替存储
【h264转YUV命令】
ffmpeg -i C:\Users\Administrator\Desktop\test.h264 -y -an -frames 1 -s 1920x1080 out.yuv
pause
【GLSL】
OpenGL着色语言(OpenGL Shading Language)是用来在OpenGL中着色编程的语言,也即开发人员写的短小的自定义程序,他们是在图形卡的GPU (Graphic Processor Unit图形处理单元)上执行的,代替了固定的渲染管线的一部分,使渲染管线中不同层次具有可编程性。比如:视图转换、投影转换等。GLSL(GL Shading Language)的着色器代码分成2个部分:Vertex Shader(顶点着色器)和Fragment(片断着色器),有时还会有Geometry Shader(几何着色器)。负责运行顶点着色的是顶点着色器。它可以得到当前OpenGL 中的状态,GLSL内置变量进行传递。GLSL其使用C语言作为基础高阶着色语言,避免了使用汇编语言或硬件规格语言的复杂性。
【yuv_show.cpp】
#include<string>
#include<fstream>
#include<sstream>
#include<iostream>
#include<stdio.h>
#include "glad.h"
#include <GLFW/glfw3.h>typedef unsigned char BYTE;
const unsigned int SCR_WIDTH = 500;
const unsigned int SCR_HEIGHT = 600;
const int len = 1920*1080 * 3/2;
BYTE YUVdata [len];unsigned int VBO = 0;
unsigned int VAO = 0;
unsigned int EBO = 0;
unsigned int texturePIC = 0;
int shaderProgram = 0;GLuint texIndexarray[3];
GLuint texUniformY = 99;
GLuint texUniformU = 99;
GLuint texUniformV = 99;void LoadPicture()
{glGenTextures(3, texIndexarray);//生成三个纹理索引glBindTexture(GL_TEXTURE_2D, texIndexarray[0]);//为bind的纹理设置环绕,过滤方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glBindTexture(GL_TEXTURE_2D, texIndexarray[1]);//为bind的纹理设置环绕,过滤方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glBindTexture(GL_TEXTURE_2D, texIndexarray[2]);//为bind的纹理设置环绕,过滤方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//使用着色器程序,返回采样器的序号glUseProgram(shaderProgram);//该语句必须要有;安装 指定着色器程序texUniformY = glGetUniformLocation(shaderProgram, "dataY");texUniformU = glGetUniformLocation(shaderProgram, "dataU");texUniformV = glGetUniformLocation(shaderProgram, "dataV");----------加载数据--------------------------------------------------------FILE* fp = fopen("./out.yuv","rb+");//I420int returns  =fread(YUVdata,1,len,fp);int w = 1920;int h = 1080;int ysize = w*h;int uvsize = w * h / 4;void* uptr = &YUVdata[ysize];void* vptr = &YUVdata[ysize * 5 / 4];//---------------------------------------------------------------------------glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, texIndexarray[0]);// texindexarray[0] =1//使用GL_red表示单通道,glfw3里边没有YUV那个GL属性;glTexImage2D(GL_TEXTURE_2D, 0 , GL_RED, w, h ,0, GL_RED,GL_UNSIGNED_BYTE ,YUVdata);glUniform1i(texUniformY,0);                //通过 glUniform1i 的设置,保证每个 uniform 采样器对应着正确的纹理单元;注意这里不能用tesindexarray[0];glActiveTexture(GL_TEXTURE1);glBindTexture(GL_TEXTURE_2D, texIndexarray[1]);glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, w/2, h/2, 0, GL_RED, GL_UNSIGNED_BYTE,uptr);glUniform1i(texUniformU, 1);glActiveTexture(GL_TEXTURE2);glBindTexture(GL_TEXTURE_2D, texIndexarray[2]);glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, w/2, h/2, 0, GL_RED, GL_UNSIGNED_BYTE,vptr);glUniform1i(texUniformV,2);glUseProgram(0);
}void render()
{glBindVertexArray(VAO);glUseProgram(shaderProgram);glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,0);//glDrawArrays(GL_TRIANGLE_FAN,0,4);也可glUseProgram(0);glBindVertexArray(0);
}void initmodule()
{//做个一模型;正方形;映射了顶点坐标和纹理坐标的对应关系float vertexs[] = {//顶点坐标-------纹理坐标(屏幕坐标翻转)1.0f,  1.0f, 0.0f,  1.0f, 0.0f,   1.0f, -1.0f, 0.0f,  1.0f, 1.0f,   -1.0f, -1.0f, 0.0f,  0.0f, 1.0f,   -1.0f,  1.0f, 0.0f,  0.0f, 0.0f    };//一个正方形是由两个三角形得来的;记录顶点的索引顺序unsigned int indexs[] = {0,1,3,1,2,3,};//做VAOglGenVertexArrays(1,&VAO);glBindVertexArray(VAO);//做VBOglGenBuffers(1, &VBO);glBindBuffer(GL_ARRAY_BUFFER, VBO);//创建显存空间glBufferData(GL_ARRAY_BUFFER,sizeof(vertexs), vertexs, GL_STATIC_DRAW);//设置索引缓冲glGenBuffers(1,&EBO);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indexs),indexs,GL_STATIC_DRAW);    //加载纹理图片,生成纹理LoadPicture();//设置第0个锚点,3个点,不需要归一化,跨度5个float可以读下一个点glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,5*sizeof(float),(void*)0);//打开顶点glEnableVertexAttribArray(0);//纹理属性设置,纹理在第一个锚点上(指定顶点数据)glVertexAttribPointer(1,2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));//打开纹理glEnableVertexAttribArray(1);//解除绑定VBOglBindBuffer(GL_ARRAY_BUFFER,0);//解绑VAOglBindVertexArray(0);}void initshader(const char* verpath,const char* fragpath)
{//编译shader,并记录shaderIDstd::string VerCode("");std::string fregCode("");//读文件std::ifstream  vShaderFile;std::ifstream  fShaderFile;vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);try{vShaderFile.open(verpath);fShaderFile.open(fragpath);std::stringstream vsstream, fsstream;vsstream << vShaderFile.rdbuf();fsstream << fShaderFile.rdbuf();VerCode = vsstream.str();fregCode = fsstream.str();}catch (const std::exception&){std::cout << "read file error" << std::endl;}const char* vshader = VerCode.c_str();const char* fshader = fregCode.c_str();//shader 编译连接unsigned int vertexID = 0, fragID = 0;char infoLog[512];//存储错误信息int  successflag = 0;vertexID = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertexID,1,&vshader,NULL );glCompileShader(vertexID);//获取编译是否成功glGetShaderiv(vertexID,GL_COMPILE_STATUS,&successflag);if (!successflag){glGetShaderInfoLog(vertexID,512,NULL,infoLog);std::string errstr(infoLog);std::cout << "v shader err"<<infoLog;}//fragfragID = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragID, 1, &fshader, NULL);glCompileShader(fragID);//获取编译是否成功glGetShaderiv(fragID, GL_COMPILE_STATUS, &successflag);if (!successflag){glGetShaderInfoLog(fragID, 512, NULL, infoLog);std::string errstr(infoLog);std::cout << "f shader err"<<infoLog;}//链接shaderProgram = glCreateProgram();glAttachShader(shaderProgram,vertexID);glAttachShader(shaderProgram,fragID);glBindAttribLocation(shaderProgram, 0, "aPos");glBindAttribLocation(shaderProgram, 1, "texCoord");glLinkProgram(shaderProgram);glGetProgramiv(shaderProgram,GL_LINK_STATUS,&successflag);if (!successflag){glGetShaderInfoLog(shaderProgram, 512, NULL, infoLog);std::string errstr(infoLog);std::cout << "link error";}//编译完成后,可以把中间的步骤程序删除glDeleteShader(vertexID);glDeleteShader(fragID);
}
void processInput(GLFWwindow *window)
{if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS){//将窗口设置为关闭,跳出循环glfwSetWindowShouldClose(window, true);}
}void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{glViewport(0, 0, width, height);
}int main()
{//glfw初始化glfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);//glfw创建窗口GLFWwindow* window = glfwCreateWindow(500, 600, "LearnOpenGL", NULL, NULL);if (window == NULL){printf("创建窗口失败");//终止glfwTerminate();return -1;}//显示窗口glfwMakeContextCurrent(window);//设置回调,当窗口大小调整后将调用该回调函数glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);// glad初始化if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){printf("加载失败");return -1;}initshader("vertexShader.glsl", "fragmentShader.glsl");//先编译着色器initmodule();// 使用循环达到循环渲染效果while (!glfwWindowShouldClose(window)){//自定义输入事件processInput(window);glClearColor(0.0f,0.0f,0.0f,1.0f);glClear(GL_COLOR_BUFFER_BIT);render();//交互缓冲区,否则显示空白glfwSwapBuffers(window);//输入输出事件,否则无法对窗口进行交互glfwPollEvents();}//终止渲染 关闭并清理glfw本地资源glfwTerminate();return 0;
}
【vertexShader.glsl】
#version 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec2 texCoord; out vec2 TexCoord;
void main()
{gl_Position = vec4(aPos.x,aPos.y,aPos.z,1.0);TexCoord = texCoord;
};
【fragmentShader.glsl】
#version 330 core
layout(location = 0) out vec4 FragColor;
in vec2 TexCoord;
uniform sampler2D dataY;
uniform sampler2D dataU;
uniform sampler2D dataV;
vec3 yuv;
vec3 rgb;
void main()
{yuv.x = texture2D(dataY, TexCoord).r-0.0625;yuv.y = texture2D(dataU, TexCoord).r-0.5;yuv.z = texture2D(dataV, TexCoord).r-0.5;rgb = mat3(1,              1,      1,     0,       -0.18732, 1.8556,    1.57481, -0.46813,      0) * yuv;   FragColor = vec4(rgb.x, rgb.y,rgb.z,1); 
};
【编译】
g++ -o yuv_show glad.c yuv_show.cpp -lglfw3 -lGL -lX11 -lm -lpthread -ldl
【运行】
1、报错:v shader err0:2(1): error: shader output explicit location requires GL_ARB_separate_shader_objects extension or GLSL 4.20
原因:fragmentShader.glsl和vertexShader.glsl搞反了
2、报错:段错误
解决方法:sudo ./yuv_show
注:render()函数中增加LoadPicture()并修改其为读取不同的yuv数据可以实现视频流的播放。

相关文章:

ubuntu18.04 OpenGL开发(显示YUV)

源码参考&#xff1a;https://download.csdn.net/download/weixin_55163060/88382816 安装opengl库 sudo apt install libglu1-mesa-dev freeglut3-dev mesa-common-dev 安装opengl工具包 sudo apt install mesa-utils 检查opengl版本信息&#xff08;桌面终端执行&#xff09…...

React(react18)中组件通信06——redux-toolkit + react-redux

React&#xff08;react18&#xff09;中组件通信06——redux-toolkit react-redux 1 前言1.1 redux 和 react-redux1.2 关于redux-toolkit1.2.1 官网1.2.2 为什么要用Redux Toolkit&#xff1f; 1.3 安装 Redux Toolkit1.4 Redux Toolkit相关API 2. 开始例子——官网例子2.1 …...

第七章 查找 九、B+树

目录 一、定义 二、B树需要满足的条件 三、重要考点 一、定义 1、B树是一种常用的数据结构&#xff0c;用于实现关系型数据库中的索引。 2、其特点是可以在磁盘等外存储器上高效地存储大量数据&#xff0c;并支持快速的查询、插入、删除等操作。 3、B树的结构类似于二叉搜…...

XPD911协议系列-集成同步降压多口互联控制器

产品描述&#xff1a; XPD911 是一款集成 USB Type-C、USB Power Delivery&#xff08;PD&#xff09; 3.1 以及 PPS、 QC3.0/3.0 /2.0 快充协议、华为 FCP/SCP/HVSCP 快充协议、三星 AFC 快充协议、VOOC 快充协议、MTK PE 快充协议、BC1.2 DCP 以及苹果设备 2.4A 充电规范的多…...

数字反转(蓝桥杯)

数字反转 题目描述 给定一个整数&#xff0c;请将该数各个位上数字反转得到一个新数。新数也应满足整数的常见形式&#xff0c;即除非给定的原数为零&#xff0c;否则反转后得到的新数的最高位数字不应为零&#xff08;参见实例 2&#xff09;。 输入描述 输入共 1 行&…...

十一.EtherCAT开发之microchip MCU D51+ LAN9253 的开发FOE应用(SPI directly 模式)

十一.EtherCAT开发之microchip MCU D51+ LAN9253 的开发FOE应用(SPI directly 模式) 文章目录 十一.EtherCAT开发之microchip MCU D51+ LAN9253 的开发FOE应用(SPI directly 模式)11.0 软件更新方式11.1 SSC TOOL配置11.2 MCU D51 FOE函数支持11.2.1 下载download11.2.2 上传up…...

【分布式计算】二、架构(Architectures)

1.中心化架构&#xff08;Centralized Architectures&#xff09; 1.1.经典C/S模型 服务器&#xff1a;一个或多个进程提供服务 客户端&#xff1a;一个或多个进程使用服务 客户端和服务器可以在不同的机器上 客户端遵循请求/回复模型 1.2.传统三层视图 用户界面层&#x…...

Springboot对MVC、tomcat扩展配置

Springboot在web层的开发基本都是采用Springmvc框架技术&#xff0c;但是Springmvc中的某些配置在boot是没有的&#xff0c;我们就应该根据自己的需求进行对mvc扩展配置 Springboot1.x版本如何配置 通过注解Configuration一个类&#xff0c;继承webmvcconfigureradapter&#…...

网络子网划分练习

网络子网划分练习 1.背景&#xff1a; 在一个仓储企业网络拓朴结构如图1-所示&#xff0c;该企业占地500亩。有五层办公楼1栋&#xff0c;大型仓库10栋。每栋仓库内、外部配置视频监控16台&#xff0c;共计安装视频监控160台&#xff0c;Switch A、服务器、防火墙、管理机、Rou…...

Leetcode刷题笔记--Hot51-60

1--环形链表II 主要思路&#xff1a; 快慢指针&#xff0c;快指针每次走两步&#xff0c;慢指针每次走一步&#xff1b; 第一次相遇时&#xff0c;假设慢指针共走了 f 步&#xff0c;则快指针走了 2f 步&#xff1b; 假设起点到环入口结点的长度为 a&#xff08;不包括入口结点…...

广告牌安全监测系统,用科技护航大型广告牌安全

城市的街头巷尾&#xff0c;处处可见高耸的广告牌&#xff0c;它们以各种形式和颜色吸引着行人的目光。然而&#xff0c;作为城市景观的一部分&#xff0c;广告牌的安全性常常被我们所忽视。广告牌量大面大&#xff0c;由于设计、材料、施工方法的缺陷&#xff0c;加上后期的检…...

volatile

什么是volatile volatile是Java提供的一种轻量级的同步机制。Java 语言包含两种内在的同步机制&#xff1a;同步块&#xff08;或方法&#xff09;和 volatile 变量&#xff0c;相比于synchronized&#xff08;synchronized通常称为重量级锁&#xff09;&#xff0c;volatile更…...

JAVA:实现Excel和PDF上下标

1、简介 最近项目需要实现26个小写字母的上下标功能,自己去网上找了所有Unicode的上下标形式,缺少一些关键字母,顾后面考虑自己创建上下标字体样式,以此来记录。 2、Excel Excel本身是支持上下标,我们可以通过Excel单元格的样式来设置当前字体上下标,因使用的是POI的m…...

AI写稿软件,最新的AI写稿软件有哪些

写作已经成为各行各业无法绕开的重要环节。不论是企业的广告宣传、新闻媒体的报道、还是个人自媒体的内容创作&#xff0c;文字都扮演着不可或缺的角色。随着信息的爆炸式增长&#xff0c;写作的需求也不断攀升&#xff0c;这使得许多人感到困扰。时间不够用、创意枯竭、写作技…...

干货:数据仓库基础知识(全)

1、什么是数据仓库&#xff1f; 权威定义&#xff1a;数据仓库是一个面向主题的、集成的、相对稳定的、反映历史变化的数据集合&#xff0c;用于支持管理决策。 1&#xff09;数据仓库是用于支持决策、面向分析型数据处理&#xff1b; 2&#xff09;对多个异构的数据源有效集…...

二分搜索简介

概念&#xff1a; 二分搜索算法&#xff08;Binary Search&#xff09;是一种高效的搜索算法&#xff0c;用于在有序数组中查找特定元素的位置。它的基本思想是将数组分为两部分&#xff0c;通过比较目标值与数组中间元素的大小关系&#xff0c;确定目标值可能存在的区间&…...

虚拟车衣VR云展厅平台扩大了展览的触达范围

传统展厅主要是以静态陈列的形式来传达内容&#xff0c;主要的展示形式有图片、视频等&#xff0c;具有一定的局限性&#xff0c;体验感较差&#xff0c;客户往往不能深入地了解信息和细节内容。 VR全景看车是通过虚拟现实技术实现逼真的汽车观赏和试乘体验。消费者可以通过智能…...

云部署家里的服务器

1.固定静态ip 查看ip地址&#xff0c;en开头的 ifconfig查看路由器ip&#xff0c;via开头的 ip route修改配置文件 cd /etc/netplan/ #来到这个文件夹 sudo cp 01-network-manager-all.yaml 01-network-manager-all.yaml.bak #先备…...

【利用冒泡排序的思想模拟实现qsort函数】

1.qsort函数 1.1qsort函数的介绍 资源来源于cplusplus网站 1.2qsort函数的主要功能 对数组的元素进行排序 对数组中由 指向的元素进行排序&#xff0c;每个元素字节长&#xff0c;使用该函数确定顺序。 此函数使用的排序算法通过调用指定的函数来比较元素对&#xff0c;并将指…...

[plugin:vite:css] [sass] Undefined mixin.

前言&#xff1a; vite vue3 TypeScript环境 scss报错&#xff1a; [plugin:vite:css] [sass] Undefined mixin. 解决方案&#xff1a; 在vite.config.ts文件添加配置 css: {preprocessorOptions: {// 导入scss预编译程序scss: {additionalData: use "/resources/_ha…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

Spring数据访问模块设计

前面我们已经完成了IoC和web模块的设计&#xff0c;聪明的码友立马就知道了&#xff0c;该到数据访问模块了&#xff0c;要不就这俩玩个6啊&#xff0c;查库势在必行&#xff0c;至此&#xff0c;它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据&#xff08;数据库、No…...

Xen Server服务器释放磁盘空间

disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

代码规范和架构【立芯理论一】(2025.06.08)

1、代码规范的目标 代码简洁精炼、美观&#xff0c;可持续性好高效率高复用&#xff0c;可移植性好高内聚&#xff0c;低耦合没有冗余规范性&#xff0c;代码有规可循&#xff0c;可以看出自己当时的思考过程特殊排版&#xff0c;特殊语法&#xff0c;特殊指令&#xff0c;必须…...

LOOI机器人的技术实现解析:从手势识别到边缘检测

LOOI机器人作为一款创新的AI硬件产品&#xff0c;通过将智能手机转变为具有情感交互能力的桌面机器人&#xff0c;展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家&#xff0c;我将全面解析LOOI的技术实现架构&#xff0c;特别是其手势识别、物体识别和环境…...

麒麟系统使用-进行.NET开发

文章目录 前言一、搭建dotnet环境1.获取相关资源2.配置dotnet 二、使用dotnet三、其他说明总结 前言 麒麟系统的内核是基于linux的&#xff0c;如果需要进行.NET开发&#xff0c;则需要安装特定的应用。由于NET Framework 是仅适用于 Windows 版本的 .NET&#xff0c;所以要进…...