1111
1212#import < Accelerate/Accelerate.h>
1313
14- #if PY_MAJOR_VERSION < 3
15-
16- #pragma clang diagnostic push
17- #pragma clang diagnostic ignored "-Wmacro-redefined"
18- #define PyBytes_Check (name ) PyString_Check(name)
19- #pragma clang diagnostic pop
20- #define PyAnyInteger_Check (name ) (PyLong_Check(name) || PyInt_Check(name))
21-
22- #else
23-
2414#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
2515#include < numpy/arrayobject.h>
26- #define PyAnyInteger_Check (name ) (PyLong_Check(name) || (_import_array(), PyArray_IsScalar(name, Integer)))
2716
28- #endif
17+ #define PyAnyInteger_Check ( name ) (PyLong_Check(name) || (_import_array(), PyArray_IsScalar(name, Integer)))
2918
3019using namespace CoreML ::Python;
3120
5948
6049 @autoreleasepool {
6150 NSMutableDictionary <NSString *, NSObject *> *inputDict = [[NSMutableDictionary <NSString *, NSObject *> alloc] init ];
62-
51+
6352 for (const auto element : dict) {
6453 std::string key = element.first .cast <std::string>();
6554 NSString *nsKey = [NSString stringWithUTF8String: key.c_str ()];
6655 id nsValue = Utils::convertValueToObjC (element.second );
6756 inputDict[nsKey] = nsValue;
6857 }
69-
58+
7059 feautreProvider = [[MLDictionaryFeatureProvider alloc ] initWithDictionary: inputDict error: &localError];
7160 }
7261
134123}
135124
136125static MLFeatureValue * convertValueToDictionary (const py::handle& handle) {
137-
126+
138127 if (!PyDict_Check (handle.ptr ())) {
139128 throw std::runtime_error (" Not a dictionary." );
140129 }
141-
130+
142131 // Get the first value in the dictionary; use that as a hint.
143132 PyObject *key = nullptr , *value = nullptr ;
144133 Py_ssize_t pos = 0 ;
145-
134+
146135 int has_values = PyDict_Next (handle.ptr (), &pos, &key, &value);
147-
136+
148137 // Is it an empty dict? If so, just return an empty dictionary.
149138 if (!has_values) {
150139 return [MLFeatureValue featureValueWithDictionary: @{} error: nullptr ];
@@ -222,12 +211,12 @@ static void handleCVReturn(CVReturn status) {
222211static MLFeatureValue * convertValueToImage (const py::handle& handle) {
223212 // assumes handle is a valid PIL image!
224213 CVPixelBufferRef pixelBuffer = nil ;
225-
214+
226215 size_t width = handle.attr (" width" ).cast <size_t >();
227216 size_t height = handle.attr (" height" ).cast <size_t >();
228217 OSType format;
229218 std::string formatStr = handle.attr (" mode" ).cast <std::string>();
230-
219+
231220 if (formatStr == " RGB" ) {
232221 format = kCVPixelFormatType_32BGRA ;
233222 } else if (formatStr == " RGBA" ) {
@@ -242,18 +231,18 @@ static void handleCVReturn(CVReturn status) {
242231 msg << " Supported types are: RGB, RGBA, L." ;
243232 throw std::runtime_error (msg.str ());
244233 }
245-
234+
246235 CVReturn status = CVPixelBufferCreate (kCFAllocatorDefault , width, height, format, NULL , &pixelBuffer);
247236 handleCVReturn (status);
248-
237+
249238 // get bytes out of the PIL image
250239 py::object tobytes = handle.attr (" tobytes" );
251240 py::object bytesResult = tobytes ();
252241 assert (PyBytes_Check (bytesResult.ptr ()));
253242 Py_ssize_t bytesLength = PyBytes_Size (bytesResult.ptr ());
254243 assert (bytesLength >= 0 );
255244 const char *bytesPtr = PyBytes_AsString (bytesResult.ptr ());
256-
245+
257246 // copy data into the CVPixelBuffer
258247 status = CVPixelBufferLockBaseAddress (pixelBuffer, 0 );
259248 handleCVReturn (status);
@@ -268,33 +257,33 @@ static void handleCVReturn(CVReturn status) {
268257 srcBuffer.data = const_cast <char *>(srcPointer);
269258 srcBuffer.width = width;
270259 srcBuffer.height = height;
271-
260+
272261 vImage_Buffer dstBuffer;
273262 memset (&dstBuffer, 0 , sizeof (dstBuffer));
274263 dstBuffer.data = baseAddress;
275264 dstBuffer.width = width;
276265 dstBuffer.height = height;
277266
278267 if (formatStr == " RGB" ) {
279-
268+
280269 // convert RGB to BGRA
281270 assert (bytesLength == width * height * 3 );
282271
283272 srcBuffer.rowBytes = width * 3 ;
284273 dstBuffer.rowBytes = bytesPerRow;
285274 vImageConvert_RGB888toBGRA8888 (&srcBuffer, NULL , 255 , &dstBuffer, false , 0 );
286-
275+
287276 } else if (formatStr == " RGBA" ) {
288-
277+
289278 // convert RGBA to BGRA
290279 assert (bytesLength == width * height * 4 );
291280 srcBuffer.rowBytes = width * 4 ;
292281 dstBuffer.rowBytes = bytesPerRow;
293282 uint8_t permuteMap[4 ] = { 2 , 1 , 0 , 3 };
294283 vImagePermuteChannels_ARGB8888 (&srcBuffer, &dstBuffer, permuteMap, 0 );
295-
284+
296285 } else if (formatStr == " L" ) {
297-
286+
298287 // 8 bit grayscale.
299288 assert (bytesLength == width * height);
300289
@@ -303,7 +292,7 @@ static void handleCVReturn(CVReturn status) {
303292 vImageCopyBuffer (&srcBuffer, &dstBuffer, 1 , 0 );
304293
305294 } else if (formatStr == " F" ) {
306-
295+
307296 // convert Float32 to Float16.
308297 assert (bytesLength == width * height * sizeof (Float32));
309298
@@ -317,14 +306,14 @@ static void handleCVReturn(CVReturn status) {
317306 msg << " Supported types are: RGB, RGBA, L." ;
318307 throw std::runtime_error (msg.str ());
319308 }
320-
309+
321310#ifdef COREML_SHOW_PIL_IMAGES
322311 if (formatStr == " RGB" ) {
323312 // for debugging purposes, convert back to PIL image and show it
324313 py::object scope = py::module::import (" __main__" ).attr (" __dict__" );
325314 py::eval<py::eval_single_statement>(" import PIL.Image" , scope);
326315 py::object pilImage = py::eval<py::eval_expr>(" PIL.Image" );
327-
316+
328317 std::string cvPixelStr (count, 0 );
329318 const char *basePtr = static_cast <char *>(baseAddress);
330319 for (size_t row = 0 ; row < height; row++) {
@@ -334,7 +323,7 @@ static void handleCVReturn(CVReturn status) {
334323 }
335324 }
336325 }
337-
326+
338327 py::bytes cvPixelBytes = py::bytes (cvPixelStr);
339328 py::object frombytes = pilImage.attr (" frombytes" );
340329 py::str mode = " RGB" ;
@@ -343,62 +332,62 @@ static void handleCVReturn(CVReturn status) {
343332 img.attr (" show" )();
344333 }
345334#endif
346-
335+
347336 status = CVPixelBufferUnlockBaseAddress (pixelBuffer, 0 );
348337 handleCVReturn (status);
349338
350339 MLFeatureValue *fv = [MLFeatureValue featureValueWithPixelBuffer: pixelBuffer];
351340 CVPixelBufferRelease (pixelBuffer);
352-
341+
353342 return fv;
354343}
355344
356345static bool IsPILImage (const py::handle& handle) {
357346 // TODO put try/catch around this?
358-
347+
359348 try {
360349 py::module::import (" PIL.Image" );
361350 } catch (...) {
362351 return false ;
363352 }
364-
353+
365354 py::object scope = py::module::import (" __main__" ).attr (" __dict__" );
366355 py::eval<py::eval_single_statement>(" import PIL.Image" , scope);
367356 py::handle imageTypeHandle = py::eval<py::eval_expr>(" PIL.Image.Image" , scope);
368357 assert (PyType_Check (imageTypeHandle.ptr ())); // should be a Python type
369-
358+
370359 return PyObject_TypeCheck (handle.ptr (), (PyTypeObject *)(imageTypeHandle.ptr ()));
371360}
372361
373362MLFeatureValue * Utils::convertValueToObjC (const py::handle& handle) {
374-
363+
375364 if (PyAnyInteger_Check (handle.ptr ())) {
376365 try {
377366 int64_t val = handle.cast <int64_t >();
378367 return [MLFeatureValue featureValueWithInt64: val];
379368 } catch (...) {}
380369 }
381-
370+
382371 if (PyFloat_Check (handle.ptr ())) {
383372 try {
384373 double val = handle.cast <double >();
385374 return [MLFeatureValue featureValueWithDouble: val];
386375 } catch (...) {}
387376 }
388-
377+
389378 if (PyBytes_Check (handle.ptr ()) || PyUnicode_Check (handle.ptr ())) {
390379 try {
391380 std::string val = handle.cast <std::string>();
392381 return [MLFeatureValue featureValueWithString: [NSString stringWithUTF8String: val.c_str ()]];
393382 } catch (...) {}
394383 }
395-
384+
396385 if (PyDict_Check (handle.ptr ())) {
397386 try {
398387 return convertValueToDictionary (handle);
399388 } catch (...) {}
400389 }
401-
390+
402391 if (PyList_Check (handle.ptr ()) || PyTuple_Check (handle.ptr ())) {
403392 try {
404393 return convertValueToSequence (handle);
@@ -410,11 +399,11 @@ static bool IsPILImage(const py::handle& handle) {
410399 return convertValueToArray (handle);
411400 } catch (...) {}
412401 }
413-
402+
414403 if (IsPILImage (handle)) {
415404 return convertValueToImage (handle);
416405 }
417-
406+
418407 py::print (" Error: value type not convertible:" );
419408 py::print (handle);
420409 throw std::runtime_error (" value type not convertible" );
@@ -474,6 +463,11 @@ static size_t sizeOfArrayElement(MLMultiArrayDataType type) {
474463 __block py::object array;
475464 [value getBytesWithHandler: ^(const void *bytes, NSInteger size) {
476465 switch (type) {
466+ #if BUILT_WITH_MACOS26_SDK
467+ case MLMultiArrayDataTypeInt8:
468+ array = py::array (shape, strides, reinterpret_cast <const int8_t *>(bytes));
469+ break ;
470+ #endif
477471 case MLMultiArrayDataTypeInt32:
478472 array = py::array (shape, strides, reinterpret_cast <const int32_t *>(bytes));
479473 break ;
@@ -508,7 +502,7 @@ static size_t sizeOfArrayElement(MLMultiArrayDataType type) {
508502 NSString *nskey = static_cast <NSString *>(key);
509503 pykey = py::str ([nskey UTF8String ]);
510504 }
511-
505+
512506 NSNumber *value = dict[key];
513507 ret[pykey] = py::float_ ([value doubleValue ]);
514508 }
@@ -519,7 +513,7 @@ static size_t sizeOfArrayElement(MLMultiArrayDataType type) {
519513 if (CVPixelBufferIsPlanar (value)) {
520514 throw std::runtime_error (" Only non-planar CVPixelBuffers are currently supported by this Python binding." );
521515 }
522-
516+
523517 // supports grayscale and BGRA format types
524518 auto formatType = CVPixelBufferGetPixelFormatType (value);
525519 assert (formatType == kCVPixelFormatType_32BGRA
@@ -553,10 +547,10 @@ static size_t sizeOfArrayElement(MLMultiArrayDataType type) {
553547
554548 auto result = CVPixelBufferLockBaseAddress (value, kCVPixelBufferLock_ReadOnly );
555549 assert (result == kCVReturnSuccess );
556-
550+
557551 uint8_t *src = reinterpret_cast <uint8_t *>(CVPixelBufferGetBaseAddress (value));
558552 assert (src != nullptr );
559-
553+
560554 size_t srcBytesPerRow = CVPixelBufferGetBytesPerRow (value);
561555
562556 // Prepare for vImage blitting
@@ -587,10 +581,10 @@ static size_t sizeOfArrayElement(MLMultiArrayDataType type) {
587581 msg << " Unsupported pixel format type: " << std::hex << std::setfill (' 0' ) << std::setw (4 ) << formatType << " . " ;
588582 throw std::runtime_error (msg.str ());
589583 }
590-
584+
591585 result = CVPixelBufferUnlockBaseAddress (value, kCVPixelBufferLock_ReadOnly );
592586 assert (result == kCVReturnSuccess );
593-
587+
594588 py::object scope = py::module::import (" __main__" ).attr (" __dict__" );
595589 py::eval<py::eval_single_statement>(" import PIL.Image" , scope);
596590 py::object pilImage = py::eval<py::eval_expr>(" PIL.Image" , scope);
0 commit comments