如何在Clojure中更快地填充此缓冲区

Setzer22

我正在尝试制作一个函数,该函数将使用BufferedImage并返回一个ByteBuffer,然后可以将其用作OpenGL纹理。为此,我了解到我必须进行一些字节移位,这与我的问题并没有真正的关系。它与BufferedImage值为ARGB和需要RGBA的OpenGL有关。

我要实现的功能(从Java)是这样的:

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 * 512切片集需要10秒钟,这是完全不能接受的。我正在尝试以不到一秒钟的速度运行该程序。

请注意,一直花费时间的部分是循环。

我不妨提及那些时间是使用REPL进行的。

另外,请注意,我很清楚我可以在代码的性能关键部分使用java,因此这更多是一个理论问题,因此我可以学习如何优化clojure代码。

皮奥特里克·比兹尔(Piotrek Bzdyl)

当您设置使用功能的解决方案的问题显露*warn-on-reflection*true

(set! *warn-on-reflection* true)

加载代码时,编译器将告诉您sub-byte函数返回Object,并且无法静态解析匹配方法。

Reflection warning, web_app/so.clj:26:11 - call to static method aset on clojure.lang.RT can't be resolved (argument types: [B, int, java.lang.Object).

不幸的是,你不能用一个类型提示byte返回值,你的函数,因为只有longdouble图元支持作为返回类型:

(defn sub-byte ^byte [^long b ^long x]
  (unchecked-byte (-> x
                      (bit-shift-left (* 8 b))
                      (bit-shift-right 24))))

CompilerException java.lang.IllegalArgumentException: Only long and double primitives are supported, compiling:(web_app/so.clj:7:1)

您可能会尝试将提示^long作为返回类型,但提示的结果类型不是您的函数体返回的内容(byte):

(defn sub-byte ^long [^long b ^long x]
  (unchecked-byte (-> x
                      (bit-shift-left (* 8 b))
                      (bit-shift-right 24))))

CompilerException java.lang.IllegalArgumentException: Mismatched primitive return, expected: long, had: byte, compiling:(web_app/so.clj:7:1)

但是,您可以使函数返回,long但随后您必须将其包装在任何地方,unchecked-byte这样您就可以消除所有反射警告:

(defn sub-byte ^long [^long b ^long x]
  (-> x
      (bit-shift-left (* 8 b))
      (bit-shift-right 24))))

(unchecked-byte (sub-byte ...))

另一种解决方案是使用已经发现的宏,这样可以避免函数调用及其返回类型出现任何问题。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何在到达缓冲区而不是缓冲区已满时读取缓冲区中的数据?

来自分类Dev

此代码如何使缓冲区溢出

来自分类Dev

如何及时填充ALSA缓冲区

来自分类Dev

如何及时填充ALSA缓冲区

来自分类Dev

如何在Vim中替换整个缓冲区的内容

来自分类Dev

如何在Swift中附加协议缓冲区?

来自分类Dev

如何在vim中浏览缓冲区?

来自分类Dev

缓冲区如何在Java IO中工作?

来自分类Dev

如何在Arcgis Android中获取Road的缓冲区?

来自分类Dev

如何在缓冲区中执行代码?

来自分类Dev

如何在Python中合并多个缓冲区对象?

来自分类Dev

如何在Netty中解码未知长度的缓冲区?

来自分类Dev

如何在php中设置输出缓冲区名称?

来自分类Dev

如何在C中返回缓冲区地址

来自分类Dev

如何在流缓冲区C中添加参数

来自分类Dev

如何在Vulkan中重新分配缓冲区

来自分类Dev

如何在tmux shell的输出缓冲区中搜索?

来自分类Dev

如何在cmd缓冲区中退格字符?

来自分类Dev

如何在NSIS中本机访问内存缓冲区

来自分类Dev

如何在lwjgl中绑定缓冲区

来自分类Dev

如何在 Lucee 中重置头缓冲区?

来自分类Dev

在emacs中,如何在不单独打开每个缓冲区的情况下杀死多个缓冲区

来自分类Dev

存储缓冲区和行填充缓冲区如何相互影响?

来自分类Dev

如何防止strncpy_s在调试版本中填充目标缓冲区?

来自分类Dev

填充GHC Haskell中的可变缓冲区时如何获得类似于C的性能

来自分类Dev

如何初始化数组并用缓冲区中的字符填充?

来自分类Dev

如何防止strncpy_s在调试版本中填充目标缓冲区?

来自分类Dev

在emacs的* nrepl *缓冲区中评估Clojure命名空间

来自分类Dev

在emacs的* nrepl *缓冲区中评估Clojure命名空间

Related 相关文章

热门标签

归档