Last active
March 10, 2024 00:05
-
-
Save todbot/c47e7f1c92caee1c9c1569bc4d08ca52 to your computer and use it in GitHub Desktop.
Compute average color of a JPEG image in CircuitPython
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Compute the average (median or mean) color of a JPEG using ulab.numpy | |
# 9 Mar 2024 - @todbot / Tod Kurt | |
# Note: test images are included as comment below, max tested resolution 256x192 | |
import ulab.numpy as np | |
import displayio | |
import jpegio | |
def rgb565_to_rgb888(v, swapped=True): | |
"""Convert RGB565 (normal or swapped) to RGB888 tuple""" | |
if swapped: | |
v = ((v & 0xff) << 8) | ((v >> 8) & 0xff) | |
r8 = (v >> 11) << 3 | |
g8 = ((v >> 5) << 2) & 0xff | |
b8 = (v << 3) & 0xff | |
return r8, g8, b8 | |
def bitmap565_to_nparray888(bitmap): | |
"""Turn a Bitmap in RGB565_SWAPPED colorspace to RGB888 ndarray""" | |
w,h = bitmap.width, bitmap.height | |
a = np.array(np.zeros((w*h,3)), dtype=np.int16) | |
for y in range(h): | |
for x in range(w): | |
a[y*w+x] = rgb565_to_rgb888(bitmap[x,y]) | |
return a | |
def average_color_for_jpeg(jpeg_fname): | |
"""For a given JPG file, determine most common color | |
Returns both median (most common) and average as two RGB tuples""" | |
decoder = jpegio.JpegDecoder() | |
width, height = decoder.open(jpeg_fname) | |
bitmap = displayio.Bitmap(width, height, 65535) # RGB565_SWAPPED is 16-bit | |
decoder.decode(bitmap) | |
ndbitmap = bitmap565_to_nparray888(bitmap) | |
med = np.median(ndbitmap, axis=0) | |
avg = np.mean(ndbitmap, axis=0) | |
rgb_median = int(med[0]),int(med[1]),int(med[2]) | |
rgb_mean = int(avg[0]),int(avg[1]),int(avg[2]) | |
return (rgb_median, rgb_mean) | |
jpeg_fnames = ( | |
"/imgs/test1.jpg", | |
"/imgs/Mixed-forest-256.jpg", | |
"imgs/Adirondacks_in_May_2008-256.jpg", | |
) | |
for jpeg_fname in jpeg_fnames: | |
print("jpeg file:", jpeg_fname) | |
rgb_median, rgb_avg = average_color_for_jpeg(jpeg_fname) | |
print("median color: %02X%02X%02X" % rgb_median) | |
print("average color: %02X%02X%02X" % rgb_avg) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The test images used: