I'm still concerned about your initialization of the "min" variable. Can you 
see how this will give the incorrect result if the minimum pixel value in your 
image is > 0 ?

As written below, this will scale up the lightest values to fully "white", but 
it will fail to convert the darkest values to fully black.



> On Nov 27, 2019, at 6:14 PM, Chris Dawlud <[email protected]> wrote:
> 
> Thank you. It makes a lot of sense.
> I completely forgot about discarding alpha channel. Also, I'm using half 
> format so in my specific case I should have used half instead of float in the 
> iterator constructor.
> 
> For future reference, here's the working code:
> void ImageLoader::normalize(OIIO::ImageBuf* image)
> {
>       using namespace OIIO;
> 
>       auto stats = ImageBufAlgo::computePixelStats(*image);
> 
>       auto min = 0.0f;
>       auto max = 0.0f;
> 
>       auto nc = std::min(3, image->nchannels());
> 
>       for (auto c=0; c < nc; ++c) {
>               min = std::min(min, stats.min[c]);
>               max = std::max(max, stats.max[c]);
>       }
> 
>       auto roi = image->roi();
>       roi.chend = nc;
>       ImageBufAlgo::contrast_remap(*image, *image, min, max, 0.0f, 1.0f, 1.0, 
> 0.5f, roi);
> }
> 
> 
> 
> ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
> On Thursday, 28 November 2019 02:32, Larry Gritz <[email protected]> wrote:
> 
>> To clarify: I believe that the contrast_remap function is new in OIIO 2.1. 
>> On older versions, or merely if you prefer it, I think you could achieve the 
>> same thing with
>> 
>>     ImageBufAlgo::sub(*image, *image, min, roi);
>>     ImageBufAlgo::mul(*image, *image, (max-min), roi);
>> 
>> Note also that this whole business of passing the roi explicitly is to limit 
>> the pixel alterations to just the first 3 channels. You almost surely don't 
>> want to scale the alpha values or any additional channels.
>> 
>> 
>>> On Nov 27, 2019, at 5:27 PM, Larry Gritz <[email protected] 
>>> <mailto:[email protected]>> wrote:
>>> 
>>> 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 <[email protected] 
>>>> <mailto:[email protected]>> 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
>>>> [email protected] <mailto:[email protected]>
>>>> http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org 
>>>> <http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org>
>>> 
>>> 
>>> --
>>> Larry Gritz
>>> [email protected] <mailto:[email protected]>
>>> 
>>> 
>>> 
>>> 
>>> _______________________________________________
>>> Oiio-dev mailing list
>>> [email protected] <mailto:[email protected]>
>>> http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org
>> 
>> 
>> --
>> Larry Gritz
>> [email protected] <mailto:[email protected]>
>> 
> 
> _______________________________________________
> 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