私はBufferedImageをとり、ByteBufferを返す関数を作ろうとしています。それでOpenGLテクスチャとして使うことができます。そうするために、私は私の質問に本当に関係のないバイトシフトをしなければならないことを学んだ。 BufferedImageの値はRGBGBを必要とするARGBおよびOpenGLと関係しています。どのようにすれば、このバッファをもっと速く塗りつぶすことができますか?
私は(Javaから)を実装しようとしている機能はこの1つである:
public static ByteBuffer toByteBuffer(BufferedImage img){
byte[] byteArray = new byte[img.getWidth()*img.getHeight()*4];
for(int i = 0; i < img.getWidth()*img.getHeight(); i++){
int value = img.getRGB(i%img.getWidth(), (i-(i%img.getWidth()))/img.getWidth());
byteArray[i*4] = (byte) ((value<<8)>>24);
byteArray[i*4+1] = (byte) ((value<<16)>>24);
byteArray[i*4+2] = (byte) ((value<<24)>>24);
byteArray[i*4+3] = (byte) (value>>24);
}
return (ByteBuffer) ByteBuffer.allocateDirect(byteArray.length).put(byteArray).flip();
}
そして、これはClojureのと私の試みです:
(defn sub-byte [^long b ^long x]
(unchecked-byte (-> x
(bit-shift-left (* 8 b))
(bit-shift-right 24))))
(defn bufferedimage->bytebuffer [^BufferedImage img]
(binding [*unchecked-math* true]
(let [w (.getWidth img)
h (.getHeight img)
^bytes arr (make-array Byte/TYPE (* 4 w h))]
(loop [i 0]
(let [img-i (mod i w)
img-j (quot i w)
value (.getRGB img img-i img-j)]
(aset arr (* i 4) (sub-byte 1 value))
(aset arr (+ 1 (* i 4)) (sub-byte 2 value))
(aset arr (+ 2 (* i 4)) (sub-byte 3 value))
(aset arr (+ 3 (* i 4)) (sub-byte 0 value))
(when (< (+ i 1) (* w h)) (recur (+ i 1)))
))
(cast ByteBuffer (-> (ByteBuffer/allocateDirect (count arr))
(.put arr)
(.flip))))))
これは512をロードするために10秒かかります* 512タイルセット。これはまったく受け入れられません。これを1秒未満で実行しようとしています。
すべての時間を費やしている部分がループであることに注意してください。
これらの時間はREPLを使用して取得されることに言及しているかもしれません。
また、コードのパフォーマンスに重大な影響を及ぼす部分についてはJavaを使用できることをよく知っているので、これは理論的な質問のほうが多いので、クロージャコードを最適化する方法を学ぶことができます。
'clojure.core/time'を使って、コードのどの部分が最も時間を費やすかを測定できます。 –
私はすでにしました。私のポストから: "いつも取っている部分はループです"。 – Setzer22
[Criterium](https://github.com/hugoduncan/criterium)は、ベンチマークのためのより良い方法です。一般的に、 'map'、' reduce'、 'filter'はおそらく' loop/recur'よりもスピードとイディオムの方が良い選択でしょう。 – jmargolisvt