@@ -23,7 +23,6 @@ ImagingGetBBox(Imaging im, int bbox[4], int alpha_only) {
2323 /* Get the bounding box for any non-zero data in the image.*/
2424
2525 int xsize = im -> xsize , ysize = im -> ysize ;
26- int has_data ;
2726
2827 /* Initialize bounding box to max values */
2928 bbox [0 ] = xsize ;
@@ -33,61 +32,87 @@ ImagingGetBBox(Imaging im, int bbox[4], int alpha_only) {
3332#define GETBBOX (image , mask , type ) \
3433 /* first stage: looking for any pixels from top */ \
3534 for (int y = 0; y < ysize; y++) { \
36- has_data = 0; \
3735 const type *restrict row = (const type *)im->image[y]; \
36+ /* vectorisable OR-reduce of the row */ \
37+ type acc = 0 ; \
38+ for (int x = 0 ; x < xsize ; x ++ ) { \
39+ acc |= row [x ] & mask ; \
40+ } \
41+ if (!acc ) { \
42+ continue ; \
43+ } \
3844 for (int x = 0 ; x < xsize ; x ++ ) { \
3945 if (row [x ] & mask ) { \
40- has_data = 1; \
4146 bbox [0 ] = x ; \
4247 bbox [1 ] = y ; \
4348 break ; \
4449 } \
4550 } \
46- if (has_data) { \
47- break; \
48- } \
51+ break ; \
4952 } \
5053 /* Check that we have a box */ \
5154 if (bbox [1 ] < 0 ) { \
5255 return 0 ; /* no data */ \
5356 } \
5457 /* second stage: looking for any pixels from bottom */ \
5558 for (int y = ysize - 1 ; y >= bbox [1 ]; y -- ) { \
56- has_data = 0 ; \
5759 const type * restrict row = (const type * )im -> image [y ]; \
60+ /* vectorisable OR-reduce of the row */ \
61+ type acc = 0 ; \
62+ for (int x = 0 ; x < xsize ; x ++ ) { \
63+ acc |= row [x ] & mask ; \
64+ } \
65+ if (!acc ) { \
66+ continue ; \
67+ } \
5868 for (int x = 0 ; x < xsize ; x ++ ) { \
5969 if (row [x ] & mask ) { \
60- has_data = 1 ; \
6170 bbox [0 ] = x < bbox [0 ] ? x : bbox [0 ]; \
6271 bbox [3 ] = y + 1 ; \
6372 break ; \
6473 } \
6574 } \
66- if (has_data ) { \
67- break ; \
68- } \
75+ break ; \
6976 } \
7077 /* third stage: looking for left and right boundaries */ \
7178 for (int y = bbox [1 ]; y < bbox [3 ]; y ++ ) { \
7279 const type * restrict row = (const type * )im -> image [y ]; \
73- for (int x = 0 ; x < bbox [0 ]; x ++ ) { \
74- if (row [x ] & mask ) { \
75- bbox [0 ] = x ; \
76- break ; \
80+ if (bbox [0 ] > 0 ) { \
81+ /* vectorisable OR-reduce of the left margin */ \
82+ type acc = 0 ; \
83+ for (int x = 0 ; x < bbox [0 ]; x ++ ) { \
84+ acc |= row [x ] & mask ; \
85+ } \
86+ if (acc ) { \
87+ for (int x = 0 ; x < bbox [0 ]; x ++ ) { \
88+ if (row [x ] & mask ) { \
89+ bbox [0 ] = x ; \
90+ break ; \
91+ } \
92+ } \
7793 } \
7894 } \
79- for (int x = xsize - 1 ; x >= bbox [2 ]; x -- ) { \
80- if (row [x ] & mask ) { \
81- bbox [2 ] = x + 1 ; \
82- break ; \
95+ if (bbox [2 ] < xsize ) { \
96+ /* vectorisable OR-reduce of the right margin */ \
97+ type acc = 0 ; \
98+ for (int x = bbox [2 ]; x < xsize ; x ++ ) { \
99+ acc |= row [x ] & mask ; \
100+ } \
101+ if (acc ) { \
102+ for (int x = xsize - 1 ; x >= bbox [2 ]; x -- ) { \
103+ if (row [x ] & mask ) { \
104+ bbox [2 ] = x + 1 ; \
105+ break ; \
106+ } \
107+ } \
83108 } \
84109 } \
85110 }
86111
87112 if (im -> image8 ) {
88113 if (isModeI16 (im -> mode )) {
89114 // In I16 modes, image8 is two-byte pixels, so scan as UINT16.
90- // Since we're looking for zeroes, endianness testing is independent .
115+ // Since we're looking for zeroes, endianness doesn't matter .
91116 GETBBOX (image8 , 0xffff , UINT16 );
92117 } else {
93118 GETBBOX (image8 , 0xff , UINT8 );
0 commit comments