opengl图像处理

复制代码
#ifndef ADVANCED_OPENGL_PROCESSOR_H
#define ADVANCED_OPENGL_PROCESSOR_H

#include <android/native_window.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
#include <vector>
#include <atomic>
#include <mutex>
#include <functional>
#include <memory>

// 图像格式定义
enum class PixelFormat {
    RGBA8,      // 32位RGBA
    RGB8,       // 24位RGB
    RGBA16F,    // 半精度浮点
    RGBA32F,    // 单精度浮点
    YUV_NV21,   // Android相机格式
    YUV_NV12
};

// 变换参数
struct TransformParams {
    float rotationAngle = 0.0f;      // 旋转角度(度数)
    float scaleX = 1.0f;             // X轴缩放
    float scaleY = 1.0f;             // Y轴缩放
    float pivotX = 0.5f;             // 旋转中心X(0-1)
    float pivotY = 0.5f;             // 旋转中心Y(0-1)
    float translateX = 0.0f;         // X轴平移
    float translateY = 0.0f;         // Y轴平移
    bool keepAspectRatio = true;     // 保持宽高比
    bool bilinearFilter = true;      // 双线性过滤
    bool cropToInputSize = false;    // 裁剪到输入尺寸
};

// 性能统计
struct PerformanceMetrics {
    double gpuTimeMs = 0.0;          // GPU处理时间
    double uploadTimeMs = 0.0;       // 数据上传时间
    double downloadTimeMs = 0.0;     // 数据下载时间
    double totalTimeMs = 0.0;        // 总处理时间
    int32_t frameCount = 0;          // 处理帧数
    double averageFps = 0.0;         // 平均帧率
    size_t memoryUsedMB = 0;         // 显存使用量
    int32_t lastOutputWidth = 0;     // 上次输出宽度
    int32_t lastOutputHeight = 0;    // 上次输出高度
};

// 计算包围盒结果
struct BoundingBox {
    int32_t width;
    int32_t height;
    float offsetX;
    float offsetY;
};

class AdvancedOpenGLProcessor {
public:
    using FrameCallback = std::function<void(const uint8_t* data, int width, int height, 
                                            PixelFormat format)>;
    
    AdvancedOpenGLProcessor();
    ~AdvancedOpenGLProcessor();
    
    // 初始化
    bool initialize(ANativeWindow* window, PixelFormat format = PixelFormat::RGBA8);
    
    // 单帧处理
    bool processFrame(const uint8_t* inputData, int inputWidth, int inputHeight,
                     uint8_t* outputData, int* outputWidth, int* outputHeight);
    
    // 连续处理
    void startContinuousProcessing(FrameCallback callback);
    void stopContinuousProcessing();
    
    // 批量处理
    bool processBatch(const std::vector<const uint8_t*>& inputFrames,
                     int width, int height,
                     std::vector<uint8_t*>& outputFrames);
    
    // 设置变换参数
    void setTransformParams(const TransformParams& params);
    
    // 设置输出尺寸(自动或手动)
    void setOutputSize(int width, int height, bool autoCrop = false);
    
    // 性能优化接口
    void enableAsyncProcessing(bool enable);
    void enableGPUTiming(bool enable);
    void setMaxTextureSize(int maxSize);
    void setUsePBO(bool use) { mUsePBO = use; }
    
    // 资源管理
    void trimMemory();
    void flushPipeline();
    
    // 查询信息
    PerformanceMetrics getPerformanceMetrics() const;
    bool isInitialized() const { return mInitialized; }
    
    // 获取变换后的包围盒
    BoundingBox calculateBoundingBox(int inputWidth, int inputHeight) const;
    
    // 清理
    void cleanup();

private:
    // EGL资源
    EGLDisplay mEglDisplay;
    EGLSurface mEglSurface;
    EGLContext mEglContext;
    ANativeWindow* mNativeWindow;
    bool mInitialized;
    bool mUsePBO;
    
    // OpenGL资源
    GLuint mProgram;
    GLuint mFramebuffer;
    GLuint mInputTexture;
    GLuint mOutputTexture;
    GLuint mVAO;
    GLuint mVBO;
    GLuint mEBO;
    GLuint mPBO[2];
    int mCurrentPBOIndex;
    
    // 着色器变量位置
    struct {
        GLint transformMatrix;
        GLint textureSize;
        GLint pivotPoint;
        GLint useBilinear;
        GLint cropEnabled;
        GLint cropRect;
    } mUniformLocations;
    
    // 变换参数
    TransformParams mTransformParams;
    mutable std::mutex mTransformMutex;
    
    // 输出尺寸
    int mOutputWidth;
    int mOutputHeight;
    bool mAutoCalculateSize;
    
    // 性能统计
    PerformanceMetrics mPerformanceMetrics;
    mutable std::mutex mStatsMutex;
    
    // 内部方法
    bool compileShaders();
    bool createFramebuffer(int width, int height);
    bool createPBOs(int width, int height);
    GLuint createTexture(int width, int height, PixelFormat format);
    void updateUniforms(int inputWidth, int inputHeight);
    void calculateTransformMatrix(float matrix[16], int inputWidth, int inputHeight) const;
    void readPixelsAsync(uint8_t* outputData, int width, int height);
    void readPixelsSync(uint8_t* outputData, int width, int height);
    void updatePerformanceMetrics(int64_t uploadTime, int64_t processTime, int64_t downloadTime);
    
    // 时间测量
    class Timer {
    public:
        void start() { 
            clock_gettime(CLOCK_MONOTONIC, &mStartTime); 
        }
        
        int64_t elapsedMicroseconds() const {
            timespec endTime;
            clock_gettime(CLOCK_MONOTONIC, &endTime);
            return (endTime.tv_sec - mStartTime.tv_sec) * 1000000LL +
                   (endTime.tv_nsec - mStartTime.tv_nsec) / 1000LL;
        }
        
    private:
        timespec mStartTime;
    };
};

#endif // ADVANCED_OPENGL_PROCESSOR_H

#include "advanced_opengl_processor.h"
#include <android/log.h>
#include <cmath>
#include <cstring>
#include <unistd.h>
#include <time.h>

#define LOG_TAG "GLProcessor"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)

// 着色器代码
const char* VERTEX_SHADER_SOURCE = R"(
    #version 300 es
    precision highp float;
    
    layout(location = 0) in vec2 aPosition;
    layout(location = 1) in vec2 aTexCoord;
    
    out vec2 vTexCoord;
    
    uniform mat4 uTransformMatrix;
    uniform vec2 uTextureSize;
    uniform vec2 uPivotPoint;
    uniform int uCropEnabled;
    uniform vec4 uCropRect; // x, y, width, height
    
    void main() {
        // 应用变换矩阵
        vec4 transformedPos = uTransformMatrix * vec4(aPosition, 0.0, 1.0);
        
        // 处理裁剪
        if (uCropEnabled == 1) {
            // 将裁剪区域映射到[-1, 1]
            vec2 normalizedPos = (transformedPos.xy + 1.0) * 0.5;
            normalizedPos = (normalizedPos - uCropRect.xy) / uCropRect.zw;
            normalizedPos = normalizedPos * 2.0 - 1.0;
            gl_Position = vec4(normalizedPos, 0.0, 1.0);
        } else {
            gl_Position = transformedPos;
        }
        
        vTexCoord = aTexCoord;
    }
)";

const char* FRAGMENT_SHADER_SOURCE = R"(
    #version 300 es
    precision highp float;
    
    in vec2 vTexCoord;
    out vec4 fragColor;
    
    uniform sampler2D uTexture;
    uniform vec2 uTextureSize;
    uniform int uUseBilinear;
    
    // 双线性插值
    vec4 texture2DBilinear(sampler2D tex, vec2 uv, vec2 texSize) {
        vec2 texelCoord = uv * texSize - 0.5;
        vec2 f = fract(texelCoord);
        vec2 baseCoord = floor(texelCoord);
        
        vec4 tex00 = texture(tex, (baseCoord + vec2(0.5, 0.5)) / texSize);
        vec4 tex10 = texture(tex, (baseCoord + vec2(1.5, 0.5)) / texSize);
        vec4 tex01 = texture(tex, (baseCoord + vec2(0.5, 1.5)) / texSize);
        vec4 tex11 = texture(tex, (baseCoord + vec2(1.5, 1.5)) / texSize);
        
        vec4 tex0 = mix(tex00, tex10, f.x);
        vec4 tex1 = mix(tex01, tex11, f.x);
        
        return mix(tex0, tex1, f.y);
    }
    
    // Lanczos滤波(高质量缩放)
    vec4 texture2DLanczos(sampler2D tex, vec2 uv, vec2 texSize) {
        const float PI = 3.14159265359;
        const int TAPS = 2; // Lanczos窗口大小
        
        vec2 texelCoord = uv * texSize;
        vec2 fractCoord = fract(texelCoord);
        vec2 baseCoord = floor(texelCoord) - float(TAPS - 1);
        
        vec4 sum = vec4(0.0);
        float totalWeight = 0.0;
        
        for (int i = 0; i < TAPS * 2; i++) {
            for (int j = 0; j < TAPS * 2; j++) {
                vec2 sampleCoord = baseCoord + vec2(float(i), float(j));
                vec2 sampleUV = sampleCoord / texSize;
                
                if (sampleUV.x >= 0.0 && sampleUV.x <= 1.0 && 
                    sampleUV.y >= 0.0 && sampleUV.y <= 1.0) {
                    
                    float dx = (sampleCoord.x + 0.5) - texelCoord.x;
                    float dy = (sampleCoord.y + 0.5) - texelCoord.y;
                    
                    // Lanczos函数
                    float lanczos(float x) {
                        if (x == 0.0) return 1.0;
                        if (abs(x) >= float(TAPS)) return 0.0;
                        float pix = PI * x;
                        return (TAPS * sin(pix) * sin(pix / float(TAPS))) / (pix * pix);
                    }
                    
                    float weight = lanczos(dx) * lanczos(dy);
                    sum += texture(tex, sampleUV) * weight;
                    totalWeight += weight;
                }
            }
        }
        
        return totalWeight > 0.0 ? sum / totalWeight : texture(tex, uv);
    }
    
    void main() {
        vec2 clampedCoord = clamp(vTexCoord, 0.0, 1.0);
        
        if (uUseBilinear == 1) {
            fragColor = texture2DBilinear(uTexture, clampedCoord, uTextureSize);
        } else if (uUseBilinear == 2) {
            // 高质量缩放模式
            fragColor = texture2DLanczos(uTexture, clampedCoord, uTextureSize);
        } else {
            fragColor = texture(uTexture, clampedCoord);
        }
        
        // Alpha预乘(如果使用RGBA)
        fragColor.rgb *= fragColor.a;
    }
)";

AdvancedOpenGLProcessor::AdvancedOpenGLProcessor()
    : mEglDisplay(EGL_NO_DISPLAY)
    , mEglSurface(EGL_NO_SURFACE)
    , mEglContext(EGL_NO_CONTEXT)
    , mNativeWindow(nullptr)
    , mInitialized(false)
    , mUsePBO(true)
    , mProgram(0)
    , mFramebuffer(0)
    , mInputTexture(0)
    , mOutputTexture(0)
    , mVAO(0)
    , mVBO(0)
    , mEBO(0)
    , mCurrentPBOIndex(0)
    , mOutputWidth(0)
    , mOutputHeight(0)
    , mAutoCalculateSize(true) {
    
    memset(mPBO, 0, sizeof(mPBO));
    memset(&mUniformLocations, 0, sizeof(mUniformLocations));
    
    // 默认变换参数
    mTransformParams = TransformParams();
}

AdvancedOpenGLProcessor::~AdvancedOpenGLProcessor() {
    cleanup();
}

