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