i'm working on a big rgb matrix project using the espn API to get data for tracking various sports teams. since it's an rgb matrix it makes sense to display the team logos. however, there are a lot of teams across all of the leagues and images for rgb matrices have to be just so. this part of the project was really intimidating.
however, as luck would have it, the espn API includes links to excellent .PNG image files for each team. i wrote a python script that creates folders on your computer for each set of images, downloads the images, names them to match the team abbreviation in the API, resizes them, adds gamma correction from the image correction for led matrices guide, spits out a properly formatted bitmap file and deletes the original .PNG image
import wget
from PIL import Image
import os
import json
import ssl
import requests
import math
ssl._create_default_https_context = ssl._create_unverified_context
home_directory = r"YOUR-DIRECTORY-HERE"
mlb_folder_name = "mlb_logos"
mlb_folder = os.path.join(home_directory, mlb_folder_name)
os.makedirs(mlb_folder)
nfl_folder_name = "nfl_logos"
nfl_folder = os.path.join(home_directory, nfl_folder_name)
os.makedirs(nfl_folder)
nhl_folder_name = "nhl_logos"
nhl_folder = os.path.join(home_directory, nhl_folder_name)
os.makedirs(nhl_folder)
nba_folder_name = "nba_logos"
nba_folder = os.path.join(home_directory, nba_folder_name)
os.makedirs(nba_folder)
mls_folder_name = "mls_logos"
mls_folder = os.path.join(home_directory, mls_folder_name)
os.makedirs(mls_folder)
size = (32, 32)
mlb_data = ("https://site.api.espn.com/apis/site/v2/sports/baseball/mlb/teams")
nfl_data = ("https://site.api.espn.com/apis/site/v2/sports/football/nfl/teams")
nhl_data = ("https://site.api.espn.com/apis/site/v2/sports/hockey/nhl/teams")
nba_data = ("https://site.api.espn.com/apis/site/v2/sports/basketball/nba/teams")
mls_data = ("https://site.api.espn.com/apis/site/v2/sports/soccer/usa.1/teams")
GAMMA = 2.6
def process(img, output_8_bit=False, passthrough=None):
"""Given a color image filename, load image and apply gamma correction
and error-diffusion dithering while quantizing to 565 color
resolution. If output_8_bit is True, image is reduced to 8-bit
paletted mode after quantization/dithering. If passthrough (a list
of 3-tuple RGB values) is provided, dithering won't be applied to
colors in the provided list, they'll be quantized only (allows areas
of the image to remain clean and dither-free). Writes a BMP file
with the same name plus '-processed' and .BMP extension.
"""
err_next_pixel = (0, 0, 0) # Error diffused to the right
err_next_row = [(0, 0, 0) for _ in range(img.size[0])] # " diffused down
for row in range(img.size[1]):
for column in range(img.size[0]):
pixel = img.getpixel((column, row))
want = (math.pow(pixel[0] / 255.0, GAMMA) * 31.0, # Gamma and
math.pow(pixel[1] / 255.0, GAMMA) * 63.0, # quantize
math.pow(pixel[2] / 255.0, GAMMA) * 31.0) # to 565 res
if pixel in passthrough: # In passthrough list?
got = (pixel[0] >> 3, # Take color literally,
pixel[1] >> 2, # though quantized
pixel[2] >> 3)
else:
got = (min(max(int(err_next_pixel[0] * 0.5 + # Diffuse
err_next_row[column][0] * 0.25 + # from
want[0] + 0.5), 0), 31), # prior XY
min(max(int(err_next_pixel[1] * 0.5 +
err_next_row[column][1] * 0.25 +
want[1] + 0.5), 0), 63),
min(max(int(err_next_pixel[2] * 0.5 +
err_next_row[column][2] * 0.25 +
want[2] + 0.5), 0), 31))
err_next_pixel = (want[0] - got[0],
want[1] - got[1],
want[2] - got[2])
err_next_row[column] = err_next_pixel
rgb565 = ((got[0] << 3) | (got[0] >> 2), # Quantized result
(got[1] << 2) | (got[1] >> 4), # after dither
(got[2] << 3) | (got[2] >> 2))
img.putpixel((column, row), rgb565) # Put pixel back in image
if output_8_bit:
img = img.convert('P', palette=Image.ADAPTIVE)
# This is a set of color values where error diffusion dithering won't be
# applied (is still calculated for subsequent pixels, but not applied).
# Here it's set up for primary colors, so these always appear unfettered
# in output images.
PASSTHROUGH = ((0, 0, 0),
(255, 0, 0),
(255, 255, 0),
(0, 255, 0),
(0, 255, 255),
(0, 0, 255),
(255, 0, 255),
(255, 255, 255))
def logo_to_bitmap(data, folder, logo_num):
response = requests.get(data)
the_json = response.json()
for i in range(len(the_json['sports'][0]['leagues'][0]['teams'])):
url = the_json['sports'][0]['leagues'][0]['teams'][i]['team']['logos'][logo_num]['href']
filename = str(the_json['sports'][0]['leagues'][0]['teams'][i]['team']['abbreviation']) + ".png"
file = os.path.join(folder, filename)
converted_filename = str(the_json['sports'][0]['leagues'][0]['teams'][i]['team']['abbreviation']) + ".bmp"
converted_file = os.path.join(folder, converted_filename)
print(url)
testfile = wget.download(url, file)
img = Image.open(file)
img.thumbnail(size)
img1 = img.convert("RGB")
process(img1, True, PASSTHROUGH)
img1.save(converted_file)
os.remove(file)
logo_to_bitmap(mlb_data, mlb_folder, 0)
logo_to_bitmap(nfl_data, nfl_folder, 0)
logo_to_bitmap(nhl_data, nhl_folder, 0)
logo_to_bitmap(nba_data, nba_folder, 0)
logo_to_bitmap(mls_data, mls_folder, 1)
This page (prepping images for an iot rgb matrix project) was last updated on March 08, 2024.