-1

私はそれが何をしているのか理解していますが、以下に提供されているコードのステップの背後にあるロジックは何ですか?これは、LWJGLにテクスチャをロードする方法です。しかし、forループで何が起こっているのでしょうか?xとyを掛けて、ピクセルの位置を取得しませんか?forループに到達するとコメントが曖昧になるため、forループからコードの最後まで何が起こっているのかを説明すると役立ちます。ピクセル情報をバッファに入れるときの奇妙な記号がわかりません。

public class TextureLoader { 
private static final int BYTES_PER_PIXEL = 4;//3 for RGB, 4 for RGBA 
   public static int loadTexture(BufferedImage image){ 

      int[] pixels = new int[image.getWidth() * image.getHeight()]; 
        image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth()); 

        ByteBuffer buffer = BufferUtils.createByteBuffer(image.getWidth() * image.getHeight() * BYTES_PER_PIXEL); //4 for RGBA, 3 for RGB 

        for(int y = 0; y < image.getHeight(); y++){ 
            for(int x = 0; x < image.getWidth(); x++){ 
                int pixel = pixels[y * image.getWidth() + x]; 
                buffer.put((byte) ((pixel >> 16) & 0xFF));     // Red component 
                buffer.put((byte) ((pixel >> 8) & 0xFF));      // Green component 
                buffer.put((byte) (pixel & 0xFF));               // Blue component 
                buffer.put((byte) ((pixel >> 24) & 0xFF));    // Alpha component. Only for RGBA 
            } 
        } 

        buffer.flip(); //FOR THE LOVE OF GOD DO NOT FORGET THIS 

        // You now have a ByteBuffer filled with the color data of each pixel. 
        // Now just create a texture ID and bind it. Then you can load it using  
        // whatever OpenGL method you want, for example: 

      int textureID = glGenTextures(); //Generate texture ID 
        glBindTexture(GL_TEXTURE_2D, textureID); //Bind texture ID 

        //Setup wrap mode 
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE); 
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE); 

        //Setup texture scaling filtering 
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 

        //Send texel data to OpenGL 
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, image.getWidth(), image.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 

        //Return the texture ID so we can bind it later again 
      return textureID; 
   } 

   public static BufferedImage loadImage(String loc) 
   { 
        try { 
           return ImageIO.read(DefenseStep.class.getResource(loc)); 
        } catch (IOException e) { 
            //Error Handling Here 
        } 
       return null; 
   } 

}

4

4 に答える 4

2

それがしているのは、画像からピクセルごとのバッファに色をロードすることだけです。

このコードは、Javaのビット演算子を使用してそれを実行しています。このJavaトレイルを参照してください。

が表示されている場合>>、これは「この数値の2進数を右にシフトする」ことを意味し、が表示されている場合num >> n、これは「numの値nビットの2進数を右にシフトする」ことを意味します。例:

System.out.println(4 >> 2); // Prints "1"

これは、 12進数の4が0100であり、右に2ビットシフトすると0001、10進数の1であるが得られるために出力されます。

そうは言っても、画像の色はARGBを使用して表されます。つまり、画像の32ビットごとにA、R、G、B(アルファ、赤、緑、青)のそれぞれに専用の8ビットがあるため、16進形式は次のようになります。

0xAARRGGBB

ここで、各文字は16進数です。

投稿したコードは、バイナリロジックを使用して、などの各グループを取得していますAARR各グループは正確に1バイト、つまり8ビットであるため、8、16、および24が由来します。&2つの数値に対してビット単位の論理ANDを実行します。両方の数値で1であるビット位置のみが1のままであり、他のすべての位置は0になります。

RR具体的な例として、 ARGBの紫からバイトを取得してみましょう。

ARGBでは、黄色は、、、、およびA=255であるため、これの16進バージョンは次のようになります。R=127G=0B=127

0xAARRGGBB
0xFF7F007F

16進値を見ると、それRRが最後から3番目のバイトであることがわかります。RRARGB値が変数に含まれるかどうかを確認するには、これをint pixel次のように入力することから始めましょう。

int pixel = 0xFF7F007F;

コードとの類似性に注意してください。ピクセルマトリックスのそれぞれintはARGBカラーです。

次に、数値を2バイト右にシフトしますRR。これにより、最下位バイトが次のようになります。

0x0000AARR
0x0000FF7F

これは次のコードで行われます:

int intermediate = pixel >> 16;

これ16は、右に2バイトシフトしたいという事実から来ており、各バイトには8ビットが含まれています。>>演算子はビットを期待しているので、2ではなく16を指定する必要があります。

次に、を取り除きたいのですがAA、そのままにしておきRRます。&これを行うには、演算子とともにビットマスクと呼ばれるものを使用します。ビットマスクは、2進数の特定のビットを選択するために使用されます。ここでは、が必要です0xFF。これは、バイナリで正確に8つの1です。(F16進数はそれぞれ2進数です1111。)

我慢してください、これは醜く見えるからです。私たちが行うときint red = intermediate & 0xFF、それが(バイナリで)行っていることは次のとおりです:

  0000 0000 0000 0000 1111 1111 0111 1111 (0x00007F7F)
& 0000 0000 0000 0000 0000 0000 1111 1111 (0x000000FF)
= 0000 0000 0000 0000 0000 0000 0111 1111 (0x0000007F)

&これは、両方の入力ビットが1の場合、結果のビットは1のみであることを意味します。

だから私たちはそれを得るred = 0x7Fred = 127、それはまさに私たちが上に持っていたものです。

編集:

yなぜ彼は、画像のピクセルを、その後xではなく、xから始めてループしているのyですか?そして、彼が変数を作成するとき、なぜ彼は幅pixelを掛けて加算するのでしょうか?ピクセルを取得するだけではいけませんか?yxx * y

簡単な3x3画像を使用してデモンストレーションしましょう。3x3の画像では、9ピクセルです。つまり、pixels配列には9つの要素があります。これらの要素はgetRGB、画像に対して行ごとに作成されるため、ピクセルとインデックスの関係は次のようになります。

0 1 2
3 4 5
6 7 8

位置は、そのピクセルを取得するために使用されるインデックスに対応します。したがって、画像の左上のピクセルを取得するには、、(0, 0)を使用しますpixel[0]。中央のピクセルを取得するには、、(1, 1)を使用しますpixel[4]。中央のピクセルの下のピクセルを取得するには、、(1, 2)を使用しますpixel[7]

これにより、次のように、画像座標からインデックスへの1:1マッピングが生成されることに注意してください。

Coord. -> Index
---------------
(0, 0) -> 0
(1, 0) -> 1
(2, 0) -> 2
(0, 1) -> 3
(1, 1) -> 4
(2, 1) -> 5
(0, 2) -> 6
(1, 2) -> 7
(2, 2) -> 8

座標は(x, y)ペアであるため、xとyのペアをインデックスに変換する数学的な方法を理解する必要があります。

楽しい数学に入ることができましたが、簡単にするためにそれはしません。x * yインデックスを取得するために使用して、提案から始めましょう。そうすると、次のようになります。

Coord. -> Index
-------------------
(0, 0) -> 0 * 0 = 0
(1, 0) -> 1 * 0 = 0
(2, 0) -> 2 * 0 = 0
(0, 1) -> 0 * 1 = 0
(1, 1) -> 1 * 1 = 1
(2, 1) -> 2 * 1 = 2
(0, 2) -> 0 * 2 = 0
(1, 2) -> 1 * 2 = 2
(2, 2) -> 2 * 2 = 4

これは上記のマッピングではないため、を使用しても機能しx * yません。getRGBピクセルの順序を変更することはできないため、上記のマッピングと一致させる必要があります。

彼の解決策を試してみましょう。彼の方程式は次のとおりですx = y * w。ここwで、は幅、この場合は3です。

Coord. -> Index
-----------------------
(0, 0) -> 0 + 0 * 3 = 0
(1, 0) -> 1 + 0 * 3 = 1
(2, 0) -> 2 + 0 * 3 = 2
(0, 1) -> 0 + 1 * 3 = 3
(1, 1) -> 1 + 1 * 3 = 4
(2, 1) -> 2 + 1 * 3 = 5
(0, 2) -> 0 + 2 * 3 = 6
(1, 2) -> 1 + 2 * 3 = 7
(2, 2) -> 2 + 2 * 3 = 8

マッピングが上記のものとどのように一致するかをご覧ください。これが私たちが望んでいたことです。基本的y * wに、ここで行っているのは、配列の最初のピクセルをスキップすることです。これは、ピクセルの行をy * wスキップするのとまったく同じです。y次に、を反復処理することによりx、現在の行の各ピクセルを反復処理します。

上記の説明から明らかでない場合は、ピクセルが水平()の順序で配列に行ごとに追加されるため、繰り返しy ます 。したがって、内側のループは値を繰り返し処理して、ジャンプしないようにする必要があります。 。同じを使用した場合、それを繰り返すと、反復が行われることになります。これは、ピクセル配列と同じ順序でバイトバッファに色を追加する必要があるため、望ましくありません。xxxy * w + xxy036147258

于 2012-10-14T20:52:48.823 に答える
0

各ピクセルは32ビット整数で表されます。その整数の左端の8ビットは、そのアルファコンポーネント、赤、緑、青の順になります。

(pixel >> 16) & 0xFF整数を16ビット右にシフトするため、その中の右端の8ビットが赤のコンポーネントになります。次に、ビットマスクを使用して他のすべてのビットをゼロに設定するため、赤いコンポーネントだけが残ります。同じロジックが他のコンポーネントにも適用されます。

参考文献。

于 2012-10-14T20:52:19.457 に答える
0

あなたが参照している奇妙な記号はシフト演算子であり、ビット単位のAND演算子だと思います。

>> nnビットで右にシフト

&& 0xFF与えられたバイナリ値の下位8ビットを取ることを意味します

つまり、forループは、pixel変数を4つの異なる8ビット部分に分解します。上位8ビットはアルファ、2番目は、3番目は、最後は青になります。

つまり、これは32ビットのマップです。

AAAAAAAARRRRRRRRGGGGGGGGBBBBBBBB

どこ:

  • A:アルファ
  • R:赤
  • G:緑
  • B:青
于 2012-10-14T20:52:55.397 に答える
0

RGBAの各コンポーネント(赤、緑、青、アルファ)には、256 = 2 ^ 8(= 1バイト)の異なる値があります。各コンポーネントを連結すると、32ビットのバイナリ文字列が生成され、forループがバイト単位でバッファにロードされます。

于 2012-10-14T20:58:05.980 に答える