it looks like this Email can't hold image.

here is my simple test code:


        //exr sequence from S25_0010.exr to S25_0079.exr
        std::string base = 
"C:/Users/Lo_Fnatic/Desktop/nima/S25_00";
&nbsp; &nbsp; &nbsp; &nbsp; for (int i = 10; i < 80; i++) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; std::string file_allpath = base + 
std::to_string(i) + std::string(".exr");
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; std::thread t([=]() {


&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //just construction.
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ImageBuf 
buf(file_allpath);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //buf.read(0, 0, 15, 
18, true, TypeDesc::UINT8);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; t.detach();
&nbsp; &nbsp; &nbsp; &nbsp; }



it will cost almost 32G memory even though i am not ready to read these pixel 
data.
thanks




------------------&nbsp;Original&nbsp;------------------
From:                                                                           
                                             "oiio-dev"                         
                                                           
<oiio-dev-requ...@lists.openimageio.org&gt;;
Date:&nbsp;Sun, May 15, 2022 02:15 AM
To:&nbsp;"oiio-dev"<oiio-dev@lists.openimageio.org&gt;;

Subject:&nbsp;Oiio-dev Digest, Vol 164, Issue 4



Send Oiio-dev mailing list submissions to
        oiio-dev@lists.openimageio.org

To subscribe or unsubscribe via the World Wide Web, visit
        http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org
or, via email, send a message with subject or body 'help' to
        oiio-dev-requ...@lists.openimageio.org

You can reach the person managing the list at
        oiio-dev-ow...@lists.openimageio.org

When replying, please edit your Subject line so it is more specific
than "Re: Contents of Oiio-dev digest..."


Today's Topics:

&nbsp;&nbsp; 1. How to Load channel from EXR file with a little memory usage.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (=?gb18030?B?qICogKiAqIC5zg==?=)
&nbsp;&nbsp; 2. Re: How to Load channel from EXR file with a little memory
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; usage. (Larry Gritz)
&nbsp;&nbsp; 3. Re: How to Load channel from EXR file with a little memory
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; usage. (Larry Gritz)


----------------------------------------------------------------------

Message: 1
Date: Sat, 14 May 2022 23:28:29 +0800
From: "=?gb18030?B?qICogKiAqIC5zg==?=" <15952002...@qq.com&gt;
To: "=?gb18030?B?b2lpby1kZXY=?=" <oiio-dev@lists.openimageio.org&gt;
Subject: [Oiio-dev] How to Load channel from EXR file with a little
        memory usage.
Message-ID: <tencent_77ef28dd6d2d2359af2ccc5ca8ce66b74...@qq.com&gt;
Content-Type: text/plain; charset="gb18030"

Hello.
I'm trying to load OpenEXR sequence to memory then draw them with Opengl.
but these EXR files are so big with many sub-channels in(one file with 300M and 
more than 30 channels).
&amp;nbsp;i just want to load the "Beauty" pass.


here is what i was tried:


&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ImageBuf buf = 
ImageBuf::ImageBuf(exr_filepath);
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; const ImageSpec&amp;amp; spec = 
buf.spec();
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; int xres = spec.width;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; int yres = spec.height;


&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; //&amp;nbsp; &amp;nbsp;i just want 
to load the RGB data from the "Beauty" pass
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; std::vector<UINT8&amp;gt; 
pixels(xres * yres * 3);


&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; //&amp;nbsp; &amp;nbsp;for example 
the Beauty pass start with index of 15
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ROI roi(0, xres, 0, yres, 0, 1, 
/*chans:*/ 15, 18);
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; buf.get_pixels(roi, 
TypeDesc::UINT8, &amp;amp;pixels[0]);



it works. but cost a huge amount of memory use with multi-threading(sometimes 
more than 80G) during loading all files.
here is my quesion:
like what i did. is this way to load all data together then save the "Beauty 
data" from them to the std::vector?
or just load the "Beauty" pass without cache all exr data first?
is this memory usage normal?


and i have checked the document. it looks like the ImageCache class is what i 
want. can i use this class in my situation?
is there anywhere i can find more example about this class?


thanks!
kong
-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
<http://lists.openimageio.org/pipermail/oiio-dev-openimageio.org/attachments/20220514/a7118f41/attachment-0001.html&gt;

------------------------------