bool AdvancedOpenGLProcessor::initialize(ANativeWindow* window, PixelFormat format) {
    if (!window) {
        LOGE("Invalid window");
        return false;
    }
    
    mNativeWindow = window;
    
    // 1. 获取EGL显示
    mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    if (mEglDisplay == EGL_NO_DISPLAY) {
        LOGE("Failed to get EGL display");
        return false;
    }
    
    // 2. 初始化EGL
    EGLint major, minor;
    if (!eglInitialize(mEglDisplay, &major, &minor)) {
        LOGE("Failed to initialize EGL");
        return false;
    }
    
    // 3. 选择配置
    EGLint configAttribs[] = {
        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
        EGL_RED_SIZE, 8,
        EGL_GREEN_SIZE, 8,
        EGL_BLUE_SIZE, 8,
        EGL_ALPHA_SIZE, 8,
        EGL_DEPTH_SIZE, 0,
        EGL_STENCIL_SIZE, 0,
        EGL_NONE
    };
    
    EGLConfig config;
    EGLint numConfigs;
    if (!eglChooseConfig(mEglDisplay, configAttribs, &config, 1, &numConfigs)) {
        LOGE("Failed to choose EGL config");
        return false;
    }
    
    // 4. 创建EGL表面
    mEglSurface = eglCreateWindowSurface(mEglDisplay, config, window, nullptr);
    if (mEglSurface == EGL_NO_SURFACE) {
        LOGE("Failed to create EGL surface");
        return false;
    }
    
    // 5. 创建OpenGL ES 3.0上下文
    EGLint contextAttribs[] = {
        EGL_CONTEXT_CLIENT_VERSION, 3,
        EGL_NONE
    };
    
    mEglContext = eglCreateContext(mEglDisplay, config, EGL_NO_CONTEXT, contextAttribs);
    if (mEglContext == EGL_NO_CONTEXT) {
        LOGE("Failed to create EGL context");
        return false;
    }
    
    // 6. 绑定上下文
    if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
        LOGE("Failed to make EGL context current");
        return false;
    }
    
    // 7. 设置交换间隔为0以获得最大性能
    eglSwapInterval(mEglDisplay, 0);
    
    // 8. 编译着色器
    if (!compileShaders()) {
        LOGE("Failed to compile shaders");
        return false;
    }
    
    mInitialized = true;
    LOGI("OpenGL ES 3.0 initialized successfully");
    return true;
}

bool AdvancedOpenGLProcessor::compileShaders() {
    // 创建顶点着色器
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &VERTEX_SHADER_SOURCE, nullptr);
    glCompileShader(vertexShader);
    
    GLint success;
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        GLchar infoLog[512];
        glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog);
        LOGE("Vertex shader compilation failed: %s", infoLog);
        return false;
    }
    
    // 创建片段着色器
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &FRAGMENT_SHADER_SOURCE, nullptr);
    glCompileShader(fragmentShader);
    
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success) {
        GLchar infoLog[512];
        glGetShaderInfoLog(fragmentShader, 512, nullptr, infoLog);
        LOGE("Fragment shader compilation failed: %s", infoLog);
        return false;
    }
    
    // 创建着色器程序
    mProgram = glCreateProgram();
    glAttachShader(mProgram, vertexShader);
    glAttachShader(mProgram, fragmentShader);
    glLinkProgram(mProgram);
    
    glGetProgramiv(mProgram, GL_LINK_STATUS, &success);
    if (!success) {
        GLchar infoLog[512];
        glGetProgramInfoLog(mProgram, 512, nullptr, infoLog);
        LOGE("Shader program linking failed: %s", infoLog);
        return false;
    }
    
    // 删除着色器对象
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
    
    // 获取uniform位置
    glUseProgram(mProgram);
    mUniformLocations.transformMatrix = glGetUniformLocation(mProgram, "uTransformMatrix");
    mUniformLocations.textureSize = glGetUniformLocation(mProgram, "uTextureSize");
    mUniformLocations.pivotPoint = glGetUniformLocation(mProgram, "uPivotPoint");
    mUniformLocations.useBilinear = glGetUniformLocation(mProgram, "uUseBilinear");
    mUniformLocations.cropEnabled = glGetUniformLocation(mProgram, "uCropEnabled");
    mUniformLocations.cropRect = glGetUniformLocation(mProgram, "uCropRect");
    
    // 创建顶点数据
    float vertices[] = {
        // 位置           // 纹理坐标
        -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, 1.0f   // 右上
    };
    
    unsigned int indices[] = {
        0, 1, 2,  // 第一个三角形
        1, 3, 2   // 第二个三角形
    };
    
    // 创建VAO、VBO和EBO
    glGenVertexArrays(1, &mVAO);
    glGenBuffers(1, &mVBO);
    glGenBuffers(1, &mEBO);
    
    glBindVertexArray(mVAO);
    
    glBindBuffer(GL_ARRAY_BUFFER, mVBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mEBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, 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);
    
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
    
    LOGI("Shaders compiled successfully");
    return true;
}

