A small culmination of my recent efforts to compile a collection of color palettes from trendy sites.
Using the same process as last time, utilizing imagemagick to generate a
histogram of the top colors in an image (scraped from a "design inspiration"
site this time). The one minor change here is using tr
to compress it down to
a CSV file with the filename included for later reference. I had intended to do
this part in Python using Wand but it turns
out to be surprisingly difficult to find good documentation on how to use the
histogram API. I eventually conceded that it would be faster to do it this way.
for i in *.jpg; do
convert $i \
-colorspace LAB \
-colors 4 \
-format %c histogram:info:- \
| gsed 's/.*\(#[0-9A-F]\{6\}\).*/\1/' \
| tr '\n' ',' >> output.csv; echo $i >> output.csv;
done
#888073,#B1B1A5,#C3C3B7,#E7E7E2,1.jpg
#303C37,#6B8CAB,#737A82,#B3BFC9,10.jpg
#000000,#56554F,#848475,#DCDBD7,100.jpg
#523E76,#BCBBBC,#C2C2C2,#CF566A,101.jpg
#302924,#EBB79E,#FBC4A5,#FCF9F4,102.jpg
...
I thought one page per image would be a logical way to present the generated palettes with their corresponding image. It also eases bandwidth requirements so that I don't force everyone to pull down 70MB of photos (unless you browse every page).
Accomplishing this was a pleasant surprise using Python and Jinja2, I pulled in
the CSV module to write a dictionary per line and then pass that into a template
and substitute the four color values into style attributes and the image file
name to an image tag src
.
import csv
import sys
from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader('template'))
template = env.get_template('template.html')
def _parse_palette_csv(csv_input):
with open(csv_input) as f:
header = ['first', 'second', 'third', 'fourth', 'image_filename']
reader = csv.DictReader(f, fieldnames=header)
for palette_dict in reader:
yield palette_dict
def generate_pages(csv_input):
palettes =_parse_palette_csv(csv_input)
for i, palette_dict in enumerate(palettes):
rendered_html = template.render(content=palette_dict)
with open("./rendered/{}.html".format(i), 'wb') as out:
out.write(rendered_html.encode('utf-8'))
if __name__ == '__main__':
generate_pages(sys.argv[1])
Where my template is (omitting some styling here):
<body>
<div>
<div>
<img src="./images/{{content.image_filename}}"></img>
</div>
<div>
<div style="background-color:{{content.first}}"></div>
<div style="background-color:{{content.second}}"></div>
<div style="background-color:{{content.third}}"></div>
<div style="background-color:{{content.fourth}}"></div>
</div>
</div>
<div>random</div>
</body>
Python and Jinja2 fly through it and generate over 500 pages in under 2 seconds. I opted out of designing navigation between pages or an index of them all and instead wrote a tiny bit of JavaScript to pick a page at random:
var random = document.querySelector('.next-a416b');
nextPage = Math.floor(Math.random() * 527) // total pages hard-coded, super good
random.addEventListener("click", function() {
window.location.href = nextPage + '.html';
})
For a final bit of flair I decided to give each page a palette specific background based on the dominant color. A tiny bit more JavaScript and I'm finished:
var body = document.querySelector('body');
function hexToRgb(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
rgb = hexToRgb("{{content.first}}");
body.style.backgroundColor = 'rgba(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ', 0.5)';
I'm converting the hex to rgba
so that I can apply an alpha value of 0.5
so
that the backgrounds aren't over-powering. Sometimes it looks a little odd, but
in general I think it works well enough.
You can check out the result here.