@@ -8,6 +8,51 @@ namespace {
88
99OIIO_NAMESPACE_USING
1010
11+ nb::tuple
12+ imagespec_get_channelformats (const ImageSpec& spec, bool allow_empty = true )
13+ {
14+ std::vector<TypeDesc> formats;
15+ if (spec.channelformats .size () || !allow_empty)
16+ spec.get_channelformats (formats);
17+ return PyOpenImageIO::C_to_tuple (cspan<TypeDesc>(formats));
18+ }
19+
20+
21+ void
22+ imagespec_set_channelformats (ImageSpec& spec, nb::handle py_channelformats)
23+ {
24+ spec.channelformats .clear ();
25+ PyOpenImageIO::py_to_stdvector (spec.channelformats , py_channelformats);
26+ }
27+
28+
29+ nb::tuple
30+ imagespec_get_channelnames (const ImageSpec& spec)
31+ {
32+ return PyOpenImageIO::C_to_tuple (cspan<std::string>(spec.channelnames ));
33+ }
34+
35+
36+ void
37+ imagespec_set_channelnames (ImageSpec& spec, nb::handle py_channelnames)
38+ {
39+ spec.channelnames .clear ();
40+ PyOpenImageIO::py_to_stdvector (spec.channelnames , py_channelnames);
41+ }
42+
43+
44+ nb::object
45+ imagespec_getattribute_typed (const ImageSpec& spec, const std::string& name,
46+ TypeDesc type = TypeUnknown)
47+ {
48+ ParamValue tmpparam;
49+ const ParamValue* p = spec.find_attribute (name, tmpparam, type);
50+ if (!p)
51+ return nb::none ();
52+ return PyOpenImageIO::make_pyobject (p->data (), p->type (), p->nvalues ());
53+ }
54+
55+
1156ROI
1257imagespec_get_roi (const ImageSpec& spec)
1358{
@@ -43,16 +88,7 @@ namespace PyOpenImageIO {
4388void
4489declare_imagespec (nb::module_& m)
4590{
46- // This is intentionally not a full ImageSpec port yet. It only exists
47- // to support ROI parity until py_imagespec.cpp grows into the real
48- // binding.
4991 nb::class_<ImageSpec>(m, " ImageSpec" )
50- .def (nb::init<>())
51- .def (" __init__" ,
52- [](ImageSpec* self, int xres, int yres, int nchans,
53- const TypeDesc& format) {
54- new (self) ImageSpec (xres, yres, nchans, format);
55- })
5692 .def_rw (" x" , &ImageSpec::x)
5793 .def_rw (" y" , &ImageSpec::y)
5894 .def_rw (" z" , &ImageSpec::z)
@@ -65,9 +101,196 @@ declare_imagespec(nb::module_& m)
65101 .def_rw (" full_width" , &ImageSpec::full_width)
66102 .def_rw (" full_height" , &ImageSpec::full_height)
67103 .def_rw (" full_depth" , &ImageSpec::full_depth)
104+ .def_rw (" tile_width" , &ImageSpec::tile_width)
105+ .def_rw (" tile_height" , &ImageSpec::tile_height)
106+ .def_rw (" tile_depth" , &ImageSpec::tile_depth)
68107 .def_rw (" nchannels" , &ImageSpec::nchannels)
69- .def_prop_ro (" roi" , &imagespec_get_roi)
70- .def_prop_ro (" roi_full" , &imagespec_get_roi_full);
108+ .def_rw (" format" , &ImageSpec::format)
109+ .def_prop_rw (
110+ " channelformats" ,
111+ [](const ImageSpec& spec) {
112+ return imagespec_get_channelformats (spec);
113+ },
114+ &imagespec_set_channelformats)
115+ .def_prop_rw (" channelnames" , &imagespec_get_channelnames,
116+ &imagespec_set_channelnames)
117+ .def_rw (" alpha_channel" , &ImageSpec::alpha_channel)
118+ .def_rw (" z_channel" , &ImageSpec::z_channel)
119+ .def_rw (" deep" , &ImageSpec::deep)
120+ .def_prop_ro (" extra_attribs" ,
121+ [](const ImageSpec& spec) { return spec.extra_attribs ; })
122+ .def_prop_rw (" roi" , &imagespec_get_roi, &imagespec_set_roi)
123+ .def_prop_rw (" roi_full" , &imagespec_get_roi_full,
124+ &imagespec_set_roi_full)
125+ .def (nb::init<>())
126+ .def (nb::init<int , int , int , TypeDesc>())
127+ .def (nb::init<const ROI&, TypeDesc>())
128+ .def (nb::init<TypeDesc>())
129+ .def (nb::init<const ImageSpec&>())
130+ .def (" copy" , [](const ImageSpec& self) { return ImageSpec (self); })
131+ .def (" set_format" ,
132+ [](ImageSpec& self, TypeDesc t) { self.set_format (t); })
133+ .def (" default_channel_names" , &ImageSpec::default_channel_names)
134+ .def (" channel_bytes" ,
135+ [](const ImageSpec& spec) { return spec.channel_bytes (); })
136+ .def (
137+ " channel_bytes" ,
138+ [](const ImageSpec& spec, int chan, bool native) {
139+ return spec.channel_bytes (chan, native);
140+ },
141+ " channel" _a, " native" _a = false )
142+ .def (
143+ " pixel_bytes" ,
144+ [](const ImageSpec& spec, bool native) {
145+ return spec.pixel_bytes (native);
146+ },
147+ " native" _a = false )
148+ .def (
149+ " pixel_bytes" ,
150+ [](const ImageSpec& spec, int chbegin, int chend, bool native) {
151+ return spec.pixel_bytes (chbegin, chend, native);
152+ },
153+ " chbegin" _a, " chend" _a, " native" _a = false )
154+ .def (
155+ " scanline_bytes" ,
156+ [](const ImageSpec& spec, bool native) {
157+ return spec.scanline_bytes (native);
158+ },
159+ " native" _a = false )
160+ .def (" scanline_bytes" ,
161+ [](const ImageSpec& spec, TypeDesc type) {
162+ return spec.scanline_bytes (type);
163+ })
164+ .def (
165+ " tile_bytes" ,
166+ [](const ImageSpec& spec, bool native) {
167+ return spec.tile_bytes (native);
168+ },
169+ " native" _a = false )
170+ .def (" tile_bytes" , [](const ImageSpec& spec,
171+ TypeDesc type) { return spec.tile_bytes (type); })
172+ .def (
173+ " image_bytes" ,
174+ [](const ImageSpec& spec, bool native) {
175+ return spec.image_bytes (native);
176+ },
177+ " native" _a = false )
178+ .def (" image_bytes" ,
179+ [](const ImageSpec& spec, TypeDesc type) {
180+ return spec.image_bytes (type);
181+ })
182+ .def (" tile_pixels" , &ImageSpec::tile_pixels)
183+ .def (" image_pixels" , &ImageSpec::image_pixels)
184+ .def (" size_t_safe" , &ImageSpec::size_t_safe)
185+ .def (" channelformat" , [](const ImageSpec& spec,
186+ int chan) { return spec.channelformat (chan); })
187+ .def (" channel_name" ,
188+ [](const ImageSpec& spec, int chan) {
189+ return std::string (spec.channel_name (chan));
190+ })
191+ .def (" channelindex" ,
192+ [](const ImageSpec& spec, const std::string& name) {
193+ return spec.channelindex (name);
194+ })
195+ .def (" get_channelformats" ,
196+ [](const ImageSpec& spec) {
197+ return imagespec_get_channelformats (spec, false );
198+ })
199+ .def (" attribute" ,
200+ [](ImageSpec& spec, const std::string& name, nb::handle obj) {
201+ attribute_onearg (spec, name, obj);
202+ })
203+ .def (" attribute" ,
204+ [](ImageSpec& spec, const std::string& name, TypeDesc type,
205+ nb::handle obj) { attribute_typed (spec, name, type, obj); })
206+ .def (
207+ " get_int_attribute" ,
208+ [](const ImageSpec& spec, const std::string& name, int def) {
209+ return spec.get_int_attribute (name, def);
210+ },
211+ " name" _a, " defaultval" _a = 0 )
212+ .def (
213+ " get_float_attribute" ,
214+ [](const ImageSpec& spec, const std::string& name, float def) {
215+ return spec.get_float_attribute (name, def);
216+ },
217+ " name" _a, " defaultval" _a = 0 .0f )
218+ .def (
219+ " get_string_attribute" ,
220+ [](const ImageSpec& spec, const std::string& name,
221+ const std::string& def) {
222+ return std::string (spec.get_string_attribute (name, def));
223+ },
224+ " name" _a, " defaultval" _a = " " )
225+ .def (" getattribute" , &imagespec_getattribute_typed, " name" _a,
226+ " type" _a = TypeUnknown)
227+ .def (
228+ " get" ,
229+ [](const ImageSpec& self, const std::string& key, nb::handle def) {
230+ ParamValue tmpparam;
231+ auto p = self.find_attribute (key, tmpparam);
232+ if (!p)
233+ return nb::borrow (def);
234+ return make_pyobject (p->data (), p->type (), 1 , def);
235+ },
236+ " key" _a, " default" _a = nb::none ())
237+ .def (
238+ " erase_attribute" ,
239+ [](ImageSpec& spec, const std::string& name, TypeDesc type,
240+ bool casesensitive) {
241+ return spec.erase_attribute (name, type, casesensitive);
242+ },
243+ " name" _a = " " , " type" _a = TypeUnknown, " casesensitive" _a = false )
244+ .def_static (
245+ " metadata_val" ,
246+ [](const ParamValue& p, bool human) {
247+ return std::string (ImageSpec::metadata_val (p, human));
248+ },
249+ " param" _a, " human" _a = false )
250+ .def (
251+ " serialize" ,
252+ [](const ImageSpec& spec, const std::string& format,
253+ const std::string& verbose) {
254+ ImageSpec::SerialFormat fmt = ImageSpec::SerialText;
255+ if (Strutil::iequals (format, " xml" ))
256+ fmt = ImageSpec::SerialXML;
257+ ImageSpec::SerialVerbose verb = ImageSpec::SerialDetailed;
258+ if (Strutil::iequals (verbose, " brief" ))
259+ verb = ImageSpec::SerialBrief;
260+ else if (Strutil::iequals (verbose, " detailed" ))
261+ verb = ImageSpec::SerialDetailed;
262+ else if (Strutil::iequals (verbose, " detailedhuman" ))
263+ verb = ImageSpec::SerialDetailedHuman;
264+ return std::string (spec.serialize (fmt, verb));
265+ },
266+ " format" _a = " text" , " verbose" _a = " detailed" )
267+ .def (
268+ " set_colorspace" ,
269+ [](ImageSpec& self, const std::string& cs) {
270+ self.set_colorspace (cs);
271+ },
272+ " name" _a)
273+ .def (" __getitem__" ,
274+ [](const ImageSpec& self, const std::string& key) {
275+ ParamValue tmpparam;
276+ auto p = self.find_attribute (key, tmpparam);
277+ if (p == nullptr ) {
278+ std::string message = " key '" + key + " ' does not exist" ;
279+ throw nb::key_error (message.c_str ());
280+ }
281+ return make_pyobject (p->data (), p->type ());
282+ })
283+ .def (" __setitem__" ,
284+ [](ImageSpec& self, const std::string& key, nb::handle val) {
285+ delegate_setitem (self, key, val);
286+ })
287+ .def (" __delitem__" ,
288+ [](ImageSpec& self, const std::string& key) {
289+ self.erase_attribute (key);
290+ })
291+ .def (" __contains__" , [](const ImageSpec& self, const std::string& key) {
292+ return self.extra_attribs .contains (key);
293+ });
71294
72295 m.def (" get_roi" , &imagespec_get_roi);
73296 m.def (" get_roi_full" , &imagespec_get_roi_full);
0 commit comments