I had a few minutes to experiment with this, and I think this is the simplest 
roll-your-own RAII approach:

struct TileReleaser {
    TileReleaser(ImageCache& ic) : ic(ic) {}
    void operator()(ImageCache::Tile* tile) { ic.release_tile(tile); }
private:
    ImageCache& ic;
};

using TileHolder = std::unique_ptr<ImageCache::Tile, TileReleaser>;


Example use:

{
    // construct a unique_ptr that will release the tile upon destruction
    TileHolder tile(imagecache->get_tile(filename, 0, 0, 0, 0, 0),
                    TileReleaser(*imagecache));

    // example of using the pointer via get()
    TypeDesc format;
    void* pels = imagecache->tile_pixels(tile.get(), format);

    // The tile will automatically release when it exits scope
}


Though, as I said before, it's extremely rare that ordinary developers need to 
use the get_tile/release_tile API.


> On Oct 13, 2020, at 4:52 PM, Larry Gritz <[email protected]> wrote:
> 
> 
> 
>> On Oct 13, 2020, at 2:15 PM, Arman Garakani <[email protected] 
>> <mailto:[email protected]>> wrote:
>> 
>> 2. Not calling release: got it. I am sure you have thought about a RAII way 
>> of dealing with this. 
> 
> I hadn't really thought about this, but I think it would be fairly trivial, 
> like this sketch (caveat: I'm just typing this off the top of my head):
> 
> struct TileHolder {
>     ImageCache* ic;
>     ImageCache::Tile* tile;
> 
>     // construct from pointers to IC and Tile (presumably returned by 
> ic->get_tile())
>     TileHolder(ImageCache* ic, ImageCache::Tile* tile)
>         : ic(ic), tile(tile) {}
> 
>     // destructor releases the tile
>     ~TileHolder() { ic->release_tile(tile); }
> 
>     // operator() returns the Tile*
>     ImageCache::Tile* operator()() const { return tile; }
> };
> 
> then use something like:
> 
>     TileHolder th(ic, ic->get_tile(filename, subimage, miplevel, x, y, z));
>     ...
>     roi = ic->tile_roi(th());
>     ...
>     // When th exists scope, ic->release_tile(th()) is automatically called
> 
> Would something like this be generally handy for me to add to imagecache.h to 
> make it easier to juggle the Tile*'s?
> 
> The reason I didn't bother is that the Tile* interface is very specialized 
> and advanced. I didn't expect people to directly use it except in very rare 
> circumstances. The usual way to interact with ImageCache is either through 
> get_pixels (which copies whatever pixels you need to your buffer, without 
> needing to worry about how the tiles work at all), or by using ImageBuf 
> (which looks like an image, has pixel Iterator classes to traverse them, and 
> hides all the underlying ImageCache mechanism for large images).
> 
> 
>> 
>> 3. Number of sub images:
>> 
>>    The takeaway is that get_imagespec returns the spec for current sub 
>> image. For multi-image files, calling it repeatedly returns the current sub 
>> image count. Hence calling it repeatedly, gets the number of sub images. Got 
>> it. 
> 
> It does, but you can ask for the number of subimages directly (as in my 
> explanation), without having to copy spec after spec until you fail.
> 
> 
> 
>> The issue that I have is time stamps on a multi-image tif aka tif stack. I 
>> know there are time stamp information for every image. However I can not 
>> find a way to fetch them through the API. I could use the sub image index. 
>> If I could get duration  or FramePerSecond ( floating point or a rational 
>> number ). Am I missing the API ? Does it make sense to support ?
> 
> Yes, like if you wanted the DateTime for each subimage, you could get it with:
> 
>     ustring datetime;
>     ic->get_image_info (filename, subimage, /*miplevel=*/ 0, 
> ustring("DateTime"), OIIO::TypeString, &datetime);
> 
> This is assuming you want to use the ImageCache approach at all. Do you need 
> unlimited numbers of high-res images open all at the same time, but using a 
> small and fixed amount of memory and without having to keep track of any 
> allocations or open file handles? That's what IC is supposed to be for.
> 
> If you are primarily accessing just one or a few images/subimages at any one 
> time, it's probably easier to just use the ImageBuf interface:
> 
>     // Make an ImageBuf for a file (by default, first subimage)
>     ImageBuf buf(filename);
> 
>     // How many subimages does this image have?
>     int nsubimages = buf.nsubimages();
> 
>     // Point to a different subimage
>     buf.reset(filename, subimage);
> 
>     // Directly ask for some metadata about that subimage
>     std::string datetime = buf.spec().get_string_attribute("DateTime");
>     
>     // Copy some pixels to my area, with data type conversion
>     buf.get_pixels(roi, TypeFloat, my_float_ptr);
> 
> 
> --
> 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