BoundingBox AdvancedOpenGLProcessor::calculateBoundingBox(int inputWidth, int inputHeight) const {
    // 计算旋转后的包围盒
    float angleRad = mTransformParams.rotationAngle * M_PI / 180.0f;
    float cosA = cos(angleRad);
    float sinA = sin(angleRad);
    
    // 原始矩形四个角点(以旋转中心为原点)
    float hw = inputWidth * 0.5f;
    float hh = inputHeight * 0.5f;
    float pivotX = mTransformParams.pivotX * inputWidth - hw;
    float pivotY = mTransformParams.pivotY * inputHeight - hh;
    
    // 四个角点(相对于旋转中心)
    float corners[4][2] = {
        {-hw - pivotX, -hh - pivotY},  // 左下
        { hw - pivotX, -hh - pivotY},  // 右下
        {-hw - pivotX,  hh - pivotY},  // 左上
        { hw - pivotX,  hh - pivotY}   // 右上
    };
    
    // 应用旋转
    float minX = INFINITY, maxX = -INFINITY;
    float minY = INFINITY, maxY = -INFINITY;
    
    for (int i = 0; i < 4; i++) {
        float x = corners[i][0] * cosA - corners[i][1] * sinA;
        float y = corners[i][0] * sinA + corners[i][1] * cosA;
        
        // 应用缩放
        x *= mTransformParams.scaleX;
        y *= mTransformParams.scaleY;
        
        // 应用平移
        x += mTransformParams.translateX * inputWidth;
        y += mTransformParams.translateY * inputHeight;
        
        // 更新边界
        minX = fmin(minX, x);
        maxX = fmax(maxX, x);
        minY = fmin(minY, y);
        maxY = fmax(maxY, y);
    }
    
    // 计算尺寸和偏移
    BoundingBox bbox;
    bbox.width = static_cast<int>(ceilf(maxX - minX));
    bbox.height = static_cast<int>(ceilf(maxY - minY));
    bbox.offsetX = -minX - bbox.width * 0.5f;
    bbox.offsetY = -minY - bbox.height * 0.5f;
    
    return bbox;
}

void AdvancedOpenGLProcessor::calculateTransformMatrix(float matrix[16], int inputWidth, int inputHeight) const {
    // 单位矩阵
    memset(matrix, 0, sizeof(float) * 16);
    matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1.0f;
    
    // 将角度转换为弧度
    float angleRad = mTransformParams.rotationAngle * M_PI / 180.0f;
    float cosA = cos(angleRad);
    float sinA = sin(angleRad);
    
    // 计算旋转中心(归一化坐标转换为NDC坐标)
    float pivotX = mTransformParams.pivotX * 2.0f - 1.0f;
    float pivotY = mTransformParams.pivotY * 2.0f - 1.0f;
    
    // 构建变换矩阵(列主序):
    // 1. 平移到旋转中心
    // 2. 应用旋转
    // 3. 应用缩放
    // 4. 平移回原位置并应用用户平移
    
    // 缩放矩阵
    float scaleMatrix[16] = {
        mTransformParams.scaleX, 0, 0, 0,
        0, mTransformParams.scaleY, 0, 0,
        0, 0, 1, 0,
        0, 0, 0, 1
    };
    
    // 旋转矩阵
    float rotationMatrix[16] = {
        cosA, -sinA, 0, 0,
        sinA,  cosA, 0, 0,
        0, 0, 1, 0,
        0, 0, 0, 1
    };
    
    // 平移矩阵(到旋转中心)
    float translateToPivot[16] = {
        1, 0, 0, -pivotX,
        0, 1, 0, -pivotY,
        0, 0, 1, 0,
        0, 0, 0, 1
    };
    
    // 平移矩阵(从旋转中心)
    float translateFromPivot[16] = {
        1, 0, 0, pivotX,
        0, 1, 0, pivotY,
        0, 0, 1, 0,
        0, 0, 0, 1
    };
    
    // 用户平移矩阵
    float userTranslate[16] = {
        1, 0, 0, mTransformParams.translateX * 2.0f,
        0, 1, 0, mTransformParams.translateY * 2.0f,
        0, 0, 1, 0,
        0, 0, 0, 1
    };
    
    // 矩阵乘法:M = T_user * T_from * R * S * T_to
    // 为了简化,我们直接计算最终矩阵
    
    // 组合变换:先缩放,再旋转
    matrix[0] = cosA * mTransformParams.scaleX;
    matrix[1] = sinA * mTransformParams.scaleX;
    matrix[4] = -sinA * mTransformParams.scaleY;
    matrix[5] = cosA * mTransformParams.scaleY;
    
    // 应用平移(包括旋转中心调整和用户平移)
    float tx = pivotX - (matrix[0] * pivotX + matrix[4] * pivotY) + mTransformParams.translateX * 2.0f;
    float ty = pivotY - (matrix[1] * pivotX + matrix[5] * pivotY) + mTransformParams.translateY * 2.0f;
    
    matrix[12] = tx;
    matrix[13] = ty;
}

bool AdvancedOpenGLProcessor::createFramebuffer(int width, int height) {
    // 如果尺寸没变且已存在,则复用
    if (mFramebuffer != 0 && mOutputTexture != 0 && 
        width == mOutputWidth && height == mOutputHeight) {
        return true;
    }
    
    // 清理旧的资源
    if (mFramebuffer != 0) {
        glDeleteFramebuffers(1, &mFramebuffer);
        mFramebuffer = 0;
    }
    
    if (mOutputTexture != 0) {
        glDeleteTextures(1, &mOutputTexture);
        mOutputTexture = 0;
    }
    
    // 创建帧缓冲
    glGenFramebuffers(1, &mFramebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
    
    // 创建输出纹理
    mOutputTexture = createTexture(width, height, PixelFormat::RGBA8);
    
    // 将纹理附加到帧缓冲
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 
                          GL_TEXTURE_2D, mOutputTexture, 0);
    
    // 检查帧缓冲完整性
    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
        LOGE("Framebuffer is not complete");
        glDeleteFramebuffers(1, &mFramebuffer);
        glDeleteTextures(1, &mOutputTexture);
        mFramebuffer = 0;
        mOutputTexture = 0;
        return false;
    }
    
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    
    mOutputWidth = width;
    mOutputHeight = height;
    
    LOGI("Created framebuffer %dx%d", width, height);
    return true;
}

bool AdvancedOpenGLProcessor::createPBOs(int width, int height) {
    if (!mUsePBO) return true;
    
    size_t bufferSize = width * height * 4; // RGBA
    
    if (mPBO[0] == 0) {
        glGenBuffers(2, mPBO);
    }
    
    for (int i = 0; i < 2; i++) {
        glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO[i]);
        glBufferData(GL_PIXEL_PACK_BUFFER, bufferSize, nullptr, GL_STREAM_READ);
    }
    
    glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
    mCurrentPBOIndex = 0;
    
    return true;
}

