openGL を使用して画像をスケーリングしたいのですが、これを行う方法についてのコードを教えてもらえますか?
PS、私はJava の openGL ライブラリとしてJGLを使用しています。
1 に答える
ソリューションのほぼすべての部分のチュートリアルを見つけることができるので、これについては簡単に説明します。
ディスクからイメージをロードし、テクスチャを作成する必要があります。
目的のターゲット ディメンション (この場合は、幅が 2 倍、高さが 2 倍) のフレーム バッファー オブジェクト (FBO) を作成する必要があります。レンダリングのために FBO をアクティブにします。
テクスチャを適用してフルスクリーン クワッドをレンダリングします。
glReadPixels() を使用して結果を読み取ります。
それだけです...テクスチャマッピングハードウェアが再スケーリングを処理します。ただし、特に「スケーリング 2x」の場合は、CPU で実行する場合よりも遅くなる可能性があります。
EDIT : 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;
}
}
(透明度のための) アルファ チャネルも存在する可能性があり、これはかなり遅くなる可能性があることに注意してください。次のものも使用できます。
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 ウィンドウ サイズによって出力画像サイズが制限されます (より大きな画像を作成しようとすると、黒い境界線が表示されます)。これは、マルチパス レンダリングを使用することで解決できます (イメージ タイルをタイルごとにレンダリングし、メモリ内でイメージ全体を組み立てます)。