@@ -278,6 +278,7 @@ ImagingNewPrologueSubtype(const char *mode, int xsize, int ysize, int size) {
278278 break ;
279279 }
280280
281+ // UNDONE -- not accurate for arrow
281282 MUTEX_LOCK (& ImagingDefaultArena .mutex );
282283 ImagingDefaultArena .stats_new_count += 1 ;
283284 MUTEX_UNLOCK (& ImagingDefaultArena .mutex );
@@ -556,6 +557,62 @@ ImagingAllocateBlock(Imaging im) {
556557 return im ;
557558}
558559
560+ /* Borrowed Arrow Storage Type */
561+ /* --------------------------- */
562+ /* Don't allocate the image. */
563+
564+
565+ static void
566+ ImagingDestroyArrow (Imaging im ) {
567+ if (im -> arrow_array_capsule && im -> arrow_array_capsule -> release ) {
568+ im -> arrow_array_capsule -> release (im -> arrow_array_capsule );
569+ im -> arrow_array_capsule -> release = NULL ;
570+ im -> arrow_array_capsule = NULL ;
571+ }
572+ }
573+
574+ Imaging
575+ ImagingAllocateArrow (Imaging im , struct ArrowArray * external_array ) {
576+ /* don't really allocate, but naming patterns */
577+ Py_ssize_t y , i ;
578+
579+ char * borrowed_buffer = NULL ;
580+ struct ArrowArray * arr = external_array ;
581+
582+ /* overflow check for malloc */
583+ if (im -> linesize && im -> ysize > INT_MAX / im -> linesize ) {
584+ return (Imaging )ImagingError_MemoryError ();
585+ }
586+
587+ if (arr -> n_children == 1 ) {
588+ arr = arr -> children [0 ];
589+ }
590+ if (arr -> n_buffers == 2 ) {
591+ // undone offset. offset here is # of elements,
592+ // so depends on the size of the element
593+ // undone image is char*, arrow is void *
594+ // buffer 0 is the null list
595+ // buffer 1 is the data
596+ borrowed_buffer = (char * )arr -> buffers [1 ];
597+ }
598+
599+ if (! borrowed_buffer ) {
600+ // UNDONE better error here.
601+ // currently, only wanting one where
602+ return (Imaging )ImagingError_MemoryError ();
603+ }
604+
605+ for (y = i = 0 ; y < im -> ysize ; y ++ ) {
606+ im -> image [y ] = borrowed_buffer + i ;
607+ i += im -> linesize ;
608+ }
609+ im -> read_only = 1 ;
610+ im -> arrow_array_capsule = external_array ;
611+ im -> destroy = ImagingDestroyArrow ;
612+
613+ return im ;
614+ }
615+
559616/* --------------------------------------------------------------------
560617 * Create a new, internally allocated, image.
561618 */
@@ -627,6 +684,53 @@ ImagingNewBlock(const char *mode, int xsize, int ysize) {
627684 return NULL ;
628685}
629686
687+ Imaging
688+ ImagingNewArrow (const char * mode , int xsize , int ysize ,
689+ struct ArrowSchema * schema ,
690+ struct ArrowArray * external_array ) {
691+ /* A borrowed arrow array */
692+ Imaging im ;
693+
694+ if (xsize < 0 || ysize < 0 ) {
695+ return (Imaging )ImagingError_ValueError ("bad image size" );
696+ }
697+
698+ im = ImagingNewPrologue (mode , xsize , ysize );
699+ if (!im ) {
700+ return NULL ;
701+ }
702+
703+ int64_t pixels = (int64_t )xsize * (int64_t )ysize ;
704+
705+ if (((strcmp (schema -> format , "i" ) == 0 &&
706+ im -> pixelsize == 4 ) ||
707+ (strcmp (schema -> format , im -> arrow_band_format ) == 0 &&
708+ im -> bands == 1 ))
709+ && pixels == external_array -> length ) {
710+ // one arrow element per, and it matches a pixelsize*char
711+ if (ImagingAllocateArrow (im , external_array )) {
712+ return im ;
713+ }
714+ }
715+ if (strcmp (schema -> format , "+w:4" ) == 0
716+ && im -> pixelsize == 4
717+ && schema -> n_children > 0
718+ && schema -> children
719+ && strcmp (schema -> children [0 ]-> format , "C" ) == 0
720+ && pixels == external_array -> length
721+ && external_array -> n_children == 1
722+ && external_array -> children
723+ && 4 * pixels == external_array -> children [0 ]-> length ) {
724+ // 4 up element of char into pixelsize == 4
725+ if (ImagingAllocateArrow (im , external_array )) {
726+ return im ;
727+ }
728+ }
729+
730+ ImagingDelete (im );
731+ return NULL ;
732+ }
733+
630734Imaging
631735ImagingNew2Dirty (const char * mode , Imaging imOut , Imaging imIn ) {
632736 /* allocate or validate output image */
0 commit comments