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]> 
> 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]
> 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