Skip to content

Instantly share code, notes, and snippets.

@jamesu
Last active December 19, 2017 01:27
Show Gist options
  • Save jamesu/24d7077ab9f16ce8fed215718643d2de to your computer and use it in GitHub Desktop.
Save jamesu/24d7077ab9f16ce8fed215718643d2de to your computer and use it in GitHub Desktop.
# Script to generate cryptokitty images using assets from:
# https://github.com/BytesForBites/cryptokitty-designer
# NOTE: requires imagemagick built with --with-librsvg
require 'rubygems'
require 'rmagick'
require 'digest'
class KittyGen
# enums
BodyType = [
'mainecoon',
'cymric',
'laperm',
'munchkin',
'sphynx',
'ragamuffin',
'himalayan',
'chartreux'
]
PatternType = [
'spock',
'tigerpunk',
'calicool',
'luckystripe',
'jaguar',
'totesbasic'
]
MouthType = [
'whixtensions',
'dali',
'saycheese',
'beard',
'tongue',
'happygokitty',
'pouty',
'soserious',
'gerbil'
]
EyeType = [
'wingtips',
'fabulous',
'otaku',
'raisedbrow',
'simple',
'crazy',
'thicccbrowz',
'googly'
]
# colors
Primary = {
:mauveover => '#ded0ee',
:cloudwhite => '#ffffff',
:salmon => '#f4a792',
:shadowgrey => '#b1b1be',
:orangesoda => '#f7bc56',
:aquamarine => '#add5d2',
:greymatter => '#d1dadf',
:oldlace => '#ffebe9',
:cottoncandy => '#ecd1eb'
}
Secondary = {
:peach => '#f9cfad',
:bloodred => '#ff7a7a',
:emeraldgreen => '#8be179',
:granitegrey => '#b1aeb9',
:kittencream => '#f7ebda',
}
Tertiary = {
:barkbrown => '#886662',
:cerulian => '#385877',
:scarlet => '#ea5f5a',
:skyblue => '#83d5ff',
:coffee => '#756650',
:royalpurple => '#cf5be8',
:lemonade => '#ffef85',
:swampgreen => '#44e192',
:chocolate => '#c47e33',
:royalblue => '#5b6ee8',
:wolfgrey => '#737184'
}
EyeColor = {
:gold => '#fcdf35',
:bubblegum => '#ef52d1',
:limegreen => '#aef72f',
:chestnut => '#a56429',
:topaz => '#0ba09c',
:mintgreen => '#43edac',
:strawberry => '#ef4b62',
:sizzurp => '#7c40ff',
}
#
def initialize
load_genes
end
# loads source images which act as parts of the kitty
def load_genes
gene_list = {}
for b in BodyType
for p in PatternType
gene_list["#{b}-#{p}"] = File.open("src/cattributes/body/#{b}-#{p}.svg").read
end
end
for et in EyeType
gene_list["#{et}"] = File.open("src/cattributes/eye/#{et}.svg").read
end
for mt in MouthType
gene_list["#{mt}"] = File.open("src/cattributes/mouth/#{mt}.svg").read
end
#puts "LOADED GENES: #{gene_list.keys.inspect}"
@genes = gene_list
end
def get_gene(name)
@genes[name]
end
def detect_kitty_color(svg_text)
colors = [nil, nil, nil, nil]
return colors
Primary.each do |color, value|
if !svg_text.index(value).nil?
colors[0] = color
end
end
Secondary.each do |color, value|
if !svg_text.index(value).nil?
colors[1] = color
end
end
Tertiary.each do |color, value|
if !svg_text.index(value).nil?
colors[2] = color
end
end
EyeColor.each do |color, value|
if !svg_text.index(value).nil?
colors[3] = color
end
end
return colors
end
# Builds the cat image from a binary data string
def build_cat(kitty_data)
body, pattern, eyes, mouth, pri_color, secondary_color, tertiary_color, eye_color = kitty_data.unpack("LLLLLLLL")
# map numbers to actual values
body_name = BodyType[body % BodyType.length]
mouth_name = MouthType[mouth % MouthType.length]
eyes_name = EyeType[eyes % EyeType.length]
pattern_name = PatternType[pattern % PatternType.length]
colors = [
Primary.values[pri_color % Primary.length],
Secondary.values[secondary_color % Secondary.length],
Tertiary.values[tertiary_color % Tertiary.length],
EyeColor.values[eye_color % EyeColor.length],
]
# we have 3 images to load
kitty_image = get_gene("#{body_name}-#{pattern_name}")
kitty_mouth = get_gene(mouth_name)
kitty_eye = get_gene(eyes_name)
# detect the correct colors
body_colors = detect_kitty_color(kitty_image)
eye_colors = detect_kitty_color(kitty_eye)
mouth_colors = detect_kitty_color(kitty_mouth)
# replace colors in the images we have loaded
if !body_colors[0].nil?
kitty_image = kitty_image.gsub(Primary[body_colors[0]], colors[0])
end
if !body_colors[1].nil?
kitty_image = kitty_image.gsub(Secondary[body_colors[1]], colors[1])
end
if !eye_colors[3].nil?
kitty_eye = kitty_eye.gsub(EyeColor[eye_colors[3]], colors[3])
end
if !body_colors[2].nil?
kitty_image = kitty_image.gsub(Tertiary[body_colors[2]], colors[2])
end
if !mouth_colors[0].nil?
kitty_mouth = kitty_mouth.gsub(Primary[mouth_colors[0]], colors[0])
end
# create background
cat = Magick::Image.new(500, 500) { self.background_color = 'white' }
cat.format = 'PNG'
# composite all the selected image data to cat
dr = Magick::Draw.new
[kitty_image, kitty_mouth, kitty_eye].each do |part_svg|
img = Magick::Image.from_blob(part_svg){self.background_color = "none"}[0]
dr.composite(0, 0, 500, 500, img, Magick::SrcOverCompositeOp)
dr.draw(cat)
end
return cat
end
# Generates a random cat from a seed value
def rand_cat(seed=nil)
srand(seed) if !seed.nil?
data = [rand(BodyType.length),
rand(PatternType.length),
rand(EyeType.length),
rand(MouthType.length),
rand(Primary.length),
rand(Secondary.length),
rand(Tertiary.length),
rand(EyeColor.length)].pack("LLLLLLLL")
write_cat(data)
end
# writes a cat based on an input binary string
def write_cat(data)
data_hex = data.unpack("H*")[0]
puts "Generating cat#{data_hex}.png ..."
cat = build_cat(data)
File.open("cat#{data_hex}.png", 'w') do |f|
f.write cat.to_blob
end
end
end
# debug
#KittyGen.new.rand_cat(10)
#KittyGen.new.rand_cat(20)
#KittyGen.new.rand_cat(30)
#KittyGen.new.rand_cat(40)
# generate image from random seed input
KittyGen.new.rand_cat(ARGV[0].to_i)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment