views:

324

answers:

4

I'm developping imaging functions (yes I REALLY want to reinvent the wheel for various reasons).

I'm copying bitmaps into unsigned char arrays but I'm having some problem with byte size versus image pixel format.

for example a lot of images come as 24 bits per pixel for RGB representation so that's rather easy, every pixel has 3 unsigned chars (bytes) and everyone is happy

however sometimes the RGB has weirder types like 48 bits per pixel so 16 bits per color channel. Copying the whole image into the byte array works fine but its when I want to retrieve the data that things get blurry

Right now I have the following code to get a single pixel for grayscale images

unsigned char NImage::get_pixel(int i, int j)
   {
   return this->data[j * pitch + i];
   }

NImage::data is unsigned char array

This returns a single byte. How can I access my data array with different pixel formats?

A: 

At 48 bits per pixel, with 16 bit per color, you can't return an 8 bit value, you must return a 16 bit short or unsigned short otherwise the data gets truncated.

You might try developing overloaded functions to handle this.

A: 

What's the problem with 48bits per pixel? Simply read your data as uint16_t or unsigned short and you get the 16 bit extracted properly.

It gets worse for more complicated bit pattern, i.e. rgb565 where you'll need to extract data using bitmasks.

Alexander Gessler
+1  A: 

You should do it like this:

unsigned short NImage::get_pixel(int i, int j)
   {
       int offset = 2 * (j * pitch + i);
      // image pixels are usually stored in big-endian format
      return data[offset]*256 + data[offset+1];
   }
alemjerus
+1 for accounting for endianness.
jamesdlin
Regarding endianness, be careful as this property is format specific. For example, JIFF stores words in big-endian, GIF in little-endian, however TIFF can use both. In case of TIFF, first byte of header is an indicator: 0x49 for little endian and 0x4D for big endian.
mloskot
A: 

You have to know how big your pixels are.

If it's RGB then your 100x100 pixel image (say) will have 30,000 unsigned chars.

unsigned char NImage::get_red_component(int i, int j) 
{ 
    return this->data[3*(j * pitch + i)]; 
}

unsigned char NImage::get_green_component(int i, int j) 
{ 
    return this->data[3*(j * pitch + i) + 1]; 
}

unsigned char NImage::get_blue_component(int i, int j) 
{ 
    return this->data[3*(j * pitch + i) + 2]; 
}

Or for 48-bit RGB,

unsigned char NImage::get_red_MSB(int i, int j) 
{ 
    return this->data[6*(j * pitch + i)]; 
}

unsigned char NImage::get_red_LSB(int i, int j) 
{ 
    return this->data[6*(j * pitch + i) + 1]; 
}

... etc etc ...
John at CashCommons