这是一个简单的代码,只对窗口着色4次. 也许有一些我看不到的明显事物. 我的目标是从头开始学习计算机图形,我想逐个像素地绘制以完全控制.我正在寻找一种快速的方法来做到这一点
也许有一些我看不到的明显事物.
我的目标是从头开始学习计算机图形,我想逐个像素地绘制以完全控制.我正在寻找一种快速的方法来做到这一点.
Here是完整代码.
相关的clojure部分:
(defmacro for-loop [[sym init check change :as params] & steps] `(loop [~sym ~init value# nil] (if ~check (let [new-value# (do ~@steps)] (recur ~change new-value#)) value#))) (time (for-loop [k 0 (< k 2) (inc k)] (for-loop [c 0 (< c 2) (inc c)] (for-loop [i 0 (< i width) (inc i)] (for-loop [j 0 (< j height) (inc j)] (aset ^ints @pixels (+ i (* j width)) (get cs c)))) (.repaint canvas))))
java中的相同代码:
long t = System.currentTimeMillis(); for (int k = 0 ; k < 2; k++) { for (int c = 0; c < 2; c++) { for (int i = 0 ; i < width; i++) { for (int j = 0; j < height; j++) { pixels[i + j * width] = cs[c]; } } repaint(); } } System.out.println(System.currentTimeMillis() - t);有几个问题:
>如果你运行lein检查,你会看到反射警告.你在运行时强制反射会降低速度.我将画布创建更改为:
(defonce canvas (doto (proxy [Frame] [] (update [g] (.paint this g)) (paint [^Graphics2D g] (.drawImage g, ^BufferedImage image, 0, 0 nil))) (.setSize width height) (.setBackground Color/black) (.setFocusableWindowState false) (.setVisible true)))
注意我正在使用的类型提示.它不知道要使用哪个drawImage重载,并且完全找不到paint方法.
>然而,主要问题是使用aset.来自aset的文档:
Sets the value at the index/indices. Works on Java arrays of
reference types. Returns val.
强调我的.
问题是aset不适用于原语.它强制将每个数字包装为整数,然后在图像中使用时再次打开.当在图像的每个像素上相乘时,这是非常昂贵的.
将aset更改为aset-int以改为使用int基元.这将执行时间从大约20秒缩短到半秒.
老实说,我不能低估它.它比它快得多,但仍然比Java版本慢约20倍.我现在已经工作了将近2个小时,而且我已经撞墙了.希望其他人可以挤出最后一点时间.