2

Using imagez I can get a pixel from an image as [r g b]. Using this colour wheel I have verified that this extraction part is almost certainly working. This is the imagez code that does the extraction:

(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)]))

I need to do the opposite of this extraction. Here are some examples of the 'colour value' (or pixel) being extracted:

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)   

Doing the opposite would mean that [153 193 194] becomes -6700606. This question has been asked before on SO, for example here. Here are two of my attempts which do not work:

;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)))

image --1--> extracted-pixel --2--> rgb colour --3--> to-write-pixel --4--> image

Steps 1 and 2 are working, but step 3 is not. If step 3 were working extracted-pixel would be the same as to-write-pixel.

There is an rgb function in imagez, but it too does not work for me. (The author updated me to say it is not supposed to. See here). I might also add that the imagez function get-pixel is first used to get the pixel (step 1), followed by components-rgb (step 2) as shown above.

Take a look here where I have outlined the steps.

6
  • 1
    I suggest you post the hexadecimal representation of the colors instead of the decimal one, it will be more clear for you and for us. Commented Sep 3, 2015 at 12:00
  • your my-rgb-2 attempt: the commented line is a description of what you want? Then you are missing a few bit-shift-lefts (you do the bit-ands and bit-ors - but decided to ignore << ?) Commented Sep 3, 2015 at 14:00
  • also (format "0x%x" -6700606) => "0xffffffffff99c1c2" is possiblty helpful when printing bits/hex Commented Sep 3, 2015 at 14:02
  • There is an rgb function in imagez, but it too does not work for me. can you clarify this ? the function looks exactly like what you want ? Commented Sep 3, 2015 at 14:10
  • github.com/chrismurrph/want-pixel/blob/master/src/my/issue.clj clarifies that the existing rgb function in imagez does not work for me. Thanks. Commented Sep 3, 2015 at 15:08

2 Answers 2

0

If I understand your poblem correctly - the issue you have is that:

"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

since clojure by default uses long the only thing you need to do is use a unchecked-int to trucate the long to int as so:

(unchecked-int 0xFFFFFFFFFF99C1C2)
-6700606

which is what you want - right ?

Sign up to request clarification or add additional context in comments.

1 Comment

Looking at issue.clj you can use any of existing-rgb, my-rgb-1 or my-rgb-2. Last time I looked none of them returned the right answer.
0

I had the arguments to bit-shift-left in the wrong order. So this is a basic version of the improved 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)))

I have left off (bit-and a 0x0FF), (where a is r, g or b), simply because it is only necessary if the number is more than 255, which would not be a proper value anyway. For this answer it doesn't really matter whether it is there or not.

The next thing to do is put all the 0xF (all 4 bits filled in) at the beginning. This nearly gets me there:

(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))))  

Unfortunately if I put one more 0xF on the last line I get:

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

But that can be fixed by borrowing from the answer @birdspider gave:

(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))))

The imagez library now has this function, but done as a macro for performance reasons.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.