GLuint AdvancedOpenGLProcessor::createTexture(int width, int height, PixelFormat format) {
    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    
    // 设置纹理参数
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    
    // 根据过滤模式设置
    if (mTransformParams.bilinearFilter) {
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    } else {
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    }
    
    // 分配纹理内存
    GLenum internalFormat, dataFormat, dataType;
    
    switch (format) {
        case PixelFormat::RGBA8:
            internalFormat = GL_RGBA8;
            dataFormat = GL_RGBA;
            dataType = GL_UNSIGNED_BYTE;
            break;
        case PixelFormat::RGB8:
            internalFormat = GL_RGB8;
            dataFormat = GL_RGB;
            dataType = GL_UNSIGNED_BYTE;
            break;
        case PixelFormat::RGBA16F:
            internalFormat = GL_RGBA16F;
            dataFormat = GL_RGBA;
            dataType = GL_HALF_FLOAT;
            break;
        case PixelFormat::RGBA32F:
            internalFormat = GL_RGBA32F;
            dataFormat = GL_RGBA;
            dataType = GL_FLOAT;
            break;
        default:
            internalFormat = GL_RGBA8;
            dataFormat = GL_RGBA;
            dataType = GL_UNSIGNED_BYTE;
    }
    
    glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 
                 0, dataFormat, dataType, nullptr);
    
    glBindTexture(GL_TEXTURE_2D, 0);
    return texture;
}

void AdvancedOpenGLProcessor::updateUniforms(int inputWidth, int inputHeight) {
    glUseProgram(mProgram);
    
    // 计算并设置变换矩阵
    float transformMatrix[16];
    calculateTransformMatrix(transformMatrix, inputWidth, inputHeight);
    glUniformMatrix4fv(mUniformLocations.transformMatrix, 1, GL_FALSE, transformMatrix);
    
    // 设置纹理尺寸
    glUniform2f(mUniformLocations.textureSize, static_cast<float>(inputWidth), 
                static_cast<float>(inputHeight));
    
    // 设置旋转中心
    glUniform2f(mUniformLocations.pivotPoint, mTransformParams.pivotX, mTransformParams.pivotY);
    
    // 设置过滤模式
    glUniform1i(mUniformLocations.useBilinear, mTransformParams.bilinearFilter ? 1 : 0);
    
    // 设置裁剪
    glUniform1i(mUniformLocations.cropEnabled, mTransformParams.cropToInputSize ? 1 : 0);
    
    if (mTransformParams.cropToInputSize) {
        // 计算裁剪矩形(归一化坐标)
        BoundingBox bbox = calculateBoundingBox(inputWidth, inputHeight);
        float cropRect[4] = {
            0.5f - static_cast<float>(inputWidth) / (2.0f * bbox.width),
            0.5f - static_cast<float>(inputHeight) / (2.0f * bbox.height),
            static_cast<float>(inputWidth) / bbox.width,
            static_cast<float>(inputHeight) / bbox.height
        };
        glUniform4f(mUniformLocations.cropRect, cropRect[0], cropRect[1], cropRect[2], cropRect[3]);
    }
}

bool AdvancedOpenGLProcessor::processFrame(const uint8_t* inputData, int inputWidth, int inputHeight,
                                         uint8_t* outputData, int* outputWidth, int* outputHeight) {
    if (!mInitialized || !inputData) {
        LOGE("Processor not initialized or invalid input");
        return false;
    }
    
    Timer totalTimer;
    totalTimer.start();
    
    Timer uploadTimer;
    uploadTimer.start();
    
    // 1. 计算输出尺寸
    BoundingBox bbox = calculateBoundingBox(inputWidth, inputHeight);
    int targetWidth = mAutoCalculateSize ? bbox.width : mOutputWidth;
    int targetHeight = mAutoCalculateSize ? bbox.height : mOutputHeight;
    
    if (targetWidth <= 0 || targetHeight <= 0) {
        LOGE("Invalid output dimensions: %dx%d", targetWidth, targetHeight);
        return false;
    }
    
    // 2. 创建或更新帧缓冲
    if (!createFramebuffer(targetWidth, targetHeight)) {
        LOGE("Failed to create framebuffer");
        return false;
    }
    
    // 3. 创建或更新输入纹理
    if (mInputTexture == 0) {
        mInputTexture = createTexture(inputWidth, inputHeight, PixelFormat::RGBA8);
    }
    
    // 4. 上传输入数据到纹理
    glBindTexture(GL_TEXTURE_2D, mInputTexture);
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, inputWidth, inputHeight,
                   GL_RGBA, GL_UNSIGNED_BYTE, inputData);
    
    int64_t uploadTime = uploadTimer.elapsedMicroseconds();
    
    Timer processTimer;
    processTimer.start();
    
    // 5. 绑定帧缓冲
    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
    glViewport(0, 0, targetWidth, targetHeight);
    
    // 6. 清除颜色缓冲
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    
    // 7. 更新uniform变量
    updateUniforms(inputWidth, inputHeight);
    
    // 8. 绑定纹理和VAO
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, mInputTexture);
    glUniform1i(glGetUniformLocation(mProgram, "uTexture"), 0);
    
    glBindVertexArray(mVAO);
    
    // 9. 绘制
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    
    int64_t processTime = processTimer.elapsedMicroseconds();
    
    Timer downloadTimer;
    downloadTimer.start();
    
    // 10. 读取结果
    if (outputData) {
        if (mUsePBO) {
            readPixelsAsync(outputData, targetWidth, targetHeight);
        } else {
            readPixelsSync(outputData, targetWidth, targetHeight);
        }
    }
    
    int64_t downloadTime = downloadTimer.elapsedMicroseconds();
    
    // 11. 清理状态
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glBindVertexArray(0);
    glBindTexture(GL_TEXTURE_2D, 0);
    
    // 12. 如果绑定到窗口,显示结果
    if (mNativeWindow) {
        int windowWidth = ANativeWindow_getWidth(mNativeWindow);
        int windowHeight = ANativeWindow_getHeight(mNativeWindow);
        
        if (windowWidth > 0 && windowHeight > 0) {
            glViewport(0, 0, windowWidth, windowHeight);
            glClear(GL_COLOR_BUFFER_BIT);
            
            // 使用简单着色器显示结果
            glBindTexture(GL_TEXTURE_2D, mOutputTexture);
            glBindVertexArray(mVAO);
            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
            
            eglSwapBuffers(mEglDisplay, mEglSurface);
        }
    }
    
    // 13. 更新输出尺寸
    if (outputWidth) *outputWidth = targetWidth;
    if (outputHeight) *outputHeight = targetHeight;
    
    // 14. 更新性能统计
    updatePerformanceMetrics(uploadTime, processTime, downloadTime);
    
    LOGI("Processed frame %dx%d -> %dx%d in %.2f ms", 
         inputWidth, inputHeight, targetWidth, targetHeight,
         totalTimer.elapsedMicroseconds() / 1000.0);
    
    return true;
}

void AdvancedOpenGLProcessor::readPixelsAsync(uint8_t* outputData, int width, int height) {
    size_t bufferSize = width * height * 4;
    
    // 绑定PBO用于读取
    glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO[mCurrentPBOIndex]);
    
    // 异步读取到当前PBO
    glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, 0);
    
    // 绑定另一个PBO并映射之前的数据
    int nextPBO = (mCurrentPBOIndex + 1) % 2;
    glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO[nextPBO]);
    
    void* mappedData = glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, bufferSize, GL_MAP_READ_BIT);
    if (mappedData) {
        memcpy(outputData, mappedData, bufferSize);
        glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
    }
    
    // 交换PBO
    mCurrentPBOIndex = nextPBO;
    glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
}

void AdvancedOpenGLProcessor::readPixelsSync(uint8_t* outputData, int width, int height) {
    // 同步读取
    glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, outputData);
}

void AdvancedOpenGLProcessor::setTransformParams(const TransformParams& params) {
    std::lock_guard<std::mutex> lock(mTransformMutex);
    mTransformParams = params;
}

void AdvancedOpenGLProcessor::setOutputSize(int width, int height, bool autoCrop) {
    mOutputWidth = width;
    mOutputHeight = height;
    mAutoCalculateSize = !autoCrop;
    
    if (autoCrop) {
        mTransformParams.cropToInputSize = true;
    }
}

void AdvancedOpenGLProcessor::updatePerformanceMetrics(int64_t uploadTime, int64_t processTime, int64_t downloadTime) {
    std::lock_guard<std::mutex> lock(mStatsMutex);
    
    mPerformanceMetrics.uploadTimeMs = uploadTime / 1000.0;
    mPerformanceMetrics.gpuTimeMs = processTime / 1000.0;
    mPerformanceMetrics.downloadTimeMs = downloadTime / 1000.0;
    mPerformanceMetrics.totalTimeMs = (uploadTime + processTime + downloadTime) / 1000.0;
    mPerformanceMetrics.frameCount++;
    
    // 计算平均FPS(基于最近10帧)
    static const int FRAME_HISTORY = 10;
    static double frameTimes[FRAME_HISTORY] = {0};
    static int frameIndex = 0;
    
    frameTimes[frameIndex] = mPerformanceMetrics.totalTimeMs;
    frameIndex = (frameIndex + 1) % FRAME_HISTORY;
    
    double sum = 0;
    int count = 0;
    for (int i = 0; i < FRAME_HISTORY; i++) {
        if (frameTimes[i] > 0) {
            sum += frameTimes[i];
            count++;
        }
    }
    
    if (count > 0 && sum > 0) {
        mPerformanceMetrics.averageFps = 1000.0 / (sum / count);
    }
    
    // 估计内存使用
    size_t textureMemory = (mOutputWidth * mOutputHeight * 4) / (1024 * 1024);
    size_t bufferMemory = (mUsePBO ? mOutputWidth * mOutputHeight * 4 * 2 : 0) / (1024 * 1024);
    mPerformanceMetrics.memoryUsedMB = textureMemory + bufferMemory;
    mPerformanceMetrics.lastOutputWidth = mOutputWidth;
    mPerformanceMetrics.lastOutputHeight = mOutputHeight;
}

PerformanceMetrics AdvancedOpenGLProcessor::getPerformanceMetrics() const {
    std::lock_guard<std::mutex> lock(mStatsMutex);
    return mPerformanceMetrics;
}

void AdvancedOpenGLProcessor::trimMemory() {
    if (!mInitialized) return;
    
    LOGI("Trimming memory");
    
    // 释放PBO
    if (mPBO[0] != 0) {
        glDeleteBuffers(2, mPBO);
        memset(mPBO, 0, sizeof(mPBO));
    }
    
    // 缩小输出纹理
    if (mOutputTexture != 0 && (mOutputWidth > 256 || mOutputHeight > 256)) {
        glBindTexture(GL_TEXTURE_2D, mOutputTexture);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, 
                    GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
        glBindTexture(GL_TEXTURE_2D, 0);
    }
    
    glFinish();
}

void AdvancedOpenGLProcessor::flushPipeline() {
    if (!mInitialized) return;
    glFlush();
}

