16 bit planar RGB from memory

Discussion in 'Mac Programming' started by fredrum, Dec 20, 2008.

  1. fredrum macrumors newbie

    Joined:
    Dec 14, 2008
    #1
    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
     
  2. ncl macrumors member

    Joined:
    Aug 16, 2008
    #2
    I can't really help you (never worked with exr files before) but according to this:
    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.

    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
     
  3. lazydog macrumors 6502a

    Joined:
    Sep 3, 2005
    Location:
    Cramlington, UK
    #3
    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;
       }	
    }
    
     
  4. fredrum thread starter macrumors newbie

    Joined:
    Dec 14, 2008
    #4
    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
     
  5. lazydog macrumors 6502a

    Joined:
    Sep 3, 2005
    Location:
    Cramlington, UK
    #5
    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
     

Share This Page