3

I was wondering the meaning of "Bitwise Shifting". Currently I am trying to create Image Filters in Java using BufferedImage. I found some good answers on how to access the RGB values individually in other posts but wasnt exactly sure on how it works. I understand the RGB values are stored in a 32-bit int each 8-bit part representing the value.

This is what I was looking at: a link

Basically looking for someone to explain this process, the Google searches Ive done were too technical.

Community
  • 1
  • 1
0xOffset
  • 45
  • 1
  • 6
  • 1
    possible duplicate of [Absolute Beginner's Guide to Bit Shifting?](http://stackoverflow.com/questions/141525/absolute-beginners-guide-to-bit-shifting) and [many others](http://stackoverflow.com/search?q=what+is+bit+shifting&submit=search) – Matt Ball Dec 08 '11 at 19:05
  • 1
    Not really. I think he's trying to understand the representation, not bit-shifting, in general. – Wayne Dec 08 '11 at 19:12

4 Answers4

3

When you have a single integer that contains multiple bytes of information, then masking and shifting are the processes used to access the individual pieces. Assuming the bytes are stored like such (they probably aren't, but...) then this is what you could do to retrieve them:

aRGB: 255, 65, 33, 17
binary: 11111111 01000001 00100001 00010001

To retrieve the red value (65) from a variable x:

x && 0x00FF0000

  11111111 01000001 00100001 00010001
* 00000000 11111111 00000000 00000000
-------------------------------------
  00000000 01000001 00000000 00000000

Then the shifting operation, to move the bits to where they make sense as a lone value:

00000000 01000001 00000000 00000000 >> 16 = 00000000 00000000 00000000 01000001

The binary mask captures only the second byte of the value, by setting all the other bits to 0; only the bits that match the second byte remain as they are (multiplied by 1, not 0). Then, you shift the bits to the right 16 places, to strip off those extra 0's. Obviously, the leading 0's no longer matter, so the result is just a plain binary 01000001, or decimal 65.

Myrddin Emrys
  • 42,126
  • 11
  • 38
  • 51
  • My answer is about retrieving a byte from a combined value; @Angelo answered the opposite, how to build the combined value from the individual parts. Re-reading the link, I suspect Angelo's answer is more appropriate to the question. – Myrddin Emrys Dec 08 '11 at 19:21
2

It is technical in nature. You store a value 0 - 255, or in binary:

from
00000000
to
11111111

then you take a larger container like this one:

0000000000000000

and insert it there so if your color is 117

0000000001110101

and shift it to the left one byte so you get

0111010100000000

then you add the second color, say it 65 or 01000001 and get

0111010101000001

then you again shift it one byte to the left and get

011101010100000100000000

at last you add the third color and its for example a 255 or 11111111 you get

011101010100000111111111

so you have stored three values 0 - 255 via bitshift.

Angelo Fuchs
  • 9,825
  • 1
  • 35
  • 72
1

There is more than one way to think about a pattern of bits in memory. Usually, we think of the bits stored in an integer as representing a single number. The higher-order bits contribute greater value than the lower-order bits and their values are summed to arrive at a single number, so the following pattern:

00001101 00110000 00000111

Would be interpreted as:

2^0 + 2^1 + 2^3 + 2^13 + 2^14 + 2^15 + 2^17 + 2^18 = 864,263

But we're free to think of this pattern as three individual groups of 8-bit numbers (each representing the numeric value of a color component). However, to convert a bit pattern in the higher-order bits into the number we intend it to represent, we need to interpret those bits as though they appeared in the rightmost 8-bit group. This is why we shift.

For example, to get the value of the leftmost 8-bit group, we need to mask all bits not in that group, and then shift those bits 16 places to the right, so that they occupy the rightmost position:

// first, assume n = 00001101 00110000 00000111
(n & 0xFF0000) >> 16 // red

Zeros are automatically shifted into the vacated bits, leaving:

00000000 00000000 00001101

Which we can now interpret as:

13

Similarly, we can calculate the value of the bits in the center and rightmost groups:

(n & 0x00FF00) >> 8 // green
n & 0x0000FF // blue (no shift necessary)

Setting the value of one of these components requires shifting in the other direction. For example, the following shifts 75 into the center 8-bit position:

n = (n & (0xFF00FF)) | (75 << 8) 

We're first resetting the green value (with the 0xFF00FF mask) and then shifting the number 75 8 bits to the left. Finally, we combine these two numbers.

We can see that this works by shifting it back out again:

(n & 0x00FF00) >> 8 // => 75

Resetting or maximizing one of the components is even simpler. As we've seen in the earlier example, zero-ing a component can be done like this:

n = n & 0xFF00FF // clear out green

The following mask, on the other hand, maximizes the value of the green component:

n = n | 0x00FF00
Wayne
  • 59,728
  • 15
  • 131
  • 126
0

Bitwise operations are operations on the bits of the binary representation of the data rather than the data represented as an integer or floating point number. For example, 8 may be represented as 1000 in binary. Shifting it to the right twice moves all the digits to the right by 3, padding with 0's, resulting in 0010, or 2.

For more, see the Wikipedia article.

Dave
  • 5,133
  • 21
  • 27