简体   繁体   中英

c++ bmp bitwise operator

 for(unsigned int  h=0; h<ImageBits.iHeight; h++)
  {
        for(unsigned int  w=0; w<ImageBits.iWidth; w++)
        {
              // So in this loop - if our data isn't aligned to 4 bytes, then its been padded
              // in the file so it aligns...so we check for this and skip over the padded 0's
              // Note here, that the data is read in as b,g,r and not rgb as you'd think!
              unsigned char r,g,b;
              fread(&b, 1, 1, fp);
              fread(&g, 1, 1, fp);
              fread(&r, 1, 1, fp);

              ImageBits.pARGB[ w + h*ImageBits.iWidth ] = (r<<16 | g<<8 | b);

        }// End of for loop w

        //If there are any padded bytes - we skip over them here
        if( iNumPaddedBytes != 0 )
        {
              unsigned char skip[4];
              fread(skip, 1, 4 - iNumPaddedBytes, fp);
        }// End of if reading padded bytes

  }// End of for loop h

I do not understand this statement and how does it store the rgb value of the pixel

ImageBits.pARGB[ w + h*ImageBits.iWidth ] = (r<<16 | g<<8 | b);

i did a read up on the << bitwise shift operator but i still do not understand how it works.Can someone help me out here.

You need to convert separate values for Red, Green and Blue into a single variable, so you push them 16 and 8 bits to the "left" respectively, so they align 8 bits for Red (begin - 16), then you get 8 bits for Green (begin - 8) and the remaining color.

Consider the following:

 Red   -> 00001111
 Green -> 11110000
 Blue  -> 10101010

Then RGB -> that has 24 bits capacity would look like this initially ->
-> 00000000 00000000 00000000
(there would actually be some random rubbish but it's easier to
demonstrate like this)

Shift the Red byte 16 places to the left, so we get 00001111 00000000 00000000.
Shift the Green byte 8 places to the left, so we have 00001111 11110000 00000000.
Don't shift the Blue byte, so we have 00001111 11110000 10101010.

You could achieve a similar result with unions . Here's an ellaboration as to why we do it like this. The only way for you to access a variable is to have it's address (usually bound to a variable name, or an alias).

That means that we have an address of the first byte only and also a guarantee that if it's a variable that is 3 bytes wide, the following two bytes that are next to our addressed byte belong to us. So we can literally "push the bits" to the left ( shift them ) so they "flow" into the remaining bytes of the variable. We could also pointer-arithmetic a pointer there or as I've mentioned already, use a union.

Bit shifting moves the bits that make up the value along by the number you specify.

In this case it's done with colour values so that you can store multiple 1 byte components (such as RGBA which are in the range 0-255) in a single 4 byte structure such as an int

Take this byte:

00000011

which is equal to 3 in decimal. If we wanted to store the value 3 for the RGB and A channel, we would need to store this value in the int (the int being 32 bits)

R        G        B        A
00000011 00000011 00000011 00000011 

As you can see the bits are set in 4 groups of 8, and all equal the value 3, but how do you tell what the R value is when it's stored this way?

If you got rid of the G/B/A values, you'd be left with

00000011 00000000 00000000 00000000

Which still doesn't equal 3 - (in fact it's some massive number - 12884901888 I think)

In order to get this value into the last byte of the int, you need to shift the bits 24 places to the right. eg

12884901888 >> 24

Then the bits would look like this:

00000000 00000000 00000000 00000011

And you would have your value '3'

Basically it's just a way of moving bits around in a storage structure so that you can better manipulate the values. Putting the RGBA values into a single value is usually called stuffing the bits

let's visualize this and break it into several steps, and you'll see how simple it is.

let's say we have the ARGB 32 bit variable, that can be viewed as

int rgb = {a: 00, r: 00, g: 00, b: 00} (this is not valid code, of course, and let's leave the A out of this for now).

the value in each of these colors is 8 bit of course.

now we want to place a new value, and we have three 8 bit variables for each color:

unsigned char r = 0xff, g=0xff, b=0xff .

what we're essentially doing is taking a 32 bit variable, and then doing this:

rgb |= r << 16 (shifting the red 16 bit left. everything to right of it will remain 0)

so now we have

rgb = [a: 00, r: ff, g: 00, b: 00]

and now we do:

rgb = rgb | (g << 8) rgb = rgb | (g << 8) (meaning taking the existing value and OR'ing it with green shifted to its place)

so we have [a: 00, r: ff, g: ff, b: 00]

and finally...

rgb = rgb | b rgb = rgb | b (meaning taking the value and ORing it with the blue 8 bits. the rest remains unchanged)

leaving us with [a: 00, r: ff, g: f, b: ff]

which represents a 32 bit (24 actually since the Alpha is irrelevant to this example) color.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM