在Clojure中创建一个给定r g b的像素

时间:2015-09-03 11:57:52

标签: clojure

使用imagez我可以将图片中的像素设为[r g b]。使用这个colour wheel我已经证实这个提取部分几乎肯定能够正常工作。这是进行提取的imagez代码:

(defn components-rgb
  "Return the RGB components of a colour value, in a 3-element vector of long values"
  ([^long rgb]
   [(bit-shift-right (bit-and rgb 0x00FF0000) 16)
    (bit-shift-right (bit-and rgb 0x0000FF00) 8)
    (bit-and rgb 0x000000FF)]))

我需要做与提取相反的事情。以下是一些提取的“颜色值”(或像素)示例:

First pixel: -6700606 (in HEX: FFFFFFFFFF99C1C2)  
Last pixel: -11449516 (in HEX: FFFFFFFFFF514B54)  
First as colour: [153 193 194] (in HEX: 99 C1 C2)   
Last as colour: [81 75 84] (in HEX: 51 4B 54)   

相反的做法意味着[153 193 194]变为-6700606。之前已经在SO上询问了这个问题,例如here。以下是我的两个不起作用的尝试:

;rgb = 0xFFFF * r + 0xFF * g + b
(defn my-rgb-1 [[r g b]]
  (+ (* 0xFFFF r) (* 0xFF g) b))  

;int rgb = ((r&0x0ff)<<16)|((g&0x0ff)<<8)|(b&0x0ff);
(defn my-rgb-2 [[r g b]]
(let [red (bit-shift-left 16 (bit-and r 0x0FF))
      green (bit-shift-left 8 (bit-and g 0x0FF))
      blue (bit-and b 0x0FF)]
 (bit-or red green blue)))

图像 - 1 - &gt;提取像素 - 2 - > rgb color - 3 - &gt;写入像素 - 4 - &gt;图像

步骤1和2正在运行,但步骤3不是。如果步骤3工作提取 - 像素将与写入像素相同。

imagez中有一个rgb函数,但它对我来说也不起作用。 (作者更新了我说不应该这样做。见here)。我还可以补充一点,imagez函数get-pixel首先用于获取像素(步骤1),然后是components-rgb(步骤2),如上所示。

看看here,我已经概述了步骤。

2 个答案:

答案 0 :(得分:0)

如果我理解你的问题 - 你遇到的问题是:

"First pixel" in hex is i.e 0xFFFFFFFFF99C1C2
 you convert it to decimal-rgb via `components-rgb` = [153 193 194]
 you re-convert [153 193 194] to int via `rbg` and get 
  0x99C1C2
which by all means is correct

因为默认情况下clojure使用很长时间你需要做的事情 使用unchecked-intlong定格为int,如下所示:

(unchecked-int 0xFFFFFFFFFF99C1C2)
-6700606

这是你想要的 - 对吧?

答案 1 :(得分:0)

我有错误顺序左移位的参数。所以这是改进的my-rgb-2

的基本版本
(defn my-rgb-2 [[r g b]]
  (let [red (bit-shift-left r 16)
        green (bit-shift-left g 8)
        blue b]
    (bit-or red green blue)))

我已经离开了(bit-and a 0x0FF),(其中a是r,g或b),只是因为只有当数字大于255时才需要,这无论如何都不是正确的值。对于这个答案,它是否存在并不重要。

接下来要做的是将所有0xF(所有4位填充)放在开头。这几乎让我在那里:

(defn my-rgb-2 [[r g b]]
  (let [red (bit-shift-left (bit-and r 0x0FF) 16)
        green (bit-shift-left (bit-and g 0x0FF) 8)
        blue (bit-and b 0x0FF)]
    (bit-or 0xFFFFFFFFF000000 (bit-or red green blue))))  

不幸的是,如果我在最后一行再添加一个0xF:

Exception in thread "main" java.lang.IllegalArgumentException: bit operation not supported for: class clojure.lang.BigInt

但是可以通过借用@birdspider给出的答案来解决这个问题:

(defn my-rgb-2 [[r g b]]
  (let [red (bit-shift-left (bit-and r 0x0FF) 16)
        green (bit-shift-left (bit-and g 0x0FF) 8)
        blue (bit-and b 0x0FF)]
    (bit-or (bit-or red green blue) (unchecked-int 0xFFFFFFFFFF000000))))

imagez库现在具有此功能,但出于性能原因而作为宏完成。