当前位置: 首页 > 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…...

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站&#xff0c;会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后&#xff0c;网站没有变化的情况。 不熟悉siteground主机的新手&#xff0c;遇到这个问题&#xff0c;就很抓狂&#xff0c;明明是哪都没操作错误&#x…...

在软件开发中正确使用MySQL日期时间类型的深度解析

在日常软件开发场景中&#xff0c;时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志&#xff0c;到供应链系统的物流节点时间戳&#xff0c;时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库&#xff0c;其日期时间类型的…...

系统设计 --- MongoDB亿级数据查询优化策略

系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log&#xff0c;共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题&#xff0c;不能使用ELK只能使用…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕&#xff0c;#AI 监考一度冲上热搜。当AI深度融入高考&#xff0c;#时间同步 不再是辅助功能&#xff0c;而是决定AI监考系统成败的“生命线”。 AI亮相2025高考&#xff0c;40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕&#xff0c;江西、…...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral&#xff08;热门工具 Ruff 的开发者&#xff09;推出的下一代高性能 Python 包管理器和构建工具&#xff0c;用 Rust 编写。它旨在解决传统工具&#xff08;如 pip、virtualenv、pip-tools&#xff09;的性能瓶颈&#xff0c;同时…...

Java编程之桥接模式

定义 桥接模式&#xff08;Bridge Pattern&#xff09;属于结构型设计模式&#xff0c;它的核心意图是将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。这种模式通过组合关系来替代继承关系&#xff0c;从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...