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

【论文阅读】大语言模型中的文化道德规范知识

摘要&#xff1a; 在已有的研究中&#xff0c;我们知道英语语言模型中包含了类人的道德偏见&#xff0c;但从未有研究去检测语言模型对不同国家文化的道德差异。 我们分析了语言模型包含不同国家文化道德规范的程度&#xff0c;主要针对两个方面&#xff0c;其一是看语言模型…...

51单片机实训项目之产品数量计数器

/********************************************************************************* * 【实验平台】&#xff1a; QX-MCS51 单片机开发板 * 【外部晶振】&#xff1a; 11.0592mhz * 【主控芯片】&#xff1a; STC89C52 * 【编译环境】&#xff1a; Keil μVisio3 * 【程序…...

Scala第七章节

Scala第七章节 scala总目录 章节目标 掌握继承和抽象类相关知识点掌握匿名内部类的用法了解类型转换的内容掌握动物类案例 1. 继承 1.1 概述 实际开发中, 我们发现好多类中的内容是相似的(例如: 相似的属性和行为), 每次写很麻烦. 于是我们可以把这些相似的内容提取出来单…...

C语言进程的相关操作

C语言进程的相关操作 进程简介 每个进程都有一个非负整数形式到的唯一编号&#xff0c;即PID&#xff08;Process Identification&#xff0c;进程标识&#xff09;PID在任何时刻都是唯一的&#xff0c;但是可以重用&#xff0c;当进程终止并被回收以后&#xff0c;其PID就可…...

数据结构学习系列之链式栈

链式栈&#xff1a;即&#xff1a;栈的链式存储结构&#xff1b;分析&#xff1a;为了提高程序的运算效率&#xff0c;应采用头插法和头删法&#xff1b;进栈&#xff1a; int push_link_stack(stack_t *link_stack,int data) {if(NULL link_stack){printf("入参合理性检…...

too many session files in /var/tmp

Linux中Too many open files 问题分析和解决_e929: too many viminfo temp files-CSDN博客...

【7.0】打开未知来源安装应用

默认打开未知来源安装应用 frameworks\base\packages\SettingsProvider\res\values\defaults.xml <bool name"def_install_non_market_apps">false</bool>...

安装ipfs-swarm-key-gen

安装ipfs-swarm-key-gen Linux安装go解释器安装ipfs-swarm-key-gen Linux安装go解释器 https://blog.csdn.net/omaidb/article/details/133180749 安装ipfs-swarm-key-gen # 编译ipfs-swarm-key-gen二进制文件 go get -u github.com/Kubuxu/go-ipfs-swarm-key-gen/ipfs-swarm…...

BASH shell脚本篇5——文件处理

这篇文章介绍下BASH shell中的文件处理。之前有介绍过shell的其它命令&#xff0c;请参考&#xff1a; BASH shell脚本篇1——基本命令 BASH shell脚本篇2——条件命令 BASH shell脚本篇3——字符串处理 BASH shell脚本篇4——函数 在Bash Shell脚本中&#xff0c;可以使用…...

ElementUI之首页导航及左侧菜单(模拟实现)

目录 ​编辑 前言 一、mockjs简介 1. 什么是mockjs 2. mockjs的用途 3. 运用mockjs的优势 二、安装与配置mockjs 1. 安装mockjs 2. 引入mockjs 2.1 dev.env.js 2.2 prod.env.js 2.3 main.js 三、mockjs的使用 1. 将资源中的mock文件夹复制到src目录下 2. 点击登…...

有哪些做批发的网站/域名查询 站长查询

以织梦官方站为例&#xff0c;我们采集站长学院下的PHP教程栏目&#xff0c;打开列表地址http://www.dedecms.com/web-art/PHP_jiaocheng。 登录后台&#xff0c;进入“采集节点管理”&#xff0c;新建一个节点&#xff0c;选择内容模型为“普通文章”。1.设置节点基本信息先填…...

南京哪家网站做的好/seo搜索引擎优化实训

1. jsonp 原理&#xff1a;jsonp之所以能够实现跨域资源的访问&#xff0c;是因为<script>标签不受浏览器同源策略的限制&#xff0c;使用时将src属性指定一个跨域URL&#xff0c;服务器在收到请求后&#xff0c;将数据放到指定的callback里传回来2.CORS 原理&#xff1a…...

建立网站不公开/免费个人网站源码

设计模式6大原则-单一职责原则 定义&#xff1a;一个类应该只有一个引起变化的原因。一个类只负责一项职责 如果一个类有多个职责&#xff0c;这些职责耦合在一起&#xff0c;当一个职责发生变化时&#xff0c;可能影响其他的职责。 如&#xff1a; 一个类有 A、B、C 等职责…...

网站被入侵后需做的检测(1)/附子seo

1.用户分类 超级用户&#xff08;root&#xff1a;#&#xff09;&#xff1a;可以在Linux下几乎做任何事情&#xff0c;不受限制普通用户&#xff08;local&#xff1a;$&#xff09;&#xff1a;在Linux下做有限的事情 2.用户切换 &#xff08;1&#xff09;普通用户切换到…...

乐清建站公司哪家好/推广关键词怎么设置

文章目录概述安装Java VS Scalaval 和 var基本数据类型lazy在Scala中的应用开发工具IDEAMaven概述 https://www.scala-lang.org/ Scala combines object-oriented and functional programming in one concise, high-level language. Scala’s static types help avoid bugs in…...

做康复医院网站/集团网站推广

大概的思路&#xff1a;1、读取xml文件2、当一个下拉框选中某选项时&#xff0c;根据该选项&#xff0c;当前节点指向下一层&#xff0c;进入下一层下拉框的设置3、取消当前下拉框的禁用&#xff0c;禁用下一层的下拉框4、清空当前下拉框的选项5、根据当前节点读取xml的数据&am…...