Skip to content

Instantly share code, notes, and snippets.

@jcupitt
Created January 19, 2021 10:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jcupitt/1420f8046f98c1866857711e55cf6d48 to your computer and use it in GitHub Desktop.
Save jcupitt/1420f8046f98c1866857711e55cf6d48 to your computer and use it in GitHub Desktop.
pil - pyvips image resize benchmark
#!/usr/bin/python3
import time
import sys
from io import BytesIO
import pyvips
from PIL import Image # Pillow-SIMD
def figure_size(ih, iw, oh, ow):
if oh / ih >= ow / oh:
return int(iw * (oh / ih)), oh
if oh / ih < ow / oh:
return ow, int(ih * (ow / iw)) # width height
def scale(ih, iw, oh, ow):
if oh / ih >= ow / oh:
return (oh / ih)
if oh / ih < ow / oh:
return (ow / iw) # scale
def bench(last=None, do_print=False, iterations=None, level=0, info=""):
if not last:
return time.clock_gettime(time.CLOCK_THREAD_CPUTIME_ID), time.process_time(), time.perf_counter()
result = (
time.clock_gettime(time.CLOCK_THREAD_CPUTIME_ID) - last[0],
time.process_time() - last[1],
time.perf_counter() - last[2])
if do_print:
print()
print((level * " ") + f"took {time.clock_gettime(time.CLOCK_THREAD_CPUTIME_ID) - last[0]} thread time")
print((level * " ") + f"took {time.process_time() - last[1]:.4f} cpu time")
print((level * " ") + f"took {time.perf_counter() - last[2]:.4f} real time")
if iterations:
print((level * " ") + f"took {(time.perf_counter() - last[2]) / iterations:.4f} per iteration")
if info:
print((level * " ") + info)
return result
def generate_image_pil(image, height, width, quality=75, optimize=False):
if not isinstance(image, Image.Image):
image = Image.open(BytesIO(image))
resize_image = image.resize(figure_size(image.height, image.width, height, width))
jpg_file = BytesIO()
resize_image.save(jpg_file, format="JPEG", quality=quality, optimize=optimize)
return jpg_file, resize_image
def generate_image_vips(image, height, width, quality=75, optimize=False):
if not isinstance(image, pyvips.Image):
image = pyvips.Image.new_from_buffer(image, "")
resize_image = image.resize(scale(image.height, image.width, height, width))
copy_timer = time.perf_counter()
copy = resize_image.copy_memory()
print(f"memory copy took: {time.perf_counter() - copy_timer:.4f}")
jpg_file = resize_image.write_to_buffer('.jpg', Q=quality, optimize_coding=optimize)
return jpg_file, copy
def generate_image_vips_thumbnail(image_bytes, height, width, quality=75, optimize=False):
resize_image = pyvips.Image.thumbnail_buffer(image_bytes, width, height=height)
jpg_bytes = resize_image.write_to_buffer('.jpg', Q=quality, optimize_coding=optimize)
return jpg_bytes
image_file = open(sys.argv[1], 'rb')
image = BytesIO(image_file.read())
outside_run_time = bench()
run_time = bench()
original_jpg, original = generate_image_pil(image.getbuffer(), 3508, 2480, quality=90,
optimize=False) # insert image decision tree
bench(run_time, do_print=True, level=1, info="original conversion with pil")
run_time = bench()
preview_jpg, preview = generate_image_pil(original, 800, 600, quality=80, optimize=False)
bench(run_time, do_print=True, level=1, info="preview conversion with pil")
run_time = bench()
thumbnail_jpg, thumbnail = generate_image_pil(preview, 250, 250, quality=80, optimize=False)
bench(run_time, do_print=True, level=1, info="thumbnail conversion with pil")
bench(outside_run_time, do_print=True, info="total time for pil")
open("original_pil.jpg", "wb").write(original_jpg.getbuffer())
open("preview_pil.jpg", "wb").write(preview_jpg.getbuffer())
open("thumbnail_pil.jpg", "wb").write(thumbnail_jpg.getbuffer())
outside_run_time = bench()
run_time = bench()
original_jpg, original = generate_image_vips(image.getvalue(), 3508, 2480, quality=90, optimize=False)
bench(run_time, do_print=True, level=1, info="original conversion with vips")
run_time = bench()
preview_jpg, preview = generate_image_vips(original, 800, 600, quality=80, optimize=False)
bench(run_time, do_print=True, level=1, info="preview conversion with vips")
run_time = bench()
thumbnail_jpg, thumbnail = generate_image_vips(preview, 250, 250, quality=80, optimize=False)
bench(run_time, do_print=True, level=1, info="thumbnail conversion with vips")
bench(outside_run_time, do_print=True, info="total time for vips")
open("original_vips.jpg", "wb").write(original_jpg)
open("preview_vips.jpg", "wb").write(preview_jpg)
open("thumbnail_vips.jpg", "wb").write(thumbnail_jpg)
image_bytes = image.getvalue()
outside_run_time = bench()
run_time = bench()
original_jpg = generate_image_vips_thumbnail(image_bytes, 3508, 2480, quality=90, optimize=False)
bench(run_time, do_print=True, level=1, info="original conversion with vips thumbnail")
run_time = bench()
preview_jpg = generate_image_vips_thumbnail(image_bytes, 800, 600, quality=80, optimize=False)
bench(run_time, do_print=True, level=1, info="preview conversion with vips thumbnail")
run_time = bench()
thumbnail_jpg = generate_image_vips_thumbnail(image_bytes, 250, 250, quality=80, optimize=False)
bench(run_time, do_print=True, level=1, info="thumbnail conversion with vips thumbnail")
bench(outside_run_time, do_print=True, info="total time for vips thumbnail")
open("original_vips_thumbnail.jpg", "wb").write(original_jpg)
open("preview_vips_thumbnail.jpg", "wb").write(preview_jpg)
open("thumbnail_vips_thumbnail.jpg", "wb").write(thumbnail_jpg)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment