1

How to do a binary left shift in a integer value using Ruby?


I'm trying to do a left shift binary operation but I'm getting a strange char instead of the move..

I think that it should perform like this: (java)

b = (b >> 2); //0011 1111
b = (b << 2); //1111 1100

I'm doing this in ruby:

currentRed = ChunkyPNG::Color.r(image[x,y])
currentGreen = ChunkyPNG::Color.g(image[x,y])
currentBlue = ChunkyPNG::Color.b(image[x,y])

binRed = currentRed.to_s.unpack("b*")[0]
binGreen = currentGreen.to_s.unpack("b*")[0]
binBlue = currentBlue.to_s.unpack("b*")[0]

puts "original"

puts "r #{binRed}"
puts "g #{binGreen}"
puts "b #{binBlue}"

puts "------"

binRed = binRed << 2

binGreen = binGreen << 2
binBlue = binBlue << 2


puts "new"

puts "r #{binRed}"
puts "g #{binGreen}"
puts "b #{binBlue}"

and getting it:

enter image description here

thank you in advance..

Alexandre
  • 363
  • 7
  • 20
  • 1
    What is your question? – sawa Oct 08 '13 at 19:19
  • How transform rgb values into integer binary form? I tried transform the rgb values into binary form like this: binRed = currentRed.to_s(2) binGreen = currentGreen.to_s(2) binBlue = currentBlue.to_s(2) but I got the same result as in the printscreen above.. because they still string.. – Alexandre Oct 08 '13 at 22:27

2 Answers2

4

Your binRed, binGreen, binBlue are actually Strings, because b* unpack into bitstrings. For Strings, << means append, so no wonder the strange character (character code 2) got printed.

I'm not familiar with ChunkyPNG, but from the doc it looks like currentRed, currentGreen, currentBlue are already integers. You should be able to perform bit shift on them directly.

Worakarn Isaratham
  • 1,034
  • 1
  • 9
  • 16
  • Thank you Worakam, you are right.. and yes currentRed, currentGreen and currentBlue are integers but they are rgb values, I need to transform them into binary and then perform bit shift... do you know how to do this? – Alexandre Oct 08 '13 at 22:22
  • You don't need to transform them to binary (because they're already binary under the hood). Just do `currentRed<<2` and it will shift 2 bits to the left... And if you want to truncate them down to 24 bits as in original, you can mask them with 0xFFFFFF. So something like `currentRed = (currentRed<<2) & 0xFFFFFF` should serve your need. – Worakarn Isaratham Oct 09 '13 at 02:51
  • Doing this I've got: --------- original r 253 g 253 b 253 ------ new r 1012 g 1012 b 1012 that's correct? I need do the left shift because I'm trying to perform a last significant bit change to put my data in a png. – Alexandre Oct 10 '13 at 13:25
  • @Alexandre Shifting left by 2 bits is the same as multiplying by 4, so your results are correct. 253 * 4 = 1012. If you just want to alter the last bits of an integer number, you don't need to shift them at all. – Mecki Apr 20 '19 at 01:52
2

In Ruby, << is a method. Actually most operators in Ruby are methods:

a = b << c
a = b + c
a = b ** c

# This is exactly the same as

a = b.<<(c)
a = b.+(c)
a = b.**(c)

You can even override them in your own classes to make them do whatever you want them to do. This is possibly as in Ruby everything (really everything) is an object under the hood (even classes and modules are objects, even nil is an object).

E.g. for a String the << method means append.

a = "Hello, " << "Word"
# a == "Hello, Word"

But in case of a Fixnum the << method just means shift left:

a = 5 << 2
# a == 20

So you are using the right "operator" but you need to make sure your objects are of the right class. You require integers which are of type Fixnum in Ruby.

And currentRed, currentBlue, and currentGreen are of type Fixnum already.

Mecki
  • 125,244
  • 33
  • 244
  • 253