diff --git a/src/libOpenImageIO/exif.cpp b/src/libOpenImageIO/exif.cpp index c9eeadafe9..433fa0530b 100644 --- a/src/libOpenImageIO/exif.cpp +++ b/src/libOpenImageIO/exif.cpp @@ -341,9 +341,11 @@ version4uint8_handler(const TagInfo& taginfo, const TIFFDirEntry& dir, bool /*swapendian*/ = false, int offset_adjustment = 0) { const char* data = (const char*)dataptr(dir, buf, offset_adjustment); - if (tiff_data_size(dir) == 4 && data != nullptr) // sanity check - spec.attribute(taginfo.name, TypeDesc(TypeDesc::UINT8, 4), - (const char*)data); + if (tiff_data_size(dir) == 4 && data != nullptr) { // sanity check + int val[4] = { (unsigned char)data[0], (unsigned char)data[1], + (unsigned char)data[2], (unsigned char)data[3] }; + spec.attribute(taginfo.name, TypeDesc(TypeDesc::INT, 4), val); + } } diff --git a/src/python/py_imagespec.cpp b/src/python/py_imagespec.cpp index 8ac62e4c84..a0c4151acb 100644 --- a/src/python/py_imagespec.cpp +++ b/src/python/py_imagespec.cpp @@ -50,24 +50,7 @@ ImageSpec_getattribute_typed(const ImageSpec& spec, const std::string& name, const ParamValue* p = spec.find_attribute(name, tmpparam, type); if (!p) return py::none(); - type = p->type(); - if (type.basetype == TypeDesc::INT) - return C_to_val_or_tuple((const int*)p->data(), type); - if (type.basetype == TypeDesc::UINT) - return C_to_val_or_tuple((const unsigned int*)p->data(), type); - if (type.basetype == TypeDesc::INT16) - return C_to_val_or_tuple((const short*)p->data(), type); - if (type.basetype == TypeDesc::UINT16) - return C_to_val_or_tuple((const unsigned short*)p->data(), type); - if (type.basetype == TypeDesc::FLOAT) - return C_to_val_or_tuple((const float*)p->data(), type); - if (type.basetype == TypeDesc::DOUBLE) - return C_to_val_or_tuple((const double*)p->data(), type); - if (type.basetype == TypeDesc::HALF) - return C_to_val_or_tuple((const half*)p->data(), type); - if (type.basetype == TypeDesc::STRING) - return C_to_val_or_tuple((const char**)p->data(), type); - return py::none(); + return make_pyobject(p->data(), p->type(), p->nvalues()); } @@ -238,7 +221,7 @@ declare_imagespec(py::module& m) [](const ImageSpec& self, const std::string& key, py::object def) { ParamValue tmpparam; auto p = self.find_attribute(key, tmpparam); - return p ? ParamValue_getitem(*p, false, def) : def; + return p ? make_pyobject(p->data(), p->type(), 1, def) : def; }, "key"_a, "default"_a = py::none()) .def( @@ -285,7 +268,7 @@ declare_imagespec(py::module& m) auto p = self.find_attribute(key, tmpparam); if (p == nullptr) throw py::key_error("key '" + key + "' does not exist"); - return ParamValue_getitem(*p); + return make_pyobject(p->data(), p->type()); }) // __setitem__ is the dict-like `ImageSpec[key] = value` assignment .def("__setitem__", diff --git a/src/python/py_oiio.cpp b/src/python/py_oiio.cpp index cb9877a134..af4bf37b92 100644 --- a/src/python/py_oiio.cpp +++ b/src/python/py_oiio.cpp @@ -219,6 +219,47 @@ oiio_attribute_typed(const std::string& name, TypeDesc type, +py::object +make_pyobject(const void* data, TypeDesc type, int nvalues, + py::object defaultvalue) +{ + if (type.basetype == TypeDesc::INT32) + return C_to_val_or_tuple((const int*)data, type, nvalues); + if (type.basetype == TypeDesc::FLOAT) + return C_to_val_or_tuple((const float*)data, type, nvalues); + if (type.basetype == TypeDesc::STRING) + return C_to_val_or_tuple((const char**)data, type, nvalues); + if (type.basetype == TypeDesc::UINT32) + return C_to_val_or_tuple((const unsigned int*)data, type, nvalues); + if (type.basetype == TypeDesc::INT16) + return C_to_val_or_tuple((const short*)data, type, nvalues); + if (type.basetype == TypeDesc::UINT16) + return C_to_val_or_tuple((const unsigned short*)data, type, nvalues); + if (type.basetype == TypeDesc::INT64) + return C_to_val_or_tuple((const int64_t*)data, type, nvalues); + if (type.basetype == TypeDesc::UINT64) + return C_to_val_or_tuple((const uint64_t*)data, type, nvalues); + if (type.basetype == TypeDesc::DOUBLE) + return C_to_val_or_tuple((const double*)data, type, nvalues); + if (type.basetype == TypeDesc::HALF) + return C_to_val_or_tuple((const half*)data, type, nvalues); + if (type.basetype == TypeDesc::UINT8 && type.arraylen > 0) { + // Array of uint8 bytes + // Have to make a copy of the data, because make_numpy_array will + // take possession of it. + uint8_t* ucdata(new uint8_t[type.arraylen * nvalues]); + std::memcpy(ucdata, data, type.arraylen * nvalues); + return make_numpy_array(ucdata, 1, 1, size_t(type.arraylen), + size_t(nvalues)); + } + if (type.basetype == TypeDesc::UINT8) + return C_to_val_or_tuple((const unsigned char*)data, type, nvalues); + debugfmt("Don't know how to handle type {}\n", type); + return defaultvalue; +} + + + static py::object oiio_getattribute_typed(const std::string& name, TypeDesc type = TypeUnknown) { @@ -227,13 +268,7 @@ oiio_getattribute_typed(const std::string& name, TypeDesc type = TypeUnknown) char* data = OIIO_ALLOCA(char, type.size()); if (!OIIO::getattribute(name, type, data)) return py::none(); - if (type.basetype == TypeDesc::INT) - return C_to_val_or_tuple((const int*)data, type); - if (type.basetype == TypeDesc::FLOAT) - return C_to_val_or_tuple((const float*)data, type); - if (type.basetype == TypeDesc::STRING) - return C_to_val_or_tuple((const char**)data, type); - return py::none(); + return make_pyobject(data, type); } diff --git a/src/python/py_oiio.h b/src/python/py_oiio.h index a9428302a0..a9d6254ce5 100644 --- a/src/python/py_oiio.h +++ b/src/python/py_oiio.h @@ -508,6 +508,14 @@ attribute_typed(T& myobj, string_view name, TypeDesc type, const POBJ& dataobj) +// `data` points to values of `type`. Make a python object that represents +// them. +py::object +make_pyobject(const void* data, TypeDesc type, int nvalues = 1, + py::object defaultvalue = py::none()); + + + template py::object getattribute_typed(const T& obj, const std::string& name, @@ -519,29 +527,7 @@ getattribute_typed(const T& obj, const std::string& name, bool ok = obj.getattribute(name, type, data); if (!ok) return py::none(); // None - if (type.basetype == TypeDesc::INT) - return C_to_val_or_tuple((const int*)data, type); - if (type.basetype == TypeDesc::UINT) - return C_to_val_or_tuple((const unsigned int*)data, type); - if (type.basetype == TypeDesc::INT16) - return C_to_val_or_tuple((const short*)data, type); - if (type.basetype == TypeDesc::UINT16) - return C_to_val_or_tuple((const unsigned short*)data, type); - if (type.basetype == TypeDesc::UINT8) - return C_to_val_or_tuple((const unsigned char*)data, type); - if (type.basetype == TypeDesc::FLOAT) - return C_to_val_or_tuple((const float*)data, type); - if (type.basetype == TypeDesc::DOUBLE) - return C_to_val_or_tuple((const double*)data, type); - if (type.basetype == TypeDesc::HALF) - return C_to_val_or_tuple((const half*)data, type); - if (type.basetype == TypeDesc::STRING) - return C_to_val_or_tuple((const char**)data, type); - if (type.basetype == TypeDesc::INT64) - return C_to_val_or_tuple((const int64_t*)data, type); - if (type.basetype == TypeDesc::UINT64) - return C_to_val_or_tuple((const uint64_t*)data, type); - return py::none(); + return make_pyobject(data, type); } @@ -620,40 +606,6 @@ make_numpy_array(TypeDesc format, void* data, int dims, size_t chans, -inline py::object -ParamValue_getitem(const ParamValue& self, bool allitems = false, - py::object defaultvalue = py::none()) -{ - TypeDesc t = self.type(); - int nvals = allitems ? self.nvalues() : 1; - -#define ParamValue_convert_dispatch(TYPE) \ -case TypeDesc::TYPE: \ - return C_to_val_or_tuple((CType::type*)self.data(), t, \ - nvals) - - switch (t.basetype) { - ParamValue_convert_dispatch(UCHAR); - // ParamValue_convert_dispatch(CHAR); - ParamValue_convert_dispatch(USHORT); - ParamValue_convert_dispatch(SHORT); - ParamValue_convert_dispatch(UINT); - ParamValue_convert_dispatch(INT); - // ParamValue_convert_dispatch(ULONGLONG); - // ParamValue_convert_dispatch(LONGLONG); - ParamValue_convert_dispatch(HALF); - ParamValue_convert_dispatch(FLOAT); - ParamValue_convert_dispatch(DOUBLE); - case TypeDesc::STRING: - return C_to_val_or_tuple((const char**)self.data(), t, nvals); - default: return defaultvalue; - } - -#undef ParamValue_convert_dispatch -} - - - template inline void delegate_setitem(C& self, const std::string& key, py::object obj) diff --git a/src/python/py_paramvalue.cpp b/src/python/py_paramvalue.cpp index e8f11a827f..74f62d1b8d 100644 --- a/src/python/py_paramvalue.cpp +++ b/src/python/py_paramvalue.cpp @@ -45,6 +45,28 @@ ParamValue_from_pyobject(string_view name, TypeDesc type, int nvalues, pv.init(name, type, nvalues, interp, &u[0]); return pv; } + } else if (type.basetype == TypeDesc::UINT8 && type.arraylen + && py::isinstance(obj)) { + // Special case: converting a "bytes" object to a byte array + std::string s = obj.cast(); + if (type.arraylen < 0) // convert un-specified length to real length + type.arraylen = int(s.size()) / nvalues; + if (type.arraylen * nvalues == int(s.size())) { + std::vector vals((const uint8_t*)s.data(), + (const uint8_t*)s.data() + s.size()); + pv.init(name, type, nvalues, interp, vals.data()); + return pv; + } + } else if (type.basetype == TypeDesc::UINT8) { + std::vector vals; + py_to_stdvector(vals, obj); + if (vals.size() >= expected_size) { + pv.init(name, type, nvalues, interp, vals.data()); + return pv; + } + } else { + Strutil::print("ParamValue_from_pyobject not sure how to handle {} {}\n", + name, type); } // I think this is what we should do here when not enough data is @@ -143,7 +165,9 @@ declare_paramvalue(py::module& m) #endif .def_property_readonly("value", [](const ParamValue& self) { - return ParamValue_getitem(self, true); + return make_pyobject(self.data(), + self.type(), + self.nvalues()); }) .def_property_readonly("__len__", &ParamValue::nvalues) .def(py::init()) @@ -180,7 +204,7 @@ declare_paramvalue(py::module& m) auto p = self.find(key); if (p == self.end()) throw py::key_error("key '" + key + "' does not exist"); - return ParamValue_getitem(*p); + return make_pyobject(p->data(), p->type()); }, py::return_value_policy::reference_internal) // __setitem__ is the dict-like `pvl[key] = value` assignment diff --git a/testsuite/python-imageinput/ref/out-travis.txt b/testsuite/python-imageinput/ref/out-py27.txt similarity index 66% rename from testsuite/python-imageinput/ref/out-travis.txt rename to testsuite/python-imageinput/ref/out-py27.txt index 16edf46bbd..ff79c2582b 100644 --- a/testsuite/python-imageinput/ref/out-travis.txt +++ b/testsuite/python-imageinput/ref/out-py27.txt @@ -26,7 +26,7 @@ Opened "../oiio-images/tahoe-gps.jpg" as a jpeg Exif:PixelXDimension = 2048 Exif:PixelYDimension = 1536 Exif:WhiteBalance = 0 - GPS:VersionID = (2, 2, 0, 0) + GPS:VersionID = (2L, 2L, 0L, 0L) GPS:LatitudeRef = "N" GPS:Latitude = (39.0, 18.0, 24.399999618530273) GPS:LongitudeRef = "W" @@ -97,41 +97,41 @@ Subimage 0 MIP level 10 : Testing read_image: Opened "../oiio-images/tahoe-gps.jpg" as a jpeg -@ (0L, 0L) = [40 35 57] -@ (2047L, 1535L) = [37 56 89] -@ (1024L, 768L) = [137 183 233] +@ (0, 0) = [40 35 57] +@ (2047, 1535) = [37 56 89] +@ (1024, 768) = [137 183 233] Opened "../oiio-images/tahoe-gps.jpg" as a jpeg -@ (0L, 0L) = [ 0.15686275 0.13725491 0.22352943] -@ (2047L, 1535L) = [ 0.14509805 0.21960786 0.34901962] -@ (1024L, 768L) = [ 0.53725493 0.71764708 0.91372555] +@ (0, 0) = [0.15686275 0.13725491 0.22352943] +@ (2047, 1535) = [0.14509805 0.21960786 0.34901962] +@ (1024, 768) = [0.5372549 0.7176471 0.91372555] Opened "../oiio-images/tahoe-gps.jpg" as a jpeg -@ (0L, 0L) = [40] -@ (2047L, 1535L) = [37] -@ (1024L, 768L) = [137] +@ (0, 0) = [40] +@ (2047, 1535) = [37] +@ (1024, 768) = [137] Testing read_scanline: Opened "../oiio-images/tahoe-gps.jpg" as a jpeg -@ (0L, 0L) = [40 35 57] -@ (0L, 1535L) = [ 82 94 136] +@ (0, 0) = [40 35 57] +@ (0, 1535) = [ 82 94 136] Testing read_tile: Opened "grid.tx" as a tiff -@ (32L, 32L) = [ 1 1 1 255] -@ (32L, 32L) = [255 127 127 255] +@ (32, 32) = [ 1 1 1 255] +@ (32, 32) = [255 127 127 255] Testing read_scanlines: Opened "../oiio-images/tahoe-gps.jpg" as a jpeg -@ (0L, 0L) = [40 35 57] -@ (2047L, 1535L) = [37 56 89] -@ (1024L, 768L) = [137 183 233] +@ (0, 0) = [40 35 57] +@ (2047, 1535) = [37 56 89] +@ (1024, 768) = [137 183 233] Testing read_tiles: Opened "grid.tx" as a tiff -@ (0L, 0L) = [ 0 0 0 255] -@ (1023L, 1023L) = [ 0 0 0 255] -@ (512L, 512L) = [ 0 0 0 255] +@ (0, 0) = [ 0 0 0 255] +@ (1023, 1023) = [ 0 0 0 255] +@ (512, 512) = [ 0 0 0 255] Test read_image native u16: Opened "testu16.tif" as a tiff @@ -154,55 +154,55 @@ Opened "testu16.tif" as a tiff Read array typecode float32 [ 12288 ] Testing write and read of unassociated: - writing: [[[ 0.5 0.5 0.5 0.5] - [ 0.5 0.5 0.5 0.5]] + writing: [[[0.5 0.5 0.5 0.5] + [0.5 0.5 0.5 0.5]] - [[ 0.5 0.5 0.5 0.5] - [ 0.5 0.5 0.5 0.5]]] + [[0.5 0.5 0.5 0.5] + [0.5 0.5 0.5 0.5]]] - default reading as IB: [[[ 0.25 0.25 0.25 0.5 ] - [ 0.25 0.25 0.25 0.5 ]] + default reading as IB: [[[0.25 0.25 0.25 0.5 ] + [0.25 0.25 0.25 0.5 ]] - [[ 0.25 0.25 0.25 0.5 ] - [ 0.25 0.25 0.25 0.5 ]]] + [[0.25 0.25 0.25 0.5 ] + [0.25 0.25 0.25 0.5 ]]] - reading as IB with unassoc hint: [[[ 0.5 0.5 0.5 0.5] - [ 0.5 0.5 0.5 0.5]] + reading as IB with unassoc hint: [[[0.5 0.5 0.5 0.5] + [0.5 0.5 0.5 0.5]] - [[ 0.5 0.5 0.5 0.5] - [ 0.5 0.5 0.5 0.5]]] + [[0.5 0.5 0.5 0.5] + [0.5 0.5 0.5 0.5]]] reading as II with hint, read scanlines backward: - [1] = [[ 0.5 0.5 0.5 0.5] - [ 0.5 0.5 0.5 0.5]] - [0] = [[ 0.5 0.5 0.5 0.5] - [ 0.5 0.5 0.5 0.5]] + [1] = [[0.5 0.5 0.5 0.5] + [0.5 0.5 0.5 0.5]] + [0] = [[0.5 0.5 0.5 0.5] + [0.5 0.5 0.5 0.5]] Testing write and read of TIFF CMYK with auto RGB translation: - writing: [[[ 0.50196081 0. 0. 0.50196081] - [ 0.50196081 0. 0. 0.50196081]] + writing: [[[0.5019608 0. 0. 0.5019608] + [0.5019608 0. 0. 0.5019608]] - [[ 0.50196081 0. 0. 0.50196081] - [ 0.50196081 0. 0. 0.50196081]]] + [[0.5019608 0. 0. 0.5019608] + [0.5019608 0. 0. 0.5019608]]] - default reading as IB: [[[ 0.24705884 0.49803925 0.49803925] - [ 0.24705884 0.49803925 0.49803925]] + default reading as IB: [[[0.24705884 0.49803925 0.49803925] + [0.24705884 0.49803925 0.49803925]] - [[ 0.24705884 0.49803925 0.49803925] - [ 0.24705884 0.49803925 0.49803925]]] + [[0.24705884 0.49803925 0.49803925] + [0.24705884 0.49803925 0.49803925]]] - reading as IB with rawcolor=1: [[[ 0.50196081 0. 0. 0.50196081] - [ 0.50196081 0. 0. 0.50196081]] + reading as IB with rawcolor=1: [[[0.5019608 0. 0. 0.5019608] + [0.5019608 0. 0. 0.5019608]] - [[ 0.50196081 0. 0. 0.50196081] - [ 0.50196081 0. 0. 0.50196081]]] + [[0.5019608 0. 0. 0.5019608] + [0.5019608 0. 0. 0.5019608]]] reading as II with rawcolor=0, read scanlines backward: - [1] = [[ 0.24705884 0.49803925 0.49803925] - [ 0.24705884 0.49803925 0.49803925]] - [0] = [[ 0.24705884 0.49803925 0.49803925] - [ 0.24705884 0.49803925 0.49803925]] + [1] = [[0.24705884 0.49803925 0.49803925] + [0.24705884 0.49803925 0.49803925]] + [0] = [[0.24705884 0.49803925 0.49803925] + [0.24705884 0.49803925 0.49803925]] is_imageio_format_name('tiff') = True diff --git a/testsuite/python-imageinput/ref/out-travis-py2.7-pybind2.3.txt b/testsuite/python-imageinput/ref/out-ubuntu-py2.7-pybind2.3.txt similarity index 99% rename from testsuite/python-imageinput/ref/out-travis-py2.7-pybind2.3.txt rename to testsuite/python-imageinput/ref/out-ubuntu-py2.7-pybind2.3.txt index ad87c5ef67..233389d30f 100644 --- a/testsuite/python-imageinput/ref/out-travis-py2.7-pybind2.3.txt +++ b/testsuite/python-imageinput/ref/out-ubuntu-py2.7-pybind2.3.txt @@ -26,7 +26,7 @@ Opened "../oiio-images/tahoe-gps.jpg" as a jpeg Exif:PixelXDimension = 2048 Exif:PixelYDimension = 1536 Exif:WhiteBalance = 0 - GPS:VersionID = (2, 2, 0, 0) + GPS:VersionID = (2L, 2L, 0L, 0L) GPS:LatitudeRef = "N" GPS:Latitude = (39.0, 18.0, 24.399999618530273) GPS:LongitudeRef = "W" diff --git a/testsuite/python-imagespec/ref/out-python3.txt b/testsuite/python-imagespec/ref/out-python3.txt index 0960c93644..6a07d1650b 100644 --- a/testsuite/python-imagespec/ref/out-python3.txt +++ b/testsuite/python-imagespec/ref/out-python3.txt @@ -88,8 +88,11 @@ getattribute('foo_vector') retrieves (1.0, 0.0, 11.0) getattribute('foo_matrix') retrieves (1.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 2.0, 3.0, 1.0) getattribute('foo_no') retrieves None getattribute('smpte:TimeCode') retrieves (18356486, 4294967295) +getattribute('ucarr') retrieves [49 50 51 0 0 97 98 99 1 88] getattribute('unknown') retrieves None s.get('foo_int') = 14 +s.get('ucarr') retrieves [49 50 51 0 0 97 98 99 1 88] +s['ucarr'] retrieves [49 50 51 0 0 97 98 99 1 88] s.get('unknown') = None s.get('unknown', 123) = None s['delfoo_float'] = 99.5 @@ -99,7 +102,7 @@ s['unknown'] raised a KeyError (as expected) 'foo_int' in s = True 'unknown' in s = False -extra_attribs size is 9 +extra_attribs size is 10 0 foo_str string blah "blah" 1 foo_int int 14 @@ -112,11 +115,13 @@ extra_attribs size is 9 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 1, 2, 3, 1 5 smpte:TimeCode timecode (18356486, 4294967295) 01:18:19:06 -6 delfoo_str string egg +6 ucarr uint8[10] [49 50 51 0 0 97 98 99 1 88] +49, 50, 51, 0, 0, 97, 98, 99, 1, 88 +7 delfoo_str string egg "egg" -7 delfoo_int int 29 +8 delfoo_int int 29 29 -8 delfoo_float float 99.5 +9 delfoo_float float 99.5 99.5 seralize(xml): @@ -154,6 +159,7 @@ seralize(xml): 1, 0, 11 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 1, 2, 3, 1 01:18:19:06 +49, 50, 51, 0, 0, 97, 98, 99, 1, 88 egg 29 99.5 @@ -174,6 +180,7 @@ serialize(text, human): foo_matrix: 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 1, 2, 3, 1 foo_str: "blah" foo_vector: 1, 0, 11 + ucarr: 49, 50, 51, 0, 0, 97, 98, 99, 1, 88 smpte:TimeCode: 01:18:19:06 diff --git a/testsuite/python-imagespec/ref/out.txt b/testsuite/python-imagespec/ref/out.txt index 281158385d..745d86feae 100644 --- a/testsuite/python-imagespec/ref/out.txt +++ b/testsuite/python-imagespec/ref/out.txt @@ -88,8 +88,11 @@ getattribute('foo_vector') retrieves (1.0, 0.0, 11.0) getattribute('foo_matrix') retrieves (1.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 2.0, 3.0, 1.0) getattribute('foo_no') retrieves None getattribute('smpte:TimeCode') retrieves (18356486L, 4294967295L) +getattribute('ucarr') retrieves [49 50 51 0 0 97 98 99 1 88] getattribute('unknown') retrieves None s.get('foo_int') = 14 +s.get('ucarr') retrieves [49 50 51 0 0 97 98 99 1 88] +s['ucarr'] retrieves [49 50 51 0 0 97 98 99 1 88] s.get('unknown') = None s.get('unknown', 123) = None s['delfoo_float'] = 99.5 @@ -99,7 +102,7 @@ s['unknown'] raised a KeyError (as expected) 'foo_int' in s = True 'unknown' in s = False -extra_attribs size is 9 +extra_attribs size is 10 0 foo_str string blah "blah" 1 foo_int int 14 @@ -112,11 +115,13 @@ extra_attribs size is 9 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 1, 2, 3, 1 5 smpte:TimeCode timecode (18356486L, 4294967295L) 01:18:19:06 -6 delfoo_str string egg +6 ucarr uint8[10] [49 50 51 0 0 97 98 99 1 88] +49, 50, 51, 0, 0, 97, 98, 99, 1, 88 +7 delfoo_str string egg "egg" -7 delfoo_int int 29 +8 delfoo_int int 29 29 -8 delfoo_float float 99.5 +9 delfoo_float float 99.5 99.5 seralize(xml): @@ -154,6 +159,7 @@ seralize(xml): 1, 0, 11 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 1, 2, 3, 1 01:18:19:06 +49, 50, 51, 0, 0, 97, 98, 99, 1, 88 egg 29 99.5 @@ -174,6 +180,7 @@ serialize(text, human): foo_matrix: 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 1, 2, 3, 1 foo_str: "blah" foo_vector: 1, 0, 11 + ucarr: 49, 50, 51, 0, 0, 97, 98, 99, 1, 88 smpte:TimeCode: 01:18:19:06 diff --git a/testsuite/python-imagespec/src/test_imagespec.py b/testsuite/python-imagespec/src/test_imagespec.py index 4cbd948925..eb35670a6e 100755 --- a/testsuite/python-imagespec/src/test_imagespec.py +++ b/testsuite/python-imagespec/src/test_imagespec.py @@ -2,6 +2,7 @@ from __future__ import print_function from __future__ import absolute_import +import numpy import OpenImageIO as oiio @@ -91,6 +92,7 @@ def print_imagespec (spec, msg="") : s.attribute ("foo_matrix", oiio.TypeDesc.TypeMatrix, (1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 1, 2, 3, 1)) s.attribute ("smpte:TimeCode", oiio.TypeDesc.TypeTimeCode, (18356486, 4294967295)) + s.attribute ("ucarr", "uint8[10]", numpy.array([49, 50, 51, 0, 0, 97, 98, 99, 1, 88], dtype='B')) s["delfoo_str"] = "egg" s["delfoo_int"] = 29 s["delfoo_float"] = 99.5 @@ -111,8 +113,14 @@ def print_imagespec (spec, msg="") : print ("getattribute('foo_matrix') retrieves", s.getattribute("foo_matrix")) print ("getattribute('foo_no') retrieves", s.getattribute("foo_no")) print ("getattribute('smpte:TimeCode') retrieves", s.getattribute("smpte:TimeCode")) + print ("getattribute('ucarr') retrieves", s.getattribute("ucarr")) print ("getattribute('unknown') retrieves", s.getattribute("unknown")) print ("s.get('foo_int') =", s.get('foo_int')) + print ("s.get('ucarr') retrieves", s.get("ucarr")) + try : + print ("s['ucarr'] retrieves", s['ucarr']) + except KeyError : + print ("s['ucarr'] not found") print ("s.get('unknown') =", s.get('unknown')) print ("s.get('unknown', 123) =", s.get('unknown')) print ("s['delfoo_float'] =", s['delfoo_float']) diff --git a/testsuite/python-paramlist/ref/out.txt b/testsuite/python-paramlist/ref/out.txt index 385882f599..7c361b145b 100644 --- a/testsuite/python-paramlist/ref/out.txt +++ b/testsuite/python-paramlist/ref/out.txt @@ -6,14 +6,17 @@ Testing individual ParamValue: item e float (1.0, 3.0, 5.0, 7.0) item f point (3.5, 4.5, 5.5) item g color (0.25, 0.5, 0.75) + item ucarr uint8[10] [49 50 51 0 0 97 98 99 1 88] + item bts uint8[10] [49 50 51 0 0 97 98 99 1 88] Testing ParamValueList: -pl length is 8 +pl length is 9 item i int 1 item s string Bob item e float 2.71828 item P point (2.0, 42.0, 1.0) item pressure float (98.0, 98.5, 99.0, 99.5) + item ucarr uint8[10] [49 50 51 0 0 97 98 99 1 88] item j int 42 item foo string bar item pi float 3.14159 @@ -23,8 +26,9 @@ pl[1] = s string Bob pl['e'] = 2.71828 pl['pi'] = 3.14159 pl['foo'] = bar +pl['ucarr'] = [49 50 51 0 0 97 98 99 1 88] 'e' in pl = True -after removing 'e', len= 7 pl.contains('e')= False +after removing 'e', len= 8 pl.contains('e')= False after adding 'x', then 'x' in pl = True after removing 'x', then 'x' in pl = False pl['unknown'] raised a KeyError (as expected) @@ -36,6 +40,7 @@ After merge, pl = item s string Bob item P point (2.0, 42.0, 1.0) item pressure float (98.0, 98.5, 99.0, 99.5) + item ucarr uint8[10] [49 50 51 0 0 97 98 99 1 88] item j int 42 item foo string bar item pi float 3.14159 @@ -51,4 +56,5 @@ after sorting: item pi float 3.14159 item pressure float (98.0, 98.5, 99.0, 99.5) item s string Bob + item ucarr uint8[10] [49 50 51 0 0 97 98 99 1 88] Done. diff --git a/testsuite/python-paramlist/src/test_paramlist.py b/testsuite/python-paramlist/src/test_paramlist.py index 5a50f7fa9f..c8e456e969 100755 --- a/testsuite/python-paramlist/src/test_paramlist.py +++ b/testsuite/python-paramlist/src/test_paramlist.py @@ -43,6 +43,12 @@ def print_param_list(pl) : pv = oiio.ParamValue("g", "color", numpy.array([0.25, 0.5, 0.75], dtype='f')) print_param_value(pv) + # Construct from numpy byte array + pv = oiio.ParamValue("ucarr", "uint8[10]", numpy.array([49, 50, 51, 0, 0, 97, 98, 99, 1, 88], dtype='B')) + print_param_value(pv) + # Construct from bytes + pv = oiio.ParamValue("bts", "uint8[10]", b'123\x00\x00abc\x01X') + print_param_value(pv) print ("") @@ -53,6 +59,7 @@ def print_param_list(pl) : pl.attribute ("e", 2.718281828459045) pl.attribute ("P", "point", (2.0, 42.0, 1.0)) pl.attribute ("pressure", "float", 4, [98.0, 98.5, 99.0, 99.5]) + pl.attribute ("ucarr", "uint8[10]", numpy.array([49, 50, 51, 0, 0, 97, 98, 99, 1, 88], dtype='B')) pl["j"] = 42 pl["foo"] = "bar" pl["pi"] = 3.141592653589793 @@ -66,6 +73,7 @@ def print_param_list(pl) : print ("pl['e'] = {:.6}".format(pl['e'])) print ("pl['pi'] = {:.6}".format(pl['pi'])) print ("pl['foo'] =", pl['foo']) + print ("pl['ucarr'] =", pl['ucarr']) print ("'e' in pl =", 'e' in pl) pl.remove('e')