1

我想使用openGL缩放图像,任何人都可以为我提供有关如何执行此操作的代码吗?
PS,我使用JGL作为 Java 的 openGL 库。

4

1 回答 1

1

我将对此进行简要介绍,因为您可以找到解决方案几乎每个部分的教程。

您需要从磁盘加载图像,并创建纹理。

您需要创建一个具有所需目标尺寸(在您的情况下为双倍宽度、双倍高度)的帧缓冲区对象(FBO)。使 FBO 激活以进行渲染。

应用纹理渲染全屏四边形。

使用 glReadPixels() 读取结果。

就是这样......纹理映射硬件将为您重新调整它。但它可能会比在 CPU 上完成要慢,尤其是对于“缩放 2 倍”。

编辑:根据 OP 的要求,有必要包含源代码。

所以......要在 Java 中加载图像,你会这样做:

BufferedImage img;
try {
    img = ImageIO.read(new File("myLargeImage.jpg"));
} catch (IOException e) { /* ... */ }
int w = img.getWidth(), h = img.getHeight();

对于 JGL,可能需要将图像转换为数组:

byte [][][] imageData = new byte[img.getWidth()][img.getHeight()][3]; // alloc buffer for RGB data
for(int y = 0; y < h; ++ y) {
    for(int x = 0; x < w; ++ x) {
        int RGBA = img.getRGB(x, y);
        imageData[x][y][0] = RGBA & 0xff;
        imageData[x][y][1] = (RGBA >> 8) & 0xff;
        imageData[x][y][2] = (RGBA >> 16) & 0xff;
    }
}

请注意,也可能有 alpha 通道(用于透明度),这可能会很慢。也可以使用:

int[] rgbaData = img.GetRGB(0, 0, w, h, new int[w * h], 0, w);

但这不会以 JGL 期望的正确格式返回数据。倒霉。然后你需要填充一个纹理:

int[] texId = {0};
gl.glGenTextures(1, texId); // generate texture id for your texture (can skip this line)
gl.glEnable(GL.GL_TEXTURE_2D);
gl.glBindTexture(GL.GL_TEXTURE_2D, texId[0]); // bind the texture
gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1); // set alignment of data in memory (a good thing to do before glTexImage)
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP); // set clamp (GL_CLAMP_TO_EDGE would be better)
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); // set linear filtering (so you can scale your image)
gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB, w, h, 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, imageData); // upload image data to the texture

一旦你有了纹理,你就可以画东西了。让我们重新采样您的图像:

int newW = ..., newH = ...; // fill-in your values
gl.glViewport(0, 0, newW, newH); // set viewport

gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
gl.glColor3f(1.0f, 1.0f, 1.0f); // set "white" color
gl.glDisable(GL.GL_CULL_FACE); // disable backface culling
gl.glDisable(GL.GL_LIGHTING); // disable lighting
gl.glDisable(GL.GL_DEPTH_TEST); // disable depth test
// setup OpenGL so that it renders texture colors without modification (some of that is not required by default)

gl.glBegin(GL_QUADS);
gl.glTexCoord2f(0.0f, 1.0f);
gl.glVertex2f(-1.0f, -1.0f);
gl.glTexCoord2f(1.0f, 1.0f);
gl.glVertex2f(+1.0f, -1.0f);
gl.glTexCoord2f(1.0f, 0.0f);
gl.glVertex2f(+1.0f, +1.0f);
gl.glTexCoord2f(0.0f, 0.0f);
gl.glVertex2f(-1.0f, +1.0f);
gl.glEnd();
// draw a fullscreen quad with your texture on it (scaling is performed here)

现在已经渲染了缩放的图像,需要做的就是下载它。

byte[][][] newImageData = new byte[newW][newH][3];
gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, 1); // set alignment of data in memory (this time pack alignment; a good thing to do before glReadPixels)
gl.glReadPixels(0, 0, newW, newH, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, newImageData);

然后可以将输入图像 img 转换为 imageData 的类似方式将数据转换为 BufferedImage。

请注意,我使用了变量 gl,它是 GL 类的一个实例。将代码放入一些 JGL 示例中,它应该可以工作。

需要注意的是,JGL 似乎不支持帧缓冲区对象,因此您会受到 OpenGL 窗口大小的输出图像大小的限制(尝试创建更大的图像会导致黑色边框)。它可以通过使用多通道渲染来解决(逐块渲染图像并在内存中组装完整图像)。

于 2012-02-08T10:37:14.550 回答