void AdvancedOpenGLProcessor::cleanup() {
    if (!mInitialized) return;
    
    // 清理OpenGL资源
    if (mProgram) {
        glDeleteProgram(mProgram);
        mProgram = 0;
    }
    
    if (mFramebuffer) {
        glDeleteFramebuffers(1, &mFramebuffer);
        mFramebuffer = 0;
    }
    
    if (mInputTexture) {
        glDeleteTextures(1, &mInputTexture);
        mInputTexture = 0;
    }
    
    if (mOutputTexture) {
        glDeleteTextures(1, &mOutputTexture);
        mOutputTexture = 0;
    }
    
    if (mVAO) {
        glDeleteVertexArrays(1, &mVAO);
        mVAO = 0;
    }
    
    if (mVBO) {
        glDeleteBuffers(1, &mVBO);
        mVBO = 0;
    }
    
    if (mEBO) {
        glDeleteBuffers(1, &mEBO);
        mEBO = 0;
    }
    
    if (mPBO[0] != 0) {
        glDeleteBuffers(2, mPBO);
        memset(mPBO, 0, sizeof(mPBO));
    }
    
    // 清理EGL资源
    if (mEglDisplay != EGL_NO_DISPLAY) {
        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
        
        if (mEglContext != EGL_NO_CONTEXT) {
            eglDestroyContext(mEglDisplay, mEglContext);
            mEglContext = EGL_NO_CONTEXT;
        }
        
        if (mEglSurface != EGL_NO_SURFACE) {
            eglDestroySurface(mEglDisplay, mEglSurface);
            mEglSurface = EGL_NO_SURFACE;
        }
        
        eglTerminate(mEglDisplay);
        mEglDisplay = EGL_NO_DISPLAY;
    }
    
    mNativeWindow = nullptr;
    mInitialized = false;
    
    LOGI("OpenGL processor cleaned up");
}

// main.cpp - Native Activity入口
#include <android_native_app_glue.h>
#include "advanced_opengl_processor.h"
#include <chrono>
#include <thread>

struct Engine {
    struct android_app* app;
    AdvancedOpenGLProcessor* processor;
    bool initialized;
    bool animating;
    int32_t width;
    int32_t height;
    TransformParams transform;
    uint8_t* testImage;
    int testWidth;
    int testHeight;
};

static void engine_init_display(Engine* engine) {
    if (engine->initialized) return;
    
    // 获取窗口
    ANativeWindow* window = engine->app->window;
    if (!window) return;
    
    // 初始化处理器
    engine->processor = new AdvancedOpenGLProcessor();
    if (!engine->processor->initialize(window)) {
        LOGE("Failed to initialize OpenGL processor");
        delete engine->processor;
        engine->processor = nullptr;
        return;
    }
    
    // 设置初始变换参数
    engine->transform.rotationAngle = 30.0f; // 30度旋转
    engine->transform.scaleX = 1.2f;
    engine->transform.scaleY = 0.8f;
    engine->transform.pivotX = 0.3f;
    engine->transform.pivotY = 0.7f;
    engine->transform.bilinearFilter = true;
    engine->processor->setTransformParams(engine->transform);
    
    // 创建测试图像
    engine->testWidth = 1920;
    engine->testHeight = 1080;
    size_t imageSize = engine->testWidth * engine->testHeight * 4;
    engine->testImage = new uint8_t[imageSize];
    
    // 生成测试图像(渐变+棋盘格)
    for (int y = 0; y < engine->testHeight; y++) {
        for (int x = 0; x < engine->testWidth; x++) {
            int idx = (y * engine->testWidth + x) * 4;
            
            // RGBA格式
            engine->testImage[idx] = (x * 255) / engine->testWidth;     // R
            engine->testImage[idx + 1] = (y * 255) / engine->testHeight; // G
            
            // 棋盘格图案
            bool isWhite = ((x / 64) % 2) ^ ((y / 64) % 2);
            engine->testImage[idx + 2] = isWhite ? 255 : 128;           // B
            engine->testImage[idx + 3] = 255;                           // A
        }
    }
    
    engine->width = ANativeWindow_getWidth(window);
    engine->height = ANativeWindow_getHeight(window);
    engine->initialized = true;
    engine->animating = true;
    
    LOGI("Engine initialized with window size %dx%d", engine->width, engine->height);
}

static void engine_draw_frame(Engine* engine) {
    if (!engine->processor || !engine->initialized) return;
    
    // 处理测试图像
    uint8_t* outputData = nullptr;
    int outputWidth = 0, outputHeight = 0;
    
    // 为输出分配缓冲区(实际应用中应该复用缓冲区)
    size_t maxOutputSize = engine->testWidth * engine->testHeight * 4 * 4; // 最大可能尺寸
    outputData = new uint8_t[maxOutputSize];
    
    // 处理帧
    bool success = engine->processor->processFrame(
        engine->testImage, engine->testWidth, engine->testHeight,
        outputData, &outputWidth, &outputHeight
    );
    
    if (success) {
        // 获取性能统计
        PerformanceMetrics metrics = engine->processor->getPerformanceMetrics();
        LOGI("Processed: %dx%d -> %dx%d, Time: %.2f ms, FPS: %.1f",
             engine->testWidth, engine->testHeight, outputWidth, outputHeight,
             metrics.totalTimeMs, metrics.averageFps);
    }
    
    // 清理输出缓冲区
    delete[] outputData;
    
    // 更新变换参数(动画效果)
    static float angle = 0.0f;
    angle += 1.0f;
    if (angle >= 360.0f) angle -= 360.0f;
    
    engine->transform.rotationAngle = angle;
    engine->processor->setTransformParams(engine->transform);
}

static void engine_term_display(Engine* engine) {
    if (engine->processor) {
        engine->processor->cleanup();
        delete engine->processor;
        engine->processor = nullptr;
    }
    
    if (engine->testImage) {
        delete[] engine->testImage;
        engine->testImage = nullptr;
    }
    
    engine->initialized = false;
}

static void engine_handle_cmd(struct android_app* app, int32_t cmd) {
    Engine* engine = (Engine*)app->userData;
    
    switch (cmd) {
        case APP_CMD_SAVE_STATE:
            // 保存状态
            break;
        case APP_CMD_INIT_WINDOW:
            if (engine->app->window) {
                engine_init_display(engine);
                engine_draw_frame(engine);
            }
            break;
        case APP_CMD_TERM_WINDOW:
            engine_term_display(engine);
            break;
        case APP_CMD_GAINED_FOCUS:
            engine->animating = true;
            break;
        case APP_CMD_LOST_FOCUS:
            engine->animating = false;
            break;
        case APP_CMD_LOW_MEMORY:
            if (engine->processor) {
                engine->processor->trimMemory();
            }
            break;
        case APP_CMD_RESUME:
        case APP_CMD_PAUSE:
            // 处理暂停/恢复
            break;
        case APP_CMD_CONFIG_CHANGED:
            // 配置变化
            if (engine->processor && engine->app->window) {
                engine->width = ANativeWindow_getWidth(engine->app->window);
                engine->height = ANativeWindow_getHeight(engine->app->window);
            }
            break;
    }
}

