Skip to content

Instantly share code, notes, and snippets.

@fredgido
Created January 19, 2021 02:36
Show Gist options
  • Select an option

  • Save fredgido/c09a4ed2456a14e8e1b4afba10589e75 to your computer and use it in GitHub Desktop.

Select an option

Save fredgido/c09a4ed2456a14e8e1b4afba10589e75 to your computer and use it in GitHub Desktop.
import time
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
image_file = open('example.jpg', 'rb') # https://files.catbox.moe/fxseh8.jpg
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()
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)

Intel i5-8265U (8) @ 3.900GHz

1 core: taskset --cpu-list 2 python3 main.py

PIL 1.7433s vs VIPS 1.9279s

  took 1.61188423 thread time
  took 1.6119 cpu time
  took 1.6123 real time
  original conversion with pil

  took 0.12020072299999995 thread time
  took 0.1202 cpu time
  took 0.1202 real time
  preview conversion with pil

  took 0.010778790000000038 thread time
  took 0.0108 cpu time
  took 0.0108 real time
  thumbnail conversion with pil

took 1.742943179 thread time
took 1.7429 cpu time
took 1.7433 real time
total time for pil
memory copy took: 0.8323

  took 0.039099991000000056 thread time
  took 1.4985 cpu time
  took 1.4987 real time
  original conversion with vips
memory copy took: 0.2072

  took 0.004223732000000036 thread time
  took 0.4199 cpu time
  took 0.4200 real time
  preview conversion with vips
memory copy took: 0.0077

  took 0.0037640109999999005 thread time
  took 0.0212 cpu time
  took 0.0214 real time
  thumbnail conversion with vips

took 0.03485805900000005 thread time
took 1.9273 cpu time
took 1.9279 real time
total time for vips

4 core, 8 threads: python3 main.py

PIL 1.8050s vs VIPS 1.1655s

  took 1.6735827410000002 thread time
  took 1.6736 cpu time
  took 1.6739 real time
  original conversion with pil

  took 0.12001449900000005 thread time
  took 0.1200 cpu time
  took 0.1200 real time
  preview conversion with pil

  took 0.01103045399999969 thread time
  took 0.0110 cpu time
  took 0.0110 real time
  thumbnail conversion with pil

took 1.804712722 thread time
took 1.8047 cpu time
took 1.8050 real time
total time for pil
memory copy took: 0.8016

  took 0.04441914099999966 thread time
  took 2.7282 cpu time
  took 1.0434 real time
  original conversion with vips
memory copy took: 0.0612

  took 0.0063794600000002255 thread time
  took 0.8171 cpu time
  took 0.1238 real time
  preview conversion with vips
memory copy took: 0.0029

  took 0.004536407999999881 thread time
  took 0.0305 cpu time
  took 0.0093 real time
  thumbnail conversion with vips

took 0.044359417000000345 thread time
took 3.5648 cpu time
took 1.1655 real time
total time for vips
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment