To finish off the thread for posterity: Robert Bradshaw wrote: <Robert's Cython code clipped.> Robert's version operated on a 2-d array, so only one band at a time if you have RGB. So I edited it a bit: import cython import numpy as np cimport numpy as np @cython.boundscheck(False) def halfsize(np.ndarray[np.uint8_t, ndim=3, mode="c"] a): cdef unsigned int i, j, b, w, h, d w, h, d = a.shape[0], a.shape[1], a.shape[2] cdef np.ndarray[np.uint8_t, ndim=3, mode="c"] a2 = np.ndarray((w/2, h/2, 3), np.uint8) for i in range(w/2): for j in range(h/2): for b in range(d): # color band a2[i,j,b] = (<int>a[2*i,2*j,b] + a[2*i+1,2*j,b] + a[2*i,2*j+1,b] + a[2*i+1,2*j+1,b])/4 return a2 This now does the whole RGB image at once, and is pretty snappy. Here are my timings for half-sizing a 512x512 RGB image: slicing, accumulating with a float32 time: 89 ms per loop slicing, accumulating with a uint16 time: 67 ms per loop slicing, all calculations in uint8 time: 47 ms per loop using ndimage, one band at a time, 3rd order spline. time: 280 ms per loop using ndimage, one band at a time, 1st order spline. time: 40 ms per loop using cython, one band at a time time: 11.6 ms per loop using cython, all bands at once time: 2.66 ms per loop using PIL BILNEAR interpolation time: 2.66 ms per loop So a ten times speed up over PIL, and a 17 times speed up over my fastest numpy version. If anyone has any suggestions on how to improve on the Cython version, I'd like to hear it, though I doubt it would make a practical difference. -Chris -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker@noaa.gov