山东网站seo设计整合营销策划方案模板
整理一下最近跑的两个小程序,该程序的目的是利用OpenGL实现图像的缩放,同时比较双线性插值和双三次插值两种算法的最终效果,于是将这两种算法代码以及结果展出,使用的语言为C++,放大倍数为2倍。
先置条件
1.使用的IDE为:visual studio2022
2.软件平台:Windows11
3.OpenGL版本:3
4.确保 GLFW 已正确安装:下载预编译的 GLFW 库: GLFW 官方下载页面链接;解压后,将 include 文件夹中的头文件和 lib 文件夹中的库文件添加到你的项目中。
5.链接 GLFW 库:
6.因为项目要求,输入的是raw图片,需要输入png或jpg图片的自行修改代码
双线性插值
#include <glew.h>
#include <glfw3.h>
#include <iostream>
#include <fstream>
#include <cstdio>void checkGLError(const char* label) {GLenum err;while ((err = glGetError()) != GL_NO_ERROR) {std::cerr << "OpenGL Error (" << label << "): " << err << std::endl;}
}unsigned char* loadRawImage(const char* path, int& width, int& height, int channels) {FILE* file;errno_t err = fopen_s(&file, path, "rb");if (err != 0 || !file) {fprintf(stderr, "Failed to open raw image file: %s\n", path);return nullptr;}fseek(file, 0, SEEK_END);long fileSize = ftell(file);rewind(file);int expectedSize = width * height * channels;if (fileSize != expectedSize) {fprintf(stderr, "File size does not match expected size for the given dimensions and channels.\n");fclose(file);return nullptr;}unsigned char* imageData = new unsigned char[fileSize];fread(imageData, 1, fileSize, file);fclose(file);return imageData;
}GLuint createTexture(unsigned char* data, int width, int height, int channels) {GLuint textureID;glGenTextures(1, &textureID);glBindTexture(GL_TEXTURE_2D, textureID);GLenum internalFormat = (channels == 3) ? GL_RGB : GL_R8;GLenum format = (channels == 3) ? GL_RGB : GL_RED;glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, GL_UNSIGNED_BYTE, data);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);return textureID;
}void saveRawImage(unsigned char* data, int width, int height, int channels, const char* filename) {std::ofstream outFile(filename, std::ios::binary);if (!outFile) {fprintf(stderr, "Failed to open output file: %s\n", filename);return;}int dataSize = width * height * channels;outFile.write(reinterpret_cast<char*>(data), dataSize);outFile.close();
}int main(int argc, char* argv[]) {if (!glfwInit()) {fprintf(stderr, "Failed to initialize GLFW\n");return -1;}glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Image Scaling", NULL, NULL);if (!window) {fprintf(stderr, "Failed to create GLFW window\n");glfwTerminate();return -1;}glfwMakeContextCurrent(window);glewExperimental = GL_TRUE;GLenum status = glewInit();if (status != GLEW_OK) {fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(status));return -1;}// Load shader program and set up OpenGL state here...const char* vertexShaderSource = "#version 330 core\n""layout(location = 0) in vec3 aPos;\n""layout(location = 1) in vec2 aTexCoord;\n""out vec2 TexCoord;\n""void main()\n""{\n"" gl_Position = vec4(aPos, 1.0);\n"" TexCoord = aTexCoord;\n""}\0";const char* fragmentShaderSource = "#version 330 core\n""out vec4 FragColor;\n""in vec2 TexCoord;\n""uniform sampler2D ourTexture;\n""void main()\n""{\n"" FragColor = texture(ourTexture, TexCoord);\n""}\0";GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);glCompileShader(vertexShader);GLint success;GLchar infoLog[512];glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);if (!success) {glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);printf("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n%s\n", infoLog);};GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);glCompileShader(fragmentShader);glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);if (!success) {glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);printf("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n%s\n", infoLog);};GLuint shaderProgram = glCreateProgram();glAttachShader(shaderProgram, vertexShader);glAttachShader(shaderProgram, fragmentShader);glLinkProgram(shaderProgram);glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);if (!success) {glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);printf("ERROR::PROGRAM::LINKING_FAILED\n%s\n", infoLog);}glDeleteShader(vertexShader);glDeleteShader(fragmentShader);GLfloat vertices[] = {// positions // texture coords1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // top right1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // bottom right-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, // bottom left-1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left };GLuint indices[] = {0, 1, 3, // first triangle1, 2, 3 // second triangle};GLuint VBO, VAO, EBO;glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);glGenBuffers(1, &EBO);glBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);glEnableVertexAttribArray(0);glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));glEnableVertexAttribArray(1);glBindVertexArray(0); // Unbind VAOint originalWidth = 2480; // Set your image width hereint originalHeight = 3512; // Set your image height hereint channels = 3; // RGB imageunsigned char* imageData = loadRawImage("input.raw", originalWidth, originalHeight, channels);if (!imageData) {glfwDestroyWindow(window);glfwTerminate();return -1;}int newWidth = originalWidth * 2; // Scale up by three timesint newHeight = originalHeight * 2;GLuint framebuffer;glGenFramebuffers(1, &framebuffer);glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);GLuint textureColorbuffer;glGenTextures(1, &textureColorbuffer);glBindTexture(GL_TEXTURE_2D, textureColorbuffer);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, newWidth, newHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureColorbuffer, 0);if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << std::endl;glBindFramebuffer(GL_FRAMEBUFFER, 0);GLuint texture = createTexture(imageData, originalWidth, originalHeight, channels);delete[] imageData;while (!glfwWindowShouldClose(window)) {glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);glViewport(0, 0, newWidth, newHeight);glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, texture);glUniform1i(glGetUniformLocation(shaderProgram, "ourTexture"), 0);glUseProgram(shaderProgram);glBindVertexArray(VAO);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);glBindVertexArray(0);glBindFramebuffer(GL_FRAMEBUFFER, 0);unsigned char* frameBufferPixels = new unsigned char[newWidth * newHeight * channels];glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);glReadPixels(0, 0, newWidth, newHeight, GL_RGB, GL_UNSIGNED_BYTE, frameBufferPixels);saveRawImage(frameBufferPixels, newWidth, newHeight, channels, "output.raw");delete[] frameBufferPixels;break; // Only scale once and then exit}glDeleteVertexArrays(1, &VAO);glDeleteBuffers(1, &VBO);glDeleteBuffers(1, &EBO);glDeleteTextures(1, &texture);glDeleteTextures(1, &textureColorbuffer);glDeleteFramebuffers(1, &framebuffer);glDeleteProgram(shaderProgram);glfwDestroyWindow(window);glfwTerminate();return 0;
}
双三次插值
#include <glew.h>
#include <glfw3.h>
#include <iostream>
#include <fstream>
#include <vector>// 着色器源码
const char* vertexShaderSource = R"(
#version 330 core
layout(location = 0) in vec2 aPos;
layout(location = 1) in vec2 aTexCoords;out vec2 TexCoords;void main() {gl_Position = vec4(aPos, 0.0, 1.0);TexCoords = aTexCoords;
}
)";const char* fragmentShaderSource = R"(
#version 330 corein vec2 TexCoords;
out vec4 FragColor;uniform sampler2D image;
uniform float texelSize;float cubic(float x) {float a = -0.5;if (x < 0.0) x = -x;if (x < 1.0) return (a + 2.0) * x * x * x - (a + 3.0) * x * x + 1.0;if (x < 2.0) return a * x * x * x - 5.0 * a * x * x + 8.0 * a * x - 4.0 * a;return 0.0;
}vec4 bicubic(sampler2D tex, vec2 uv) {vec2 texel = vec2(texelSize, texelSize);vec2 pixel = uv / texel - vec2(0.5, 0.5);vec2 f = fract(pixel);pixel = floor(pixel) * texel;vec4 samples[4];for (int i = 0; i < 4; ++i) {float weightY = cubic(f.y - float(i));vec2 sampleUV = pixel + vec2(0.0, float(i)) * texel;vec4 rowSamples[4];for (int j = 0; j < 4; ++j) {float weightX = cubic(float(j) - f.x);vec2 offset = vec2(float(j), 0.0) * texel;rowSamples[j] = texture(tex, sampleUV + offset) * weightX;}samples[i] = rowSamples[0] + rowSamples[1] + rowSamples[2] + rowSamples[3];samples[i] *= weightY;}return samples[0] + samples[1] + samples[2] + samples[3];
}void main() {FragColor = bicubic(image, TexCoords);
}
)";// 编译着色器
GLuint compileShader(GLenum type, const char* source) {GLuint shader = glCreateShader(type);glShaderSource(shader, 1, &source, nullptr);glCompileShader(shader);// 检查编译错误GLint success;glGetShaderiv(shader, GL_COMPILE_STATUS, &success);if (!success) {char infoLog[512];glGetShaderInfoLog(shader, 512, nullptr, infoLog);std::cerr << "ERROR::SHADER::COMPILATION_FAILED\n" << infoLog << std::endl;}return shader;
}// 创建着色器程序
GLuint createShaderProgram() {GLuint vertexShader = compileShader(GL_VERTEX_SHADER, vertexShaderSource);GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragmentShaderSource);GLuint program = glCreateProgram();glAttachShader(program, vertexShader);glAttachShader(program, fragmentShader);glLinkProgram(program);// 检查链接错误GLint success;glGetProgramiv(program, GL_LINK_STATUS, &success);if (!success) {char infoLog[512];glGetProgramInfoLog(program, 512, nullptr, infoLog);std::cerr << "ERROR::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;}glDeleteShader(vertexShader);glDeleteShader(fragmentShader);return program;
}// 加载RAW图像数据
std::vector<unsigned char> loadRawImage(const char* filePath, int width, int height) {std::ifstream file(filePath, std::ios::binary);if (!file) {std::cerr << "Failed to open RAW file: " << filePath << std::endl;return {};}std::vector<unsigned char> data(width * height * 3); // 假设是RGB格式file.read(reinterpret_cast<char*>(data.data()), data.size());file.close();return data;
}// 保存结果图像为RAW格式
void saveRawImage(const char* filePath, const std::vector<unsigned char>& data, int width, int height) {std::ofstream file(filePath, std::ios::binary);if (!file) {std::cerr << "Failed to open output RAW file: " << filePath << std::endl;return;}file.write(reinterpret_cast<const char*>(data.data()), data.size());file.close();
}int main() {// 初始化OpenGL上下文(使用离屏渲染)glfwInit();glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // 不创建窗口GLFWwindow* window = glfwCreateWindow(1, 1, "", nullptr, nullptr);glfwMakeContextCurrent(window);glewInit();// 创建着色器程序GLuint shaderProgram = createShaderProgram();glUseProgram(shaderProgram);// 加载RAW图像数据int inputWidth = 2480, inputHeight = 3512; // 输入图像尺寸auto inputData = loadRawImage("input.raw", inputWidth, inputHeight);if (inputData.empty()) {std::cerr << "Failed to load input RAW image." << std::endl;return -1;}// 创建纹理GLuint texture;glGenTextures(1, &texture);glBindTexture(GL_TEXTURE_2D, texture);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, inputWidth, inputHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, inputData.data());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);glUniform1f(glGetUniformLocation(shaderProgram, "texelSize"), 1.0f / inputWidth);// 设置帧缓冲区和渲染目标int outputWidth = inputWidth*2, outputHeight = inputHeight*2; // 输出图像尺寸GLuint framebuffer;glGenFramebuffers(1, &framebuffer);glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);GLuint renderTexture;glGenTextures(1, &renderTexture);glBindTexture(GL_TEXTURE_2D, renderTexture);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, outputWidth, outputHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTexture, 0);if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {std::cerr << "Framebuffer is not complete!" << std::endl;return -1;}// 设置顶点数据float vertices[] = {// 位置 // 纹理坐标-1.0f, 1.0f, 0.0f, 1.0f,-1.0f, -1.0f, 0.0f, 0.0f,1.0f, -1.0f, 1.0f, 0.0f,-1.0f, 1.0f, 0.0f, 1.0f,1.0f, -1.0f, 1.0f, 0.0f,1.0f, 1.0f, 1.0f, 1.0f};GLuint VBO, VAO;glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);glBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));glEnableVertexAttribArray(1);// 渲染到帧缓冲区glViewport(0, 0, outputWidth, outputHeight);glClear(GL_COLOR_BUFFER_BIT);glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, texture);glUniform1i(glGetUniformLocation(shaderProgram, "image"), 0);glBindVertexArray(VAO);glDrawArrays(GL_TRIANGLES, 0, 6);// 读取渲染结果std::vector<unsigned char> outputData(outputWidth * outputHeight * 3);glReadPixels(0, 0, outputWidth, outputHeight, GL_RGB, GL_UNSIGNED_BYTE, outputData.data());// 保存结果图像saveRawImage("output.raw", outputData, outputWidth, outputHeight);// 清理资源glDeleteVertexArrays(1, &VAO);glDeleteBuffers(1, &VBO);glDeleteTextures(1, &texture);glDeleteTextures(1, &renderTexture);glDeleteFramebuffers(1, &framebuffer);glDeleteProgram(shaderProgram);glfwTerminate();return 0;
}
最终结果展示