使用`glTexImage2D`将`CVImageBufferRef`转换为OpenGL ES纹理时如何摆脱人工制品?

时间:2016-11-05 13:41:39

标签: iphone swift opengl-es textures opengl-es-2.0

我尝试从CVImageBufferRef加载纹理:

func createTextureFromCVImageBufferRef(buffer: CVImageBufferRef) {
    let bufferHeight = CVPixelBufferGetHeight(buffer)
    let bufferWidth  = CVPixelBufferGetWidth(buffer)
    let bytesPerRow  = CVPixelBufferGetBytesPerRow(buffer)

    let w = bytesPerRow / 4 //  I option
    //let w = bufferWidth   //  II option
    let h = bufferHeight

    CVPixelBufferLockBaseAddress(buffer, CVPixelBufferLockFlags(rawValue: CVOptionFlags(0)))

    glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MIN_FILTER), GL_LINEAR)
    glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MAG_FILTER), GL_LINEAR)
    glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_S), GL_CLAMP_TO_EDGE)
    glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_T), GL_CLAMP_TO_EDGE)

    glTexImage2D(GLenum(GL_TEXTURE_2D), GLint(0), GLint(GL_RGBA), GLsizei(w), GLsizei(h), GLint(0), GLenum(GL_BGRA), GLenum(GL_UNSIGNED_BYTE), CVPixelBufferGetBaseAddress(buffer))
}

以两种不同的方式:

1)let w = bytesPerRow / 4

2)let w = bufferWidth

这两个选项在iPhone 5上完美运行,但据我所知,由于CVImageBufferRef数据对齐,我在iPhone 6上有工件。在iPhone 6上bytesPerRow / 4等于752,但bufferWidth等于750。在这两种情况下,我都有以下工件:

在第一种情况下: 图像右侧有一条2像素的线。 (它是纹理的一部分,而不仅仅是黑色背景视图)

enter image description here

在第二种情况下: 一些地狱正在进行着纹理。

enter image description here

1 个答案:

答案 0 :(得分:0)

正如您所发现的那样,您需要处理行填充,但处理它时GL会完全忽略它。您当前的方法都将其视为实际纹理数据,这就是它无法正常工作的原因。

您可以使用UNPACK_ROW_LENGTH跳过整个像素,使用UNPACK_ALIGNMENT来处理散乱字节填充(在纹理上传之前通过glPixelStorei设置)。

我认为在您的情况下,您希望将UNPACK_ROW_LENGTH设置为752,将glTexImage2D宽度参数设置为750.