Message: 2
Date: Sat, 14 May 2022 10:59:36 -0700
From: Larry Gritz <l...@larrygritz.com&gt;
To: OpenImageIO dev list <oiio-dev@lists.openimageio.org&gt;
Subject: Re: [Oiio-dev] How to Load channel from EXR file with a
        little memory usage.
Message-ID: <68429dd3-80ae-444c-b06b-70dfed031...@larrygritz.com&gt;
Content-Type: text/plain; charset="utf-8"

I think that the problem here is that the ImageBuf will read in all the 
channels, even though the get_pixels only copies out the 3 channels you need. 
The I/O itself happens "lazily", triggered by the get_pixels call itself 
needing pixel values, but at that point, it still doesn't know that you won't 
subsequently try to access other channels in the ImageBuf, so the channel 
restriction of get_pixels doesn't turn into a channel restriction for how the 
file is read and stored.

Additionally, the ImageBuf will by default store the pixels in whatever the 
"widest" data type of the file itself has (in the case of an OpenEXR, that 
would mean half at best, and maybe float depending on what's in your file), 
even though ultimately you only want UINT8 data in your program. (And if the 
file is large, there's also probably yet another copy, or partial copy, in the 
underlying ImageCache.)

But I think you can fix all of these issues by doing an explicit 
ImageBuf::read() before the first time you access the pixels, using the version 
of read() that lets you select the channel range and data type:

&nbsp;&nbsp;&nbsp; buf.read(/*subimage*/ 0, /*miplevel*/ 0,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
/*chbegin*/ 15, /*chend*/ 18,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
/*forceread*/ true, /*convert*/ TypeDesc::UINT8);
&nbsp;&nbsp;&nbsp; // ... then ...

&nbsp;&nbsp;&nbsp; // BEWARE! now channels 15... of the file are stored in 0... 
of the buf!
&nbsp;&nbsp;&nbsp; ROI roi(0, xres, 0, yres, 0, 1, /*chans:*/ 0, 4);
&nbsp;&nbsp;&nbsp; buf.get_pixels(roi, TypeDesc::UINT8, &amp;pixels[0]);

Now the buf will internally store only 3 channels of UINT8.

See where I passed true for the "forceread" parameter? That forces it to read 
the image right then, skipping use of the ImageCache and storing the entire 
image in memory (well, the channels you asked for, I mean). So the ImageBuf 
itself holds the channels you asked for, without an extra copy in the 
ImageCache. The ImageCache is usually very helpful, especially if you only need 
a small portion of a large image at any one time by one thread. The one case 
where it's wasteful is if you need an entire image all at once, and it can fit 
into memory so there is no benefit to reading it piece by piece only as needed.

And given that we have the whole image loaded into the ImageBuf without any 
ImageCache backing, it's possible that you can do one more better thing, 
depending on how you use the data. With the forced read, the ImageBuf itself 
holds channels 15,16,17 as UINT8, contiguously in memory starting at address 
localpixels(). So do you really need the pixels to be copied (and stored again) 
in your std::vector? Or can you directly use the ImageBuf's internal storage of 
the pixels?

You can test if an ImageBuf's pixels are all in memory:

&nbsp;&nbsp;&nbsp; if (buf.storage() == ImageBuf::LOCALBUFFER)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; address = (const uint8*) 
buf.localpixels();

Actually, I think localpixels() will return nullptr if it doesn't use local 
storage, so you don't need the separate check of storage(), but I still wanted 
to point that out.

(I think everything I have written is true. Please double check it.)


&gt; On May 14, 2022, at 8:28 AM, ????? <15952002...@qq.com&gt; wrote:
&gt; 
&gt; Hello.
&gt; I'm trying to load OpenEXR sequence to memory then draw them with Opengl.
&gt; but these EXR files are so big with many sub-channels in(one file with 
300M and more than 30 channels).
&gt;&nbsp; i just want to load the "Beauty" pass.
&gt; 
&gt; here is what i was tried:
&gt; 
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ImageBuf buf = 
ImageBuf::ImageBuf(exr_filepath);
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const ImageSpec&amp; spec 
= buf.spec();
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int xres = spec.width;
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int yres = spec.height;
&gt; 
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; i just want 
to load the RGB data from the "Beauty" pass
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::vector<UINT8&gt; 
pixels(xres * yres * 3);
&gt; 
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; for example 
the Beauty pass start with index of 15
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ROI roi(0, xres, 0, yres, 
0, 1, /*chans:*/ 15, 18);
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buf.get_pixels(roi, 
TypeDesc::UINT8, &amp;pixels[0]);
&gt; 
&gt; it works. but cost a huge amount of memory use with 
multi-threading(sometimes more than 80G) during loading all files.
&gt; here is my quesion:
&gt; like what i did. is this way to load all data together then save the 
"Beauty data" from them to the std::vector?
&gt; or just load the "Beauty" pass without cache all exr data first?
&gt; is this memory usage normal?
&gt; 
&gt; and i have checked the document. it looks like the ImageCache class is 
what i want. can i use this class in my situation?
&gt; is there anywhere i can find more example about this class?
&gt; 
&gt; thanks!
&gt; kong
&gt; 
&gt; _______________________________________________
&gt; Oiio-dev mailing list
&gt; Oiio-dev@lists.openimageio.org
&gt; http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org

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





-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
<http://lists.openimageio.org/pipermail/oiio-dev-openimageio.org/attachments/20220514/80e79745/attachment-0001.html&gt;

------------------------------

Message: 3
Date: Sat, 14 May 2022 11:15:51 -0700
From: Larry Gritz <l...@larrygritz.com&gt;
To: OpenImageIO dev list <oiio-dev@lists.openimageio.org&gt;
Subject: Re: [Oiio-dev] How to Load channel from EXR file with a
        little memory usage.
Message-ID: <b12c7b0e-e77c-497e-a7d2-669b73d1c...@larrygritz.com&gt;
Content-Type: text/plain; charset="utf-8"

By the way, for those following along, if you're wondering how to make oiiotool 
take these very same shortcuts:

&nbsp;&nbsp;&nbsp; oiiotool -i:ch=R,G,B:type=uint8:now=1 foo.exr ...


&gt; On May 14, 2022, at 10:59 AM, Larry Gritz <l...@larrygritz.com&gt; wrote:
&gt; 
&gt; I think that the problem here is that the ImageBuf will read in all the 
channels, even though the get_pixels only copies out the 3 channels you need. 
The I/O itself happens "lazily", triggered by the get_pixels call itself 
needing pixel values, but at that point, it still doesn't know that you won't 
subsequently try to access other channels in the ImageBuf, so the channel 
restriction of get_pixels doesn't turn into a channel restriction for how the 
file is read and stored.
&gt; 
&gt; Additionally, the ImageBuf will by default store the pixels in whatever 
the "widest" data type of the file itself has (in the case of an OpenEXR, that 
would mean half at best, and maybe float depending on what's in your file), 
even though ultimately you only want UINT8 data in your program. (And if the 
file is large, there's also probably yet another copy, or partial copy, in the 
underlying ImageCache.)
&gt; 
&gt; But I think you can fix all of these issues by doing an explicit 
ImageBuf::read() before the first time you access the pixels, using the version 
of read() that lets you select the channel range and data type:
&gt; 
&gt;&nbsp;&nbsp;&nbsp;&nbsp; buf.read(/*subimage*/ 0, /*miplevel*/ 0,
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 /*chbegin*/ 15, /*chend*/ 18,
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 /*forceread*/ true, /*convert*/ TypeDesc::UINT8);
&gt;&nbsp;&nbsp;&nbsp;&nbsp; // ... then ...
&gt; 
&gt;&nbsp;&nbsp;&nbsp;&nbsp; // BEWARE! now channels 15... of the file are 
stored in 0... of the buf!
&gt;&nbsp;&nbsp;&nbsp;&nbsp; ROI roi(0, xres, 0, yres, 0, 1, /*chans:*/ 0, 4);
&gt;&nbsp;&nbsp;&nbsp;&nbsp; buf.get_pixels(roi, TypeDesc::UINT8, 
&amp;pixels[0]);
&gt; 
&gt; Now the buf will internally store only 3 channels of UINT8.
&gt; 
&gt; See where I passed true for the "forceread" parameter? That forces it to 
read the image right then, skipping use of the ImageCache and storing the 
entire image in memory (well, the channels you asked for, I mean). So the 
ImageBuf itself holds the channels you asked for, without an extra copy in the 
ImageCache. The ImageCache is usually very helpful, especially if you only need 
a small portion of a large image at any one time by one thread. The one case 
where it's wasteful is if you need an entire image all at once, and it can fit 
into memory so there is no benefit to reading it piece by piece only as needed.
&gt; 
&gt; And given that we have the whole image loaded into the ImageBuf without 
any ImageCache backing, it's possible that you can do one more better thing, 
depending on how you use the data. With the forced read, the ImageBuf itself 
holds channels 15,16,17 as UINT8, contiguously in memory starting at address 
localpixels(). So do you really need the pixels to be copied (and stored again) 
in your std::vector? Or can you directly use the ImageBuf's internal storage of 
the pixels?
&gt; 
&gt; You can test if an ImageBuf's pixels are all in memory:
&gt; 
&gt;&nbsp;&nbsp;&nbsp;&nbsp; if (buf.storage() == ImageBuf::LOCALBUFFER)
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; address = (const uint8*) 
buf.localpixels();
&gt; 
&gt; Actually, I think localpixels() will return nullptr if it doesn't use 
local storage, so you don't need the separate check of storage(), but I still 
wanted to point that out.
&gt; 
&gt; (I think everything I have written is true. Please double check it.)
&gt; 
&gt; 
&gt;&gt; On May 14, 2022, at 8:28 AM, ????? <15952002...@qq.com 
<mailto:15952002...@qq.com&gt;&gt; wrote:
&gt;&gt; 
&gt;&gt; Hello.
&gt;&gt; I'm trying to load OpenEXR sequence to memory then draw them with 
Opengl.
&gt;&gt; but these EXR files are so big with many sub-channels in(one file with 
300M and more than 30 channels).
&gt;&gt;&nbsp; i just want to load the "Beauty" pass.
&gt;&gt; 
&gt;&gt; here is what i was tried:
&gt;&gt; 
&gt;&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ImageBuf buf = 
ImageBuf::ImageBuf(exr_filepath);
&gt;&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const ImageSpec&amp; 
spec = buf.spec();
&gt;&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int xres = spec.width;
&gt;&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int yres = spec.height;
&gt;&gt; 
&gt;&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; i just 
want to load the RGB data from the "Beauty" pass
&gt;&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::vector<UINT8&gt; 
pixels(xres * yres * 3);
&gt;&gt; 
&gt;&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; for 
example the Beauty pass start with index of 15
&gt;&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ROI roi(0, xres, 0, 
yres, 0, 1, /*chans:*/ 15, 18);
&gt;&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buf.get_pixels(roi, 
TypeDesc::UINT8, &amp;pixels[0]);
&gt;&gt; 
&gt;&gt; it works. but cost a huge amount of memory use with 
multi-threading(sometimes more than 80G) during loading all files.
&gt;&gt; here is my quesion:
&gt;&gt; like what i did. is this way to load all data together then save the 
"Beauty data" from them to the std::vector?
&gt;&gt; or just load the "Beauty" pass without cache all exr data first?
&gt;&gt; is this memory usage normal?
&gt;&gt; 
&gt;&gt; and i have checked the document. it looks like the ImageCache class is 
what i want. can i use this class in my situation?
&gt;&gt; is there anywhere i can find more example about this class?
&gt;&gt; 
&gt;&gt; thanks!
&gt;&gt; kong
&gt;&gt; 
&gt;&gt; _______________________________________________
&gt;&gt; Oiio-dev mailing list
&gt;&gt; Oiio-dev@lists.openimageio.org 
<mailto:Oiio-dev@lists.openimageio.org&gt;
&gt;&gt; http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org
&gt; 
&gt; --
&gt; Larry Gritz
&gt; l...@larrygritz.com <mailto:l...@larrygritz.com&gt;
&gt; 
&gt; 
&gt; 
&gt; 
&gt; 
&gt; _______________________________________________
&gt; Oiio-dev mailing list
&gt; Oiio-dev@lists.openimageio.org
&gt; http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org

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





-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
<http://lists.openimageio.org/pipermail/oiio-dev-openimageio.org/attachments/20220514/dce8c2a6/attachment.html&gt;

------------------------------

Subject: Digest Footer

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


------------------------------

End of Oiio-dev Digest, Vol 164, Issue 4
****************************************
_______________________________________________
Oiio-dev mailing list
Oiio-dev@lists.openimageio.org
http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org

Reply via email to