In what way doesn't it work properly? Does it crash? Appear to do nothing? Do 
something but not what you expect? What kind of image are you trying (I mean, 
what data type and channels)?

I can only speak in generalities without this info, but here's what I spotted 
as likely problems.

* ConstIterator/Iterator<float> is likely to be problematic, because it 
requires the buffer itself to be float. (Is it?) Usually we write a function 
like your normalize as a template and then have a big switch statement that 
selects a specialized variety based on the data type. (This may not really be a 
problem if all of your images are stored as 'float' buffers internally.)

* You initialized 'min' (why are these half?) to 0.0, which means that "if 
(it[c] < min)" will probably never be true (unless you have negative values), 
so it probably is not going to compute the correct minimum. A better way to 
compute min/max would be:

    float min = 1e6f;
    float max = -1e6f;
    ...
    for (int c = 0; c < nchannels; ++c) {
        min = std::min(max, it[c]);
        max = std::max(max, it[c]);
    }

* Depending on your image, you may also find that scaling all channels based on 
the biggest min/max may be wrong, particularly if it has any non-color chanels 
like alpha or Z.


So OIIO 2.1 (a release candidate now, scheduled to be the official supported 
release in 3 days!) has a function that does everything you want. Assuming 
you're able to use that, here's how I recommend doing this operation robustly 
(this is off the top of my head, I have not tested, so take with a grain of 
salt, but this is the basic idea):

    ImageBufAlgo::PixelStats stats = ImageBufAlgo::computePixelStats(*image);
    float min = 1e6f;
    float max = -1e6f;
    int nc = std::min (3, image->nchannels());  // only consider R,G,B
    for (int c = 0; c < nc; ++c) {
        min = std::min(max, stats.min[c]);
        max = std::max(max, stats.max[c]);
    }
    ROI roi = image->roi();
    roi.chend = 3;  // only rescale at most the first three channels!
    ImageBufAlgo::contrast_remap(*image, *image, min, max, 0.0f, 1.0f, 1.0, 
0.5, roi);


Using IBA::computePixelStats and contrast_remap has two big advantages over 
writing the loops yourself: (1) it handles every data type that OIIO supports, 
not just float; and (2) will go much faster because internally it's 
multithreaded!



> On Nov 27, 2019, at 4:31 PM, Chris Dawlud <kdaw...@protonmail.com> wrote:
> 
> Hi,
> 
> I want to normalize exr to make even very bright/dark images visible.
> The idea is simple but I can't figure out how to do this correctly.
> 
> I have come up with the following, but it doesn't work properly:
> void ImageLoader::normalize(OIIO::ImageBuf* image)
> {
>       using namespace OIIO;
> 
>       auto min = half{ 0.0f };
>       auto max = half{ 0.0f };
> 
>       for (auto it = ImageBuf::ConstIterator<float>{ *image }; !it.done(); 
> ++it)
>               for (auto c = 0; c < image->nchannels(); ++c) {
>                       if (it[c] < min) min = it[c];
>                       if (it[c] > max) max = it[c];
>               }
> 
>       for (auto it = ImageBuf::Iterator<float>{ *image }; !it.done(); ++it)
>               for (auto c = 0; c < image->nchannels(); ++c)
>                       it[c] = 0.0f + (it[c] - min) * ( 1.0f  - 0.0f ) / (max 
> - min);
> 
> }
> 
> _______________________________________________
> Oiio-dev mailing list
> Oiio-dev@lists.openimageio.org
> http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org

--
Larry Gritz
l...@larrygritz.com




_______________________________________________
Oiio-dev mailing list
Oiio-dev@lists.openimageio.org
http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org

Reply via email to