mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-08-26 23:24:45 +03:00
Merge 209a7754c0
into 3d8035bf31
This commit is contained in:
commit
cf99f6fd95
4
Makefile
4
Makefile
|
@ -63,6 +63,10 @@ install-coverage:
|
|||
CFLAGS="-coverage" python setup.py build_ext install
|
||||
python selftest.py --installed
|
||||
|
||||
install-openmp:
|
||||
python setup.py build_ext --enable-openmp install
|
||||
python selftest.py --installed
|
||||
|
||||
debug:
|
||||
# make a debug version if we don't have a -dbg python. Leaves in symbols
|
||||
# for our stuff, kills optimization, and redirects to dev null so we
|
||||
|
|
BIN
Tests/5k_image.jpg
Normal file
BIN
Tests/5k_image.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.4 MiB |
36
Tests/mpbench.py
Normal file
36
Tests/mpbench.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
from PIL import Image
|
||||
import time
|
||||
import math
|
||||
|
||||
def timeit(n, f, *args, **kwargs):
|
||||
def run():
|
||||
start = time.time()
|
||||
f(*args, **kwargs)
|
||||
return time.time() - start
|
||||
|
||||
runs = [run() for _ in range(n)]
|
||||
mean = sum(runs)/float(n)
|
||||
stddev = math.sqrt(sum((r-mean)**2 for r in runs)/float(n))
|
||||
return {'mean':mean,
|
||||
'median': sorted(runs)[int(n/2)],
|
||||
'min': min(runs),
|
||||
'max': max(runs),
|
||||
'stddev':stddev,
|
||||
'dev_pct': stddev/mean*100.0
|
||||
}
|
||||
|
||||
#return min(run() for _ in range(n))
|
||||
|
||||
n = 400
|
||||
image = Image.open('5k_image.jpg').copy()
|
||||
print 'warmup {mean:.4}'.format(**timeit(n // 4, image.im.resize, (2048, 1152), Image.ANTIALIAS))
|
||||
print "%s runs"%n
|
||||
print "Interpolation | Size | min | max | mean | median| stddev | Dev %"
|
||||
print "--------- | --------- | ----- | ----- | ----- | ----- | ----- | ----"
|
||||
print 'Antialias | 2048x1152 | {min:5.3f} | {max:5.3f} | {mean:5.3f} | {median:5.3f} | {stddev:5.4f} | {dev_pct:4.1f}%'.format(**timeit(n, image.im.resize, (2048, 1152), Image.ANTIALIAS))
|
||||
print 'Antialias | 320x240 | {min:5.3f} | {max:5.3f} | {mean:5.3f} | {median:5.3f} | {stddev:5.4f} | {dev_pct:4.1f}%'.format(**timeit(n, image.im.resize, (320, 240), Image.ANTIALIAS))
|
||||
print 'Bicubic | 2048x1152 | {min:5.3f} | {max:5.3f} | {mean:5.3f} | {median:5.3f} | {stddev:5.4f} | {dev_pct:4.1f}%'.format(**timeit(n, image.im.resize, (2048, 1152), Image.BICUBIC))
|
||||
print 'Bicubic | 320x240 | {min:5.3f} | {max:5.3f} | {mean:5.3f} | {median:5.3f} | {stddev:5.4f} | {dev_pct:4.1f}%'.format(**timeit(n, image.im.resize, (320, 240), Image.BICUBIC))
|
||||
print 'Bilinear | 2048x1152 | {min:5.3f} | {max:5.3f} | {mean:5.3f} | {median:5.3f} | {stddev:5.4f} | {dev_pct:4.1f}%'.format(**timeit(n, image.im.resize, (2048, 1152), Image.BILINEAR))
|
||||
print 'Bilinear | 320x240 | {min:5.3f} | {max:5.3f} | {mean:5.3f} | {median:5.3f} | {stddev:5.4f} | {dev_pct:4.1f}%'.format(**timeit(n, image.im.resize, (320, 240), Image.BILINEAR))
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
Rotating in chunks that fit in the cache can speed up rotation
|
||||
8x on a modern CPU. A chunk size of 128 requires only 65k and is large enough
|
||||
that the overhead from the extra loops are not apparent. */
|
||||
|
||||
#define ROTATE_CHUNK 512
|
||||
#define ROTATE_SMALL_CHUNK 8
|
||||
|
||||
|
@ -163,11 +164,13 @@ ImagingTranspose(Imaging imOut, Imaging imIn)
|
|||
|
||||
ImagingSectionEnter(&cookie);
|
||||
|
||||
if (imIn->image8)
|
||||
if (imIn->image8){
|
||||
#pragma omp parallel for private(x,y,xx,yy,xxx,yyy,yysize,xxsize,xxxsize,yyysize) shared(imIn,imOut) default(none) collapse(2)
|
||||
TRANSPOSE(UINT8, image8)
|
||||
else
|
||||
} else {
|
||||
#pragma omp parallel for private(x,y,xx,yy,xxx,yyy,yysize,xxsize,xxxsize,yyysize) shared(imIn,imOut) default(none) collapse(2)
|
||||
TRANSPOSE(INT32, image32)
|
||||
|
||||
}
|
||||
ImagingSectionLeave(&cookie);
|
||||
|
||||
#undef TRANSPOSE
|
||||
|
|
|
@ -241,9 +241,10 @@ ImagingResampleHorizontal_8bpc(Imaging imOut, Imaging imIn, int offset,
|
|||
|
||||
ImagingSectionEnter(&cookie);
|
||||
if (imIn->image8) {
|
||||
#pragma omp parallel for private(k,x,xx,yy,xmin,xmax,ss0,ss1,ss2,ss3) shared(imIn,imOut,kk,ksize,bounds,offset) default(none) collapse(2)
|
||||
for (yy = 0; yy < imOut->ysize; yy++) {
|
||||
for (xx = 0; xx < imOut->xsize; xx++) {
|
||||
xmin = bounds[xx * 2 + 0];
|
||||
xmin = bounds[xx * 2 + 0];
|
||||
xmax = bounds[xx * 2 + 1];
|
||||
k = &kk[xx * ksize];
|
||||
ss0 = 1 << (PRECISION_BITS -1);
|
||||
|
@ -254,7 +255,8 @@ ImagingResampleHorizontal_8bpc(Imaging imOut, Imaging imIn, int offset,
|
|||
}
|
||||
} else if (imIn->type == IMAGING_TYPE_UINT8) {
|
||||
if (imIn->bands == 2) {
|
||||
for (yy = 0; yy < imOut->ysize; yy++) {
|
||||
#pragma omp parallel for private(k,x,xx,yy,xmin,xmax,ss0,ss1,ss2,ss3) shared(imIn,imOut,kk,ksize,bounds,offset) default(none) collapse(2)
|
||||
for (yy = 0; yy < imOut->ysize; yy++) {
|
||||
for (xx = 0; xx < imOut->xsize; xx++) {
|
||||
xmin = bounds[xx * 2 + 0];
|
||||
xmax = bounds[xx * 2 + 1];
|
||||
|
@ -269,7 +271,8 @@ ImagingResampleHorizontal_8bpc(Imaging imOut, Imaging imIn, int offset,
|
|||
}
|
||||
}
|
||||
} else if (imIn->bands == 3) {
|
||||
for (yy = 0; yy < imOut->ysize; yy++) {
|
||||
#pragma omp parallel for private(k,x,xx,yy,xmin,xmax,ss0,ss1,ss2,ss3) shared(imIn,imOut,kk,ksize,bounds,offset) default(none) collapse(2)
|
||||
for (yy = 0; yy < imOut->ysize; yy++) {
|
||||
for (xx = 0; xx < imOut->xsize; xx++) {
|
||||
xmin = bounds[xx * 2 + 0];
|
||||
xmax = bounds[xx * 2 + 1];
|
||||
|
@ -285,6 +288,7 @@ ImagingResampleHorizontal_8bpc(Imaging imOut, Imaging imIn, int offset,
|
|||
}
|
||||
}
|
||||
} else {
|
||||
#pragma omp parallel for private(k,x,xx,yy,xmin,xmax,ss0,ss1,ss2,ss3) shared(imIn,imOut,kk,ksize,bounds,offset) default(none) collapse(2)
|
||||
for (yy = 0; yy < imOut->ysize; yy++) {
|
||||
for (xx = 0; xx < imOut->xsize; xx++) {
|
||||
xmin = bounds[xx * 2 + 0];
|
||||
|
@ -322,7 +326,8 @@ ImagingResampleVertical_8bpc(Imaging imOut, Imaging imIn, int offset,
|
|||
|
||||
ImagingSectionEnter(&cookie);
|
||||
if (imIn->image8) {
|
||||
for (yy = 0; yy < imOut->ysize; yy++) {
|
||||
#pragma omp parallel for private(k,y,xx,yy,ymin,ymax,ss0,ss1,ss2,ss3) shared(imIn,imOut,kk,ksize,bounds) default(none)
|
||||
for (yy = 0; yy < imOut->ysize; yy++) {
|
||||
k = &kk[yy * ksize];
|
||||
ymin = bounds[yy * 2 + 0];
|
||||
ymax = bounds[yy * 2 + 1];
|
||||
|
@ -335,6 +340,7 @@ ImagingResampleVertical_8bpc(Imaging imOut, Imaging imIn, int offset,
|
|||
}
|
||||
} else if (imIn->type == IMAGING_TYPE_UINT8) {
|
||||
if (imIn->bands == 2) {
|
||||
#pragma omp parallel for private(k,y,xx,yy,ymin,ymax,ss0,ss1,ss2,ss3) shared(imIn,imOut,kk,ksize,bounds) default(none)
|
||||
for (yy = 0; yy < imOut->ysize; yy++) {
|
||||
k = &kk[yy * ksize];
|
||||
ymin = bounds[yy * 2 + 0];
|
||||
|
@ -350,6 +356,7 @@ ImagingResampleVertical_8bpc(Imaging imOut, Imaging imIn, int offset,
|
|||
}
|
||||
}
|
||||
} else if (imIn->bands == 3) {
|
||||
#pragma omp parallel for private(k,y,xx,yy,ymin,ymax,ss0,ss1,ss2,ss3) shared(imIn,imOut,kk,ksize,bounds) default(none)
|
||||
for (yy = 0; yy < imOut->ysize; yy++) {
|
||||
k = &kk[yy * ksize];
|
||||
ymin = bounds[yy * 2 + 0];
|
||||
|
@ -366,6 +373,7 @@ ImagingResampleVertical_8bpc(Imaging imOut, Imaging imIn, int offset,
|
|||
}
|
||||
}
|
||||
} else {
|
||||
#pragma omp parallel for private(k,y,xx,yy,ymin,ymax,ss0,ss1,ss2,ss3) shared(imIn,imOut,kk,ksize,bounds) default(none)
|
||||
for (yy = 0; yy < imOut->ysize; yy++) {
|
||||
k = &kk[yy * ksize];
|
||||
ymin = bounds[yy * 2 + 0];
|
||||
|
|
20
setup.py
20
setup.py
|
@ -165,7 +165,7 @@ def _pkg_config(name):
|
|||
class pil_build_ext(build_ext):
|
||||
class feature:
|
||||
features = ['zlib', 'jpeg', 'tiff', 'freetype', 'raqm', 'lcms', 'webp',
|
||||
'webpmux', 'jpeg2000', 'imagequant']
|
||||
'webpmux', 'jpeg2000', 'imagequant', 'openmp']
|
||||
|
||||
required = {'jpeg', 'zlib'}
|
||||
|
||||
|
@ -204,9 +204,6 @@ class pil_build_ext(build_ext):
|
|||
|
||||
def finalize_options(self):
|
||||
build_ext.finalize_options(self)
|
||||
if self.debug:
|
||||
global DEBUG
|
||||
DEBUG = True
|
||||
for x in self.feature:
|
||||
if getattr(self, 'disable_%s' % x):
|
||||
setattr(self.feature, x, False)
|
||||
|
@ -224,7 +221,8 @@ class pil_build_ext(build_ext):
|
|||
|
||||
library_dirs = []
|
||||
include_dirs = []
|
||||
|
||||
extra_compile_args = []
|
||||
|
||||
_add_directory(include_dirs, "libImaging")
|
||||
|
||||
pkg_config = None
|
||||
|
@ -584,6 +582,10 @@ class pil_build_ext(build_ext):
|
|||
_find_library_file(self, "libwebpdemux")):
|
||||
feature.webpmux = "libwebpmux"
|
||||
|
||||
if feature.require('openmp'):
|
||||
extra_compile_args.append('-fopenmp')
|
||||
feature.openmp = 'gomp'
|
||||
|
||||
for f in feature:
|
||||
if not getattr(feature, f) and feature.require(f):
|
||||
if f in ('jpeg', 'zlib'):
|
||||
|
@ -622,6 +624,8 @@ class pil_build_ext(build_ext):
|
|||
libs.extend(["kernel32", "user32", "gdi32"])
|
||||
if struct.unpack("h", "\0\1".encode('ascii'))[0] == 1:
|
||||
defs.append(("WORDS_BIGENDIAN", None))
|
||||
if feature.openmp:
|
||||
libs.append(feature.openmp)
|
||||
|
||||
if sys.platform == "win32" and not (PLATFORM_PYPY or PLATFORM_MINGW):
|
||||
defs.append(("PILLOW_VERSION", '"\\"%s\\""' % PILLOW_VERSION))
|
||||
|
@ -631,7 +635,8 @@ class pil_build_ext(build_ext):
|
|||
exts = [(Extension("PIL._imaging",
|
||||
files,
|
||||
libraries=libs,
|
||||
define_macros=defs))]
|
||||
define_macros=defs,
|
||||
extra_compile_args=extra_compile_args))]
|
||||
|
||||
#
|
||||
# additional libraries
|
||||
|
@ -710,7 +715,8 @@ class pil_build_ext(build_ext):
|
|||
(feature.lcms, "LITTLECMS2"),
|
||||
(feature.webp, "WEBP"),
|
||||
(feature.webpmux, "WEBPMUX"),
|
||||
]
|
||||
(feature.openmp, "OpenMP"),
|
||||
]
|
||||
|
||||
all = 1
|
||||
for option in options:
|
||||
|
|
Loading…
Reference in New Issue
Block a user