static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) {
    Engine* engine = (Engine*)app->userData;
    
    if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
        int32_t action = AMotionEvent_getAction(event);
        
        if (action == AMOTION_EVENT_ACTION_DOWN) {
            // 点击屏幕更新旋转中心
            float x = AMotionEvent_getX(event, 0) / engine->width;
            float y = AMotionEvent_getY(event, 0) / engine->height;
            
            engine->transform.pivotX = x;
            engine->transform.pivotY = y;
            
            if (engine->processor) {
                engine->processor->setTransformParams(engine->transform);
            }
            
            return 1;
        }
    }
    
    return 0;
}

void android_main(struct android_app* state) {
    Engine engine;
    memset(&engine, 0, sizeof(engine));
    
    state->userData = &engine;
    state->onAppCmd = engine_handle_cmd;
    state->onInputEvent = engine_handle_input;
    engine.app = state;
    
    // 主循环
    while (true) {
        int ident;
        int events;
        struct android_poll_source* source;
        
        // 处理所有事件
        while ((ident = ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events, 
                                       (void**)&source)) >= 0) {
            if (source) {
                source->process(state, source);
            }
            
            // 检查是否要退出
            if (state->destroyRequested) {
                engine_term_display(&engine);
                return;
            }
        }
        
        // 渲染帧
        if (engine.initialized && engine.animating) {
            engine_draw_frame(&engine);
            
            // 限制帧率
            std::this_thread::sleep_for(std::chrono::milliseconds(16)); // ~60 FPS
        }
    }
}

cmake_minimum_required(VERSION 3.18.1)
project("AdvancedOpenGLProcessor")

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 设置编译标志
add_definitions(-DLOG_TAG=\"GLProcessor\")
add_definitions(-DGL_GLEXT_PROTOTYPES)

# 查找库
find_library(log-lib log)
find_library(android-lib android)
find_library(egl-lib EGL)
find_library(glesv3-lib GLESv3)

# 添加原生应用胶水库
add_library(app-glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c)
target_include_directories(app-glue PRIVATE ${ANDROID_NDK}/sources/android/native_app_glue)

# 源文件
set(SOURCE_FILES
    src/main/cpp/main.cpp
    src/main/cpp/advanced_opengl_processor.cpp
)

# 创建共享库
add_library(opengl_processor SHARED ${SOURCE_FILES})

# 包含目录
target_include_directories(opengl_processor PRIVATE
    ${CMAKE_SOURCE_DIR}/src/main/cpp
    ${ANDROID_NDK}/sources/android/native_app_glue
)

# 链接库
target_link_libraries(opengl_processor
    app-glue
    ${log-lib}
    ${android-lib}
    ${egl-lib}
    ${glesv3-lib}
)

# 设置输出属性
set_target_properties(opengl_processor PROPERTIES
    LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib
    ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/lib
)

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.advancedopengl">
    
    <uses-feature android:glEsVersion="0x00030000" android:required="true" />
    <uses-feature android:name="android.hardware.touchscreen" android:required="false" />
    
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="Advanced OpenGL Processor"
        android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
        
        <activity android:name="android.app.NativeActivity"
            android:label="OpenGL Processor"
            android:configChanges="orientation|keyboardHidden|screenSize">
            
            <meta-data android:name="android.app.lib_name"
                android:value="opengl_processor" />
            
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

主要特性

1. 任意角度旋转

  • 支持0-360度任意角度旋转

  • 可自定义旋转中心(归一化坐标)

  • 精确的旋转矩阵计算

2. 任意分辨率支持

  • 输入输出分辨率完全动态

  • 自动计算变换后的包围盒

  • 智能内存分配和重用

3. RGBA格式支持

  • 完整的32位RGBA处理

  • Alpha通道正确处理

  • 支持预乘Alpha

4. 高性能优化

  • PBO异步传输

  • 帧缓冲复用

  • 智能资源管理

  • 详细的性能统计

5. 高质量滤波

  • 双线性滤波

  • Lanczos高质量缩放(可选)

  • 边缘处理

6. 完整生命周期管理

  • Native Activity集成

  • 内存管理回调

  • 配置变化处理

这个实现提供了完整的、高性能的2D图像任意角度旋转处理,适用于Android平台的实时图像处理应用。

相关推荐
Java后端的Ai之路2 小时前
【AI应用开发工程师】-Gemini写前端的一个坑
前端·人工智能·gemini·ai应用开发工程师
国服第二切图仔2 小时前
实战:在华为云上快速搭建 openJiuwen Agent 平台,并开发一个“诗词雅集”知识库智能体
人工智能·华为云·智能体·openjiuwen
姓刘的哦2 小时前
推理PyTorch模型的方法
人工智能·pytorch·python
pangtout2 小时前
在AI时代,重写网络的角色
人工智能
PeterClerk2 小时前
计算机视觉(Computer Vision)领域重要会议及 CCF 等级
人工智能·深度学习·计算机视觉·ccf·计算机会议
初学大模型2 小时前
现代大模型数据跟神经网络的若干问题讨论
人工智能·机器人
咚咚王者2 小时前
人工智能之核心基础 机器学习 第十三章 自监督学习
人工智能·学习·机器学习
学海无涯,行者无疆2 小时前
Tauri框架实战——鼠标左键单击托盘图标不显示菜单
人工智能·ai编程·tauri·trae·氛围编程·托盘功能·托盘点击