Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

fredrum

macrumors newbie
Original poster
Dec 14, 2008
11
0
Hello all Christmas Crackers,

I am trying to convert some '16 bit planar RGB' data in memory into an array of 'rgba' structs, but can't figure out how to do it.

I am very inexperienced with this sort of thing.

I know that the buffer where the source image resides is made like this,

=============================
// three channels (RGB) in 16-bit (2 bytes) requires this much memory:
size_t memNeeded = width * height * 3U * 2U;
size_t adjusted = memNeeded;
// alloc this memory 16-byte aligned
unsigned char * imgbuffer = AlignedMalloc(adjusted);
=============================



I am told that when when it is written to disk with,

fwrite(imgbuffer, 1, memNeeded, fout);

it is "3 components, non-interleaved 16 bit with PC byte ordering"
I am not sure if this is a clue to how it is arranged in memory?


The closest I got was to have a loop like this and then write out the rgba struct array as an OpenEXR,

(width and height is the resolution of the image)
===========================================
int pixelCount=0;
for(i=0; i<height; i++){

for(j=0; j<width; j++){

exrPixels[j].r = imgbuffer[pixelCount];
exrPixels[j].g = imgbuffer[pixelCount+1];
exrPixels[j].b = imgbuffer[pixelCount+2];

exrPixels[j].a = 1.0;

pixelCount+=3;
}
}
=============================================


This gives me four tiled 'versions' of the image but only in the green channel. The red and blue channel has stuff that looks like noise(but of course its just mu fault).



I have tried looking for somewhere when someone explains this kind of stuff but haven't found anything online.

Does anyone know of any good websites?
Or could anyone give me a pointer to how to proceed,would be really great too?


cheers
fred
 
I can't really help you (never worked with exr files before) but according to this:
Code:
// three channels (RGB) in 16-bit (2 bytes) requires this much memory:
size_t memNeeded = width * height * 3U * 2U;
there are 2 bytes per components. But in your loading code, you consider it's only 1 byte (1 char) per components. Instead of unsigned char, try using unsigned short (or uint16_t).
Also, according the exr documentation, the 16 bits are in fact 16 bits floating point numbers.

it is "3 components, non-interleaved 16 bit with PC byte ordering"
I am not sure if this is a clue to how it is arranged in memory?
Yes it is. It means that the bytes are stored contiguously in little-endian order.

Sorry, I can't help you more than that. However, if you are developing for Mac OS X, it seems that Cocoa supports EXR files.
And, if you haven't checked already, wikipedia has an article about EXR with several links that could be interesting: http://en.wikipedia.org/wiki/OpenEXR
 
It looks like all the red pixels are defined in memory first, then the green and finally the blue. Also since the source is 16 bits per pixels and you're dealing with 8 bits you need to take the high byte. So, I think something lile this might work better:-

Code:
int pixelCount=0 ;
int redOffset = 1 ;
int greenOffset = width*height + 1 ;
int blueOffset = width*height*2 + 1 ;

for( i=0 ; i < height ; i++ )
{
   for( j = 0 ; j < width ; j++ )
   {
      exrPixels[i][j].r = imgbuffer[pixelCount];
      exrPixels[i][j].g = imgbuffer[ greenOffset +pixelCount ] ;
      exrPixels[i][j].b = imgbuffer[ blueOffset + pixelCount ] ;
      exrPixels[i][j].a = 255 ;

     pixelCount+=3;
   }	
}
 
Hi Again,

thank you both very much for your replies!

I am pretty sure that what I have now works, done based on lazydog's suggestion and then fiddled with 'til it worked.

I still don't really understand the 16 bit 'high byte' business. I know there is the little and big endians, so do you only have to skip the first byte(for PC ordering) and the total value 'sits' in the second one? I really need to go and learn some basics. :)

Anyhow this is what I ended up with and it looks right when I compare the result with a more professional exporter.

==============================================
int redOffset = 1;
int greenOffset = width * height * 2 + 1;
int blueOffset = width * height * 4 + 1;

for(i=0; i<height; i++){
for(j=0; j<width; j++){

exrPixels[j].r = imgbuffer[ redOffset + pixelCount ];
exrPixels[j].g = imgbuffer[ greenOffset + pixelCount ];
exrPixels[j].b = imgbuffer[ blueOffset + pixelCount ];

exrPixels[j].a = 1.0;


pixelCount+=2;
}
}
===============================================






Thank you both again!!
cheers
fred
 
Ah yes, there was some pretty silly mistakes in the code I posted... sorry about that. Taking the high byte is there because you need to map colours with 16 bit precision to the equivalent in only 8 bits of precision - the easiest and quickest thing to do is throw away the least significant 8 bits - a bit like rounding down a decimal number to fewer decimal places.

b e n
 
Hi Again,

thank you both very much for your replies!

I am pretty sure that what I have now works, done based on lazydog's suggestion and then fiddled with 'til it worked.

I still don't really understand the 16 bit 'high byte' business. I know there is the little and big endians, so do you only have to skip the first byte(for PC ordering) and the total value 'sits' in the second one? I really need to go and learn some basics. :)

Anyhow this is what I ended up with and it looks right when I compare the result with a more professional exporter.

==============================================
int redOffset = 1;
int greenOffset = width * height * 2 + 1;
int blueOffset = width * height * 4 + 1;

for(i=0; i<height; i++){
for(j=0; j<width; j++){

exrPixels[j].r = imgbuffer[ redOffset + pixelCount ];
exrPixels[j].g = imgbuffer[ greenOffset + pixelCount ];
exrPixels[j].b = imgbuffer[ blueOffset + pixelCount ];

exrPixels[j].a = 1.0;


pixelCount+=2;
}
}
===============================================






Thank you both again!!
cheers
fred

Hi, fredrum.

I seems you have worked with R3D file processing, right?
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.