That code is a lot more complicated than it needs to be.  p is an unsigned 
char*, so there's no point doing the &0xff (unsigned chars only range from 
0-255), and if i is looping up to spec.nchannels, there's no reason to do the 
mod.  To have the same behavior, you could replace the entire scanline loop 
with:

       int n = std::min (3, spec.nchannels);
       for ( int x = 0; x < spec.width; x++ )
       {
           float rgb[3] = { 0, 0, 0 };
           for(int i=0; i<n; ++i) {
                rgb[i] = pixels[x*spec.nchannels+i];
           }
          newQImage.setPixel( x, y, qRgb( rgb[0], rgb[1], rgb[2] ) );
       }

That is still fairly inefficient -- I bet that there's a way to set an entire 
scanline (or image) at once, without having to call setPixel separately for 
every pixel, that's going to be very slow.  Also, you are allocating 'pixels' 
on every scanline, which will make quite a memory leak.

Now, back to the meat of your question.  The way your code is structured, 
you're reading the OpenEXR file (which is inherently floating point, either 
full or half precision, with 1.0 meaning "white") and converting it into UINT8 
(8 bit unsigned integer, 255 means white) in read_scanline, then copying those 
values back to r, g, b, which are float -- copying without any rescaling -- and 
passing those to qRgb.

So here's an important question: does qRgb expect those floating-point values 
to be in the 0.0-1.0 range?  Or 0.0-255.0?  You're passing the latter right 
now.  I'll try to give a solution both ways.

And the idea is that you think the OpenEXR file is linear values, but that you 
need the QImage to have sRGB values?

Also, since you seem to need floating point anyway, you should just keep it 
float all along.

    inline float linear_to_sRGB() (float x) {
        if (x < 0.0f)
            return 0.0f;
        return (x <= 0.0031308f) ? (12.92f * x)
                                 : (1.055f * std::pow (x, 1.f/2.4f) - 0.055f);
    }

QImage newQImage( spec.width, spec.height, QImage::Format_RGB32 );
int size = spec.width*spec.nchannels;
std::vector<float> pixels (size);   // note: will deallocate when it leaves 
scope
int n = std::min (3, spec.nchannels);
for (int y = 0; y < spec.height; y++) {
       in->read_scanline( y+spec.y, 0+spec.z, TypeDesc::FLOAT, &pixels[0] );
       for ( int x = 0; x < spec.width; x++ ) {
           float rgb[3] = { 0, 0, 0 };
           for (int i=0; i<n; ++i) {
                rgb[i] = linear_to_sRGB (pixels[x*spec.nchannels+i]);
                // AND, if you think qRgb needs 0-255.0 values, rather than 
0-1.0,
                // then also do this:
                // rgb[i] *= 255.0f;
           }
           newQImage.setPixel( x, y, qRgb( rgb[0], rgb[1], rgb[2] ) );
       }
   }


How does that look?



On Jul 14, 2011, at 7:05 AM, jeronimo wrote:

> 
> Hi,
> 
> I  would like to read exr files with linear color space. For that I'm using 
> OIIO but my viewer(Qt's QGraphicsView) shows the picture with sRGB color 
> space.
> How should I read log or linear color space inputs? Should I use OpenColorIO 
> for that task or develop an algorithm that converts from sRGB to 
> linear(lookup table)? I've copied the piece of code that it's reading the 
> file. Could you tell me if I'm reading correctly the files?
> 
> QImage newQImage( spec.width, spec.height, QImage::Format_RGB32 );
> int size = spec.width*spec.nchannels;
> for (int y = 0; y < spec.height; y++) {
>        unsigned char *pixels = new unsigned char[ size ];
>        in->read_scanline( y+spec.y, 0+spec.z, TypeDesc::UINT8, pixels );
>        for ( int x = 0; x < spec.width; x++ )
>        {
>            float r = 0;
>            float g = 0;
>            float b = 0;
> 
>            unsigned char *p = ( (unsigned char*) (pixels) );
>            for(int i=0; i<spec.nchannels; ++i)
>            {
>                int mod = i%spec.nchannels;
>                if(mod ==0)
>                {
>                    r = ((*p) & 0xff);
>                }
>                else if(mod ==1)
>                {
>                    g = ((*p) & 0xff);
>                }
>                else if(mod ==2)
>                {
>                    b = ((*p) & 0xff);
>                }
>                p++;
>            }
>           newQImage.setPixel( x, y, qRgb( r, g, b ) );
>           pixels = p;
>        }
>    }
> 
> Thank you very much,
> 
> Jero
> 
> _______________________________________________
> Oiio-dev mailing list
> [email protected]
> http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org

--
Larry Gritz
[email protected]


_______________________________________________
Oiio-dev mailing list
[email protected]
http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org

Reply via email to