OK, here is the proposed implementation: https://github.com/OpenImageIO/oiio/pull/1362 <https://github.com/OpenImageIO/oiio/pull/1362>
> On Feb 19, 2016, at 6:40 PM, Andrew Gartner <[email protected]> wrote: > > Hmm, good point, forgot about this. uint8 would be weird default on the > python side. > > I like the oiio.FLOAT default idea better than the others as it will probably > be more obvious what happened in their code should they happen to be using > the read without supplying the format. > > It may break things but it breaks them the "least" in my opinion. Requiring > the argument for every call is probably better long term but we're already > changing behavior with supplying oiio.UNKNOWN so we should probably confine > the real changes to those folks as best we can. > > Just my two cents. > > TL;DR: I'd go with oiio.FLOAT as a default > > ~Andrew > > On Fri, Feb 19, 2016 at 4:52 PM, Larry Gritz <[email protected] > <mailto:[email protected]>> wrote: > OK, just one more wrinkle. > > For a script that passes no format at all, the default is/was UNKNOWN, but > that changes behavior. Before, it would return an array based on spec.format > (the "widest" format of the channels). But now, it means to return a uint8 > blob of packed native data, which is "advanced usage" for sure, and possibly > not a good default. > > I propose changing the parameter default to oiio.FLOAT, which gives a > sensible behavior for apps as well as making it very likely that old apps > will continue to work in some kind of sensible way. > > Another way to go is to require the argument to be passed. That will break > old Python scripts, but will force everything to be explicit moving forward. > > > >> On Feb 19, 2016, at 11:49 AM, Haarm-Pieter Duiker <[email protected] >> <mailto:[email protected]>> wrote: >> >> Two thumbs up! (packed into one float thumbs up) >> >> HP >> >> >> >> >> On Fri, Feb 19, 2016 at 10:21 AM, Andrew Gartner <[email protected] >> <mailto:[email protected]>> wrote: >> Yep, I'm good with that. >> >> Thanks again for teasing this apart Larry/HP >> >> ~Andrew >> >> On Fri, Feb 19, 2016 at 10:09 AM, Larry Gritz <[email protected] >> <mailto:[email protected]>> wrote: >> OK, that sounds reasonable. So we have: >> >> * If you ask for a specific type, convert and return an array of that type. >> If you ask for HALF, the half bit pattern gets returned in a uint16 array, >> since there is no true half type. >> >> * If you ask for UNKNOWN (explicitly "give me raw data"), it returns an >> array of unsigned chars containing the raw data. >> >> Everybody can live with that? >> >> >>> On Feb 19, 2016, at 8:08 AM, Haarm-Pieter Duiker <[email protected] >>> <mailto:[email protected]>> wrote: >>> >>> Of the options "pass half values disguised as an unsigned short array" >>> feels the cleanest to me. You keep the right number of components in the >>> array, if you have any checks for that, and the data to be convert to halfs >>> is already grouped appropriately. >>> >>> Converting to halfs is also a one line call to numpy: >>> np.frombuffer(np.getbuffer(np.uint16(uint16Value)), dtype=np.float16) >>> Ex. https://github.com/hpd/CLF/blob/master/python/aces/clf/Common.py#L92 >>> <https://github.com/hpd/CLF/blob/master/python/aces/clf/Common.py#L92> >>> >>> HP >>> >>> >>> >>> >>> >>> On Thu, Feb 18, 2016 at 4:06 PM, Larry Gritz <[email protected] >>> <mailto:[email protected]>> wrote: >>> In C++, asking for UNKNOWN just copies the native format data and leaves it >>> for you to sort out. But to C++, a buffer is a buffer, you're passing it a >>> void* in any case. >>> >>> In Python, it's dynamic typing, so read_image RETURNS an array, and it has >>> to be an array of some type. Which type? >>> >>> I think we all are coming to agree that if you ask for UNKNOWN, probably >>> the most analogous thing (to C++) is to return an unsigned char array, >>> filled with the raw data, and leave you to sort it out. That's as close to >>> "untyped raw buffer" as we can get. >>> >>> If you *ask* for HALF, it's nonsensical, because you can't make an actual >>> half array in Python. You could promote and convert it to float. Or you >>> could return raw values in unsigned char array (like if you'd passed >>> UNKNOWN). Or, yeah, another possibility is to pass half values disguised as >>> an unsigned short array? >>> >>> I'm not super fond of the last choice. >>> >>> Right now, we do something stupider than any of those -- which is to pack >>> raw half values into a buffer, but the buffer advertises itself as being a >>> float array. That clearly needs to change. It was never intentional; I just >>> never thought carefully about that case because I never imagined anybody >>> asking for a type that didn't exist in Python. >>> >>> So, current proposal on the table: >>> >>> * If you ask for a type that can be a valid Python array type, convert and >>> return an array of that type. >>> >>> * If you ask for UNKNOWN (explicitly "give me raw data") or HALF >>> (implicitly so, because it doesn't exist in Python), it returns an array of >>> unsigned chars containing the raw data. >>> >>> >>> >>>> On Feb 18, 2016, at 3:36 PM, Haarm-Pieter Duiker <[email protected] >>>> <mailto:[email protected]>> wrote: >>>> >>>> Returning a series of unsigned 16 bit ints for a call with the type half >>>> feels like a nice middle ground. The consumer will have to know that halfs >>>> aren't natively supported in Python, and how to convert from unsigned >>>> short to half, but that doesn't feel like a large burden. >>>> >>>> I can't speak to the expected behavior of the UNKNOWN in Python. I haven't >>>> used that path in Python or C++. >>>> >>>> HP >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> On Thu, Feb 18, 2016 at 1:23 PM, Larry Gritz <[email protected] >>>> <mailto:[email protected]>> wrote: >>>> I don't have especially strong feelings about this one way or the other. >>>> >>>> Just returning a raw data byte array matches the C++ behavior more >>>> closely, no argument there. >>>> >>>> On the "con" side, perhaps I was thinking of compatibility? We're really >>>> talking about changing the meaning of oiio.UNKNOWN from "use spec.format" >>>> to "return raw data", which differ in the case of mixed channel types. >>>> >>>> Are there Python programs out there that pass UNKNOWN (or pass nothing, >>>> defaulting to UNKNOWN) and rely on getting the right kind of array back >>>> that matches spec.format? >>>> >>>> >>>> >>>> >>>>> On Feb 18, 2016, at 12:58 PM, Andrew Gartner <[email protected] >>>>> <mailto:[email protected]>> wrote: >>>>> >>>>> "Second, I could collapse 2a and 2b, and just say that if you ask for >>>>> UNKNOWN, you get an array of uint8 back with the native raw data" >>>>> >>>>> Just out of curiosity, what are the drawbacks to doing this? I admit I >>>>> like having some way of getting at the raw data at any time (hence my >>>>> original method of exposing the native calls). That allowed me to check >>>>> my imagespec and regardless of whether I had a mixed format image or all >>>>> half data I could get everything in one read call. Granted I'm used to >>>>> keeping track of and manipulating the strides of those arrays in bytes >>>>> just out of old habit (and C++ usage) so maybe I'm the minority opinion. >>>>> >>>>> Even so, your current thinking still works if that's where the consensus >>>>> is I'm happy to use it as such. >>>>> >>>>> Thanks again >>>>> >>>>> ~Andrew >>>>> >>>>> On Thu, Feb 18, 2016 at 12:21 PM, Larry Gritz <[email protected] >>>>> <mailto:[email protected]>> wrote: >>>>> I think that the only format that we can encounter as pixel data, which >>>>> does not exist in Python arrays, is 'half'. >>>>> >>>>> So let me rephrase my current thinking: >>>>> >>>>> 1. If you ask for a specific type (except HALF), you'll get a Python >>>>> array of that type holding the converted values. >>>>> >>>>> 2. Otherwise (i.e., you ask for UNKNOWN or HALF), you will get the native >>>>> (raw) data. >>>>> (a) If all channels are the same data type and it's anything but half, >>>>> you'll get the data as a Python array of that type. >>>>> (b) Otherwise (half, or mixed channel types), you'll get the data as a >>>>> Python array of unsigned bytes. >>>>> >>>>> Note that (1) is the easy case to deal with: ask for the type you want, >>>>> let it do the conversion. If you go for option (2) by asking for native >>>>> data, you get a blob and it's up to you to figure out what to do with it. >>>>> >>>>> There are two other choices we could make. I'm not inclined to at the >>>>> moment, but would be happy to do so if people think it's helpful. First, >>>>> if you ask for HALF, I could have it return float. Second, I could >>>>> collapse 2a and 2b, and just say that if you ask for UNKNOWN, you get an >>>>> array of uint8 back with the native raw data, even if it happened to be >>>>> all channels of the same type, a type that you could have made into a >>>>> Python array of the right type. >>>>> >>>>> >>>>>> On Feb 17, 2016, at 11:16 PM, Haarm-Pieter Duiker >>>>>> <[email protected] <mailto:[email protected]>> wrote: >>>>>> >>>>>> Picking this up a little later in the day. Sorry about that. Adding >>>>>> quotes from earlier in the thread just so it's clear what I'm responding >>>>>> to. >>>>>> >>>>>> The current status: >>>>>> " >>>>>> If you read_image(oiio.FLOAT) of a half image (on disk), you get floats >>>>>> back? >>>>>> " >>>>>> Yes. >>>>>> >>>>>> " >>>>>> But if you read_image(oiio.HALF) of a half image, you get what appears >>>>>> to be an array of floats, but they are actually packed half values? >>>>>> " >>>>>> Yes. >>>>>> >>>>>> The proposal: >>>>>> " >>>>>> 1. If you ask for a (non-UNKNOWN) format that exists in Python, it >>>>>> converts to and returns an array of that format. >>>>>> " >>>>>> This is the current behavior, no? >>>>>> >>>>>> " >>>>>> 2. If you ask for UNKNOWN, or a format that doesn't exist, it returns >>>>>> the raw data in an unsigned char array. >>>>>> " >>>>>> It feels like this is two proposals (Trying not to clash with your >>>>>> earlier 2a and 2b): >>>>>> 2c. If you ask for UNKNOWN, return raw data in an unsigned char array >>>>>> 2d. If you ask for a format that doesn't exist, return raw data in an >>>>>> unsigned char array >>>>>> >>>>>> 2c. feels right. It should work for the case of typical RGB or RGBA >>>>>> images but also for multi-layer EXRs. The consumer can convert the >>>>>> channels to their intended types using methods from the ImageSpec. I'd >>>>>> suggest that asking for UNKNOWN lead unequivocally to a raw unsigned >>>>>> char array. Supporting the special cases described in the 2a and 2b >>>>>> listed earlier would require additional logic on the consuming code side >>>>>> to account for those cases. Feels like a recipe for lots of brittle >>>>>> special case logic. >>>>>> >>>>>> 2d. is less clear. How is the change in behavior from returning real >>>>>> values for known types to returning raw char array data for unknown >>>>>> types signaled to the consumer? Is this still something that programmers >>>>>> have to just know a priori? How is this different from the current >>>>>> behavior? >>>>>> >>>>>> I suppose the list of types known to OIIO but not Python is finite and >>>>>> likely to shrink over time. Having special cases like we have in that >>>>>> example code, isn't such a big deal in the mean time, but then that's >>>>>> just saying the the current behavior is fine. >>>>>> >>>>>> Hope that's helpful in some way. Aside from agreeing that adding an >>>>>> UNKNOWN option is a good idea, we're still left without a good way to >>>>>> consume half data without accounting for it explicitly. >>>>>> >>>>>> HP >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> On Wed, Feb 17, 2016 at 4:35 PM, Andrew Gartner <[email protected] >>>>>> <mailto:[email protected]>> wrote: >>>>>> That would certainly take care of things for me. Hopefully not too much >>>>>> of an impact on others as well. >>>>>> >>>>>> ~Andrew >>>>>> >>>>>> >>>>>> >>>>>> On Wed, Feb 17, 2016 at 4:20 PM, Larry Gritz <[email protected] >>>>>> <mailto:[email protected]>> wrote: >>>>>> So I'm proposing: >>>>>> >>>>>> 1. If you ask for a (non-UNKNOWN) format that exists in Python, it >>>>>> converts to and returns an array of that format. >>>>>> >>>>>> 2. If you ask for UNKNOWN, or a format that doesn't exist, it returns >>>>>> the raw data in an unsigned char array. >>>>>> >>>>>> >>>>>> There is a variation: >>>>>> >>>>>> 2a. If you ask for UNKNOWN, and all channels are the same format and >>>>>> it's a type that exists in Python, return that type. >>>>>> 2b. If you ask for UNKNOWN and it's a "mixed type" file, or a single >>>>>> type but one that doesn't exist in Python, or the type you ask for >>>>>> doesn't exist in Python, return raw data packed into an unsigned char >>>>>> array. >>>>>> >>>>>> >>>>>> >>>>>>> On Feb 17, 2016, at 4:10 PM, Andrew Gartner <[email protected] >>>>>>> <mailto:[email protected]>> wrote: >>>>>>> >>>>>>> Yea the C++ implementation works well with oiio.UNKNOWN, I kinda miss >>>>>>> that in the python side to be honest. Right now it looks like things >>>>>>> revert back to spec.format if oiio.UNKNOWN is supplied to >>>>>>> read_scanlines, that can be problematic if you have multiple formats in >>>>>>> a single image so I've avoided it. >>>>>>> >>>>>>> @Larry, to you question about returning an unsigned char array, I like >>>>>>> the idea on principle in that it preserves the decoupling as you said. >>>>>>> I'm wondering if there would be any weirdness if you had to grab >>>>>>> multiple channels of an image that had different data types one of >>>>>>> which isn't representable in python? Would it default to just unsigned >>>>>>> char yet again in that case? >>>>>>> >>>>>>> @Haarm: interesting, I didn't realize they were concatenated/packed >>>>>>> like that! I just saw the 'f' in the python array and assumed I was >>>>>>> seeing promoted values :) I'm still scratching my head over the >>>>>>> multiple format reads though, same as for Larry's idea. >>>>>>> >>>>>>> Thanks for the replies, Cheers, >>>>>>> >>>>>>> ~Andrew >>>>>>> >>>>>>> >>>>>>> >>>>>>> On Wed, Feb 17, 2016 at 3:49 PM, Haarm-Pieter Duiker >>>>>>> <[email protected] <mailto:[email protected]>> wrote: >>>>>>> If you're up for using numpy, this will get you the half float values >>>>>>> without too much extra work: >>>>>>> oiioFloats = inputImage.read_image(oiio.HALF) >>>>>>> oiioHalfs = np.frombuffer(np.getbuffer(np.float32(oiioFloats)), >>>>>>> dtype=np.float16) >>>>>>> >>>>>>> One note, the current OIIO Python implementation doesn't promote the >>>>>>> halfs to float on read. The 'float' values in the returned buffer are >>>>>>> actually each two concatenated half values, and the float buffer will >>>>>>> have half as many entries as you would expect. >>>>>>> >>>>>>> Example usage for reading here: >>>>>>> https://github.com/hpd/CLF/blob/master/python/aces/filterImageWithCLF.py#L126 >>>>>>> >>>>>>> <https://github.com/hpd/CLF/blob/master/python/aces/filterImageWithCLF.py#L126> >>>>>>> and the reverse for writing: >>>>>>> https://github.com/hpd/CLF/blob/master/python/aces/filterImageWithCLF.py#L193 >>>>>>> >>>>>>> <https://github.com/hpd/CLF/blob/master/python/aces/filterImageWithCLF.py#L193> >>>>>>> >>>>>>> HP >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> On Wed, Feb 17, 2016 at 3:25 PM, Larry Gritz <[email protected] >>>>>>> <mailto:[email protected]>> wrote: >>>>>>> In C++, you can just call read_scanlines and pass format=UNKNOWN to get >>>>>>> back the raw data in its original format. >>>>>>> >>>>>>> The problem is that in Python, there is no 'half' so it's not quite >>>>>>> sure what to return. >>>>>>> >>>>>>> I kinda like the decoupling of the raw reads (read_native_*) which are >>>>>>> the part overloaded by the individual format readers, from the >>>>>>> app-callable read_*. So perhaps rather than exposing read_native_*, we >>>>>>> should just modify the Python bindings for read_* to notice that if the >>>>>>> native raw data is not a type representable in Python, to return it as >>>>>>> an unsigned character array? >>>>>>> >>>>>>> >>>>>>> > On Feb 17, 2016, at 2:55 PM, Andrew Gartner <[email protected] >>>>>>> > <mailto:[email protected]>> wrote: >>>>>>> > >>>>>>> > Hey all, >>>>>>> > >>>>>>> > Apologies if this has come up before, but I'm curious if anyone had >>>>>>> > considered exposing ImageInput.read_native_scanlines() on the python >>>>>>> > side before. The reason I ask is mainly because the half datatype >>>>>>> > doesn't exist in the native python array class which OIIO uses for >>>>>>> > python reads. Currently the python array will punt and for anything >>>>>>> > to float (which I'd rather avoid). >>>>>>> > >>>>>>> > I had put together an implementation in OIIO 1.5 that simply took the >>>>>>> > pixel size as a parameter and exposed read_native_scanlines that way >>>>>>> > and that allowed me to get the right data properly into either numpy >>>>>>> > or a raw char python array. However, I'd rather not be forked off >>>>>>> > like that as it's a headache trying to remain current with the >>>>>>> > mainline, plus others may find it useful. >>>>>>> > >>>>>>> > Does anyone think exposing the function in general makes sense? I'm >>>>>>> > happy to send the implementation if anyone cares to see it as well. >>>>>>> > >>>>>>> > Cheers, >>>>>>> > >>>>>>> > ~Andrew >>>>>>> > >>>>>>> >>>>>>> -- >>>>>>> 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 >>>>>>> <http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org> >>>>>>> >>>>>>> >>>>>>> _______________________________________________ >>>>>>> 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> >>>>>>> >>>>>>> >>>>>>> _______________________________________________ >>>>>>> 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 >>>>>> <http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org> >>>>>> >>>>>> >>>>>> >>>>>> _______________________________________________ >>>>>> 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> >>>>>> >>>>>> >>>>>> _______________________________________________ >>>>>> 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 >>>>> <http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org> >>>>> >>>>> >>>>> _______________________________________________ >>>>> 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 >>>> <http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org> >>>> >>>> >>>> _______________________________________________ >>>> 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 >>> <http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org> >>> >>> >>> _______________________________________________ >>> 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 >> <http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org> >> >> >> >> _______________________________________________ >> 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> >> >> >> _______________________________________________ >> 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 > <http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org> > > > _______________________________________________ > 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
