Skip to content

Instantly share code, notes, and snippets.

@werdl
Last active May 17, 2023 13:55
Show Gist options
  • Save werdl/dd7808150a6c4cd74bc5ecc70c886b45 to your computer and use it in GitHub Desktop.
Save werdl/dd7808150a6c4cd74bc5ecc70c886b45 to your computer and use it in GitHub Desktop.
Photofit
dalle_ok=True
try:
import shutil
import openai
import requests
from PIL import Image
except ImportError:
dalle_ok=False
print("Switching to Python Turtle mode")
import turtle
if dalle_ok:
openai.api_key="Withheld"
failed=True
while failed and dalle_ok:
try:
option=int(input("""
0 - Generated by DALL-E
1 - Written in Python turtle
"""))
failed=False
except:
failed=True
option=1
if not option and dalle_ok:
eye=input("Eye color? ").lower()
hair=input("Hair color? ").lower()
mouth=input("Mouth shape? ").lower()
style=input("Hair style? ").lower()
nose=input("Nose style? ").lower()
tache=input("Moustache style? ").lower()
general=input("Style? ").lower()
prompt=f"a face with {eye} eyes. {hair}, {style} hair. a {mouth} mouth shape. a {nose} nose with a {tache} moustache. {general}"
print(prompt)
response = openai.Image.create(
prompt=prompt,
n=1,
size="1024x1024"
)
image_url = response['data'][0]['url']
response2 = requests.get(image_url, stream=True)
with open('img.png', 'wb') as file:
shutil.copyfileobj(response2.raw, file)
del response2
img = Image.open("img.png")
img = img.convert("P")
img.save("img.gif")
win = turtle.Screen()
win.bgpic('img.gif')
turtle.done()
else:
import random
"""
Turtle - drawing
Random - for hair
"""
turtle.setup(500,400)
t=turtle.Turtle()
t.speed(0)
clrs=['snow','ghostwhite','whitesmoke','gainsboro','floralwhite','oldlace','linen','antiquewhite','papayawhip','blanchedalmond','bisque','peachpuff','navajowhite','lemonchiffon','mintcream','azure','aliceblue','lavender','lavenderblush','mistyrose','darkslategray','dimgray','slategray','lightslategray','gray','lightgray','midnightblue','navy','cornflowerblue','darkslateblue','slateblue','mediumslateblue','lightslateblue','mediumblue','royalblue','blue','dodgerblue','deepskyblue','skyblue','lightskyblue','steelblue','lightsteelblue','lightblue','powderblue','paleturquoise','darkturquoise','mediumturquoise','turquoise','cyan','lightcyan','cadetblue','mediumaquamarine','aquamarine','darkgreen','darkolivegreen','darkseagreen','seagreen','mediumseagreen','lightseagreen','palegreen','springgreen','lawngreen','mediumspringgreen','greenyellow','limegreen','yellowgreen','forestgreen','olivedrab','darkkhaki','khaki','palegoldenrod','lightgoldenrodyellow','lightyellow','yellow','gold','lightgoldenrod','goldenrod','darkgoldenrod','rosybrown','indianred','saddlebrown','sandybrown','darksalmon','salmon','lightsalmon','orange','darkorange','coral','lightcoral','tomato','orangered','red','hotpink','deeppink','pink','lightpink','palevioletred','maroon','mediumvioletred','violetred','mediumorchid','darkorchid','darkviolet','blueviolet','purple','mediumpurple','thistle','snow2','snow3','snow4','seashell2','seashell3','seashell4','antiquewhite1','antiquewhite2','antiquewhite3','antiquewhite4','bisque2','bisque3','bisque4','peachpuff2','peachpuff3','peachpuff4','navajowhite2','navajowhite3','navajowhite4','lemonchiffon2','lemonchiffon3','lemonchiffon4','cornsilk2','cornsilk3','cornsilk4','ivory2','ivory3','ivory4','honeydew2','honeydew3','honeydew4','lavenderblush2','lavenderblush3','lavenderblush4','mistyrose2','mistyrose3','mistyrose4','azure2','azure3','azure4','slateblue1','slateblue2','slateblue3','slateblue4','royalblue1','royalblue2','royalblue3','royalblue4','blue2','blue4','dodgerblue2','dodgerblue3','dodgerblue4','steelblue1','steelblue2','steelblue3','steelblue4','deepskyblue2','deepskyblue3','deepskyblue4','skyblue1','skyblue2','skyblue3','skyblue4','lightskyblue1','lightskyblue2','lightskyblue3','lightskyblue4','slategray1','slategray2','slategray3','slategray4','lightsteelblue1','lightsteelblue2','lightsteelblue3','lightsteelblue4','lightblue1','lightblue2','lightblue3','lightblue4','lightcyan2','lightcyan3','lightcyan4','paleturquoise1','paleturquoise2','paleturquoise3','paleturquoise4','cadetblue1','cadetblue2','cadetblue3','cadetblue4','turquoise1','turquoise2','turquoise3','turquoise4','cyan2','cyan3','cyan4','darkslategray1','darkslategray2','darkslategray3','darkslategray4','aquamarine2','aquamarine4','darkseagreen1','darkseagreen2','darkseagreen3','darkseagreen4','seagreen1','seagreen2','seagreen3','palegreen1','palegreen2','palegreen3','palegreen4','springgreen2','springgreen3','springgreen4','green2','green3','green4','chartreuse2','chartreuse3','chartreuse4','olivedrab1','olivedrab2','olivedrab4','darkolivegreen1','darkolivegreen2','darkolivegreen3','darkolivegreen4','khaki1','khaki2','khaki3','khaki4','lightgoldenrod1','lightgoldenrod2','lightgoldenrod3','lightgoldenrod4','lightyellow2','lightyellow3','lightyellow4','yellow2','yellow3','yellow4','gold2','gold3','gold4','goldenrod1','goldenrod2','goldenrod3','goldenrod4','darkgoldenrod1','darkgoldenrod2','darkgoldenrod3','darkgoldenrod4','rosybrown1','rosybrown2','rosybrown3','rosybrown4','indianred1','indianred2','indianred3','indianred4','sienna1','sienna2','sienna3','sienna4','burlywood1','burlywood2','burlywood3','burlywood4','wheat1','wheat2','wheat3','wheat4','tan1','tan2','tan4','chocolate1','chocolate2','chocolate3','firebrick1','firebrick2','firebrick3','firebrick4','brown1','brown2','brown3','brown4','salmon1','salmon2','salmon3','salmon4','lightsalmon2','lightsalmon3','lightsalmon4','orange2','orange3','orange4','darkorange1','darkorange2','darkorange3','darkorange4','coral1','coral2','coral3','coral4','tomato2','tomato3','tomato4','orangered2','orangered3','orangered4','red2','red3','red4','deeppink2','deeppink3','deeppink4','hotpink1','hotpink2','hotpink3','hotpink4','pink1','pink2','pink3','pink4','lightpink1','lightpink2','lightpink3','lightpink4','palevioletred1','palevioletred2','palevioletred3','palevioletred4','maroon1','maroon2','maroon3','maroon4','violetred1','violetred2','violetred3','violetred4','magenta2','magenta3','magenta4','orchid1','orchid2','orchid3','orchid4','plum1','plum2','plum3','plum4','mediumorchid1','mediumorchid2','mediumorchid3','mediumorchid4','darkorchid1','darkorchid2','darkorchid3','darkorchid4','purple1','purple2','purple3','purple4','mediumpurple1','mediumpurple2','mediumpurple3','mediumpurple4','thistle1','thistle2','thistle3','thistle4','grey1','grey2','grey3','grey4','grey5','grey6','grey7','grey8','grey9','grey10','grey11','grey12','grey13','grey14','grey15','grey16','grey17','grey18','grey19','grey20','grey21','grey22','grey23','grey24','grey25','grey26','grey27','grey28','grey29','grey30','grey31','grey32','grey33','grey34','grey35','grey36','grey37','grey38','grey39','grey40','grey42','grey43','grey44','grey45','grey46','grey47','grey48','grey49','grey50','grey51','grey52','grey53','grey54','grey55','grey56','grey57','grey58','grey59','grey60','grey61','grey62','grey63','grey64','grey65','grey66','grey67','grey68','grey69','grey70','grey71','grey72','grey73','grey74','grey75','grey76','grey77','grey78','grey79','grey80','grey81','grey82','grey83','grey84','grey85','grey86','grey87','grey88','grey89','grey90','grey91','grey92','grey93','grey94','grey95','grey97','grey98','grey99']
clrs.append("brown")
t.width(3)
t.goto(0,0)
hair_length=80 # the maximum length of one hair
hair_max_curve=360 # the maximum curve of the hair
hair_density=10 # how many times the for loop iterates
def oval(lr,sr,tilt=90,t=t):
"""Draw an oval of length `lr` and width `sr`. Done by drawing 4 arcs."""
t.seth(-45+tilt)
t.circle(lr,90)
t.circle(sr,90)
t.circle(lr,90)
t.circle(sr,90)
eye1x,eye2x=0,0
def inpwd(prompt,default,list,tkinter,type=str): # INPutWithDefault
"""Takes input with prompt `prompt` (ensuring of type `type`), default value `default`, and checks if it is in `list`"""
try:
temp=input(prompt)
if temp!="" and temp!="\n":
temp=type(temp)
else:
return default
except:
print(f"Wrong type - ensure type is {type}")
inpwd(prompt,default,list,type)
if type==str:
temp=temp.lower()
if tkinter:
orig=t.color()
try:
t.color(temp)
t.color(orig[0])
return temp
except:
print("err ensure valid Tkinter colour")
t.color(orig[0])
return inpwd(prompt,default,list,type)
elif temp not in list and type!=int and type!=float:
print(f"Wrong type - ensure value is in {list[0:4]}...")
return inpwd(prompt,default,list,type)
else:
return temp
def uinput():
global hair_length,hair_density,hair_max_curve,beard_length,beard_density
print("Type your input. Enter for default value, ensure any colours are valid Tkinter colours (lists on the internet) :)")
eye=inpwd("Eye colour? ","lightblue",[],True)
eye_round=inpwd("Eye shape (1 oval or 0 round) ",1,[],False,int)
face=inpwd("Face shape (1 oval or 0 round) ",0,[],False,int)
eye_size=100
while eye_size>=30:
eye_size=inpwd("Eye size in pixels? ",12,[],False,int)
faceclr=inpwd("Face colour? ","papayawhip",clrs,True)
mouth=inpwd("Mouth colour? ","red",clrs,True)
happy=inpwd("Happy 1 or angry 0? ",1,[],False,int)
hair=inpwd("Is the hair long (3), longish (2), shortish (1) or bald (0)? ",2,[0,1,2,3],False,int)
curve=inpwd("Is the hair curly (2), curlyish (1) or not curly (0)? ",1,[0,1,2],False,int)
hairclr=inpwd("Hair colour? ","brown",clrs,True)
brd=inpwd("Beard 1 or not 0? ",1,[],False,int)
brdclr=inpwd("Beard colour? ",hairclr,[],True)
to_ret={
"eye":eye,
"face":face,
"eye_size":eye_size,
"faceclr":faceclr,
"mouth":mouth,
"hair":hair,
"curve":curve,
"hairclr":hairclr,
"happy":happy,
"eye_round":eye_round,
"beard":brd,
"beardclr":brdclr
}
if hair==3:
hair_length=60
hair_density=80
elif hair==2:
hair_length=40
hair_density=30
elif hair==1:
hair_length=30
hair_density=20
elif hair==0:
hair_length=0
hair_density=0
if curve==2:
hair_max_curve=360
elif curve==1:
hair_max_curve=180
elif curve==0:
hair_max_curve=90
if brd:
beard_length=hair_length/2
return to_ret
def outline(roundy):
"""Draw an outline (round if `roundy`)"""
global eye1x
global eye2x
if roundy:
old=t.heading()
t.begin_fill()
oval(100,61)
t.end_fill()
t.color("black")
oval(100,61)
t.seth(old)
eye1x=-10
eye2x=-60
else:
old=t.heading()
t.begin_fill()
oval(100,75)
t.end_fill()
t.color("black")
oval(100,75)
t.seth(old)
eye1x=-20
eye2x=-80
eyes_drawn=0
def eye(bg,roundy):
global eyes_drawn
global eye1x
global eye2x
if eyes_drawn==0:
t.penup()
t.goto(eye1x,100) # goto right position
t.pendown()
else:
t.penup()
t.goto(eye2x,100)
t.pendown()
t.penup()
t.color(bg)
t.begin_fill()
t.pendown()
oval(EYE+2,EYE/1.6) if roundy else t.circle(EYE) # draw oval
t.penup()
t.end_fill()
t.color("black")
t.pendown()
oval(EYE+2,EYE/1.6) if roundy else t.circle(EYE)
t.penup()
t.seth(90) # set heading
t.left(90)
t.forward(1)
t.right(90)
t.forward(EYE/1.9) # forward to about middle
t.begin_fill()
t.circle(2)
t.end_fill()
t.right(90)
t.forward(1)
eyes_drawn+=1
def mouth(up,clr):
"""Draw a mouth (happy if up==0 else sad) with lip colour clr"""
t.width(1.5)
thinsub=0 if not thin else -10
xy=-85-thinsub
t.color("black")
for x in range(4):
t.penup()
t.goto(xy,40 if up else 10)
t.pendown()
t.seth(270 if up else 90)
togo=25 if (x==0 or x==3) else 40
t.forward(togo)
xy+=20
t.penup()
t.goto(-90-thinsub if up else -20-thinsub,40 if up else 10)
t.seth(90 if up else 270)
t.right(180)
t.forward(20)
t.pendown()
t.left(90)
t.forward(70)
t.width(5)
t.color(clr)
t.penup()
t.goto(-95-thinsub if up else -15-thinsub,40 if up else 10)
t.pendown()
t.seth(270 if up else 90)
t.circle(40,180)
t.seth(180 if up else 0)
t.forward(80)
t.color("black")
def hair(clr):
"""Draw hair of colour clr. Everything else is taken from global constants (hair_length, hair_max_curve and hair_density)"""
t.penup()
t.color(clr)
hl3=round(hair_length/3) # HairLength/3
t.goto((-61 if thin else -75)+random.randint((-30 if not thin else -15)-hl3,(60 if not thin else 40)+hl3),random.randint(130,170)) # see comment below
t.pendown()
for x in range(hair_density if ui["hair"]<2 else round(hair_density/2)):
t.goto((-61 if thin else -75)+random.randint((-30 if not thin else -15)-hl3,(60 if not thin else 40)+hl3),random.randint(130,170)) # goto a semi-random location at the top of the head
for x in range(1 if ui["hair"]<2 else 2):
if random.randint(0,1):
t.forward(random.randint(0,hair_length))
else:
t.circle(random.randint(0,round(hair_length/3)),random.randint(0,hair_max_curve))
t.seth(random.randint(0,360))
def beard(clr):
"""Draw beard of colour clr. Everything else is taken from global constants (beard_length, beard_max_curve and beard_density)"""
t.penup()
t.color(clr)
hl3=round(beard_length/3)
t.goto((-61 if thin else -75)+random.randint((-30 if not thin else -15)-hl3,(60 if not thin else 40)+hl3),random.randint(-30,5))
t.pendown()
for x in range(hair_density):
t.goto((-61 if thin else -75)+random.randint((-30 if not thin else -15)-hl3,(60 if not thin else 40)+hl3),random.randint(-30,5)) # goto a semi-random location at the top of the head
for x in range(1 if ui["hair"]<2 else 2):
if random.randint(0,1):
t.forward(random.randint(0,beard_length))
else:
t.circle(random.randint(0,hl3),random.randint(0,hair_max_curve))
t.seth(random.randint(0,360))
t.width(3)
ui=uinput()
t.color(ui["faceclr"])
outline(ui["face"])
thin=ui["face"]
EYE=ui["eye_size"]
for x in range(2):eye(ui["eye"],ui["eye_round"])
t.color(ui["mouth"])
mouth(ui["happy"],ui["mouth"])
hair(ui["hairclr"])
if ui["beard"]:beard(ui["beardclr"])
t.penup()
t.shape("turtle")
t.seth(90)
t.color("green")
t.goto(-43 if thin else -55,60)
t.pendown()
t.stamp()
t.hideturtle()
t.penup()
t.goto(50,50)
t.pendown()
t.right(180)
t.color("black")
t.write("METADATA\n",font=("Consolas",20, "bold"))
t.penup()
t.forward(20)
for key, value in ui.items():
t.write(key,font=("Consolas",10, "bold"),move=True)
t.seth(270)
t.forward(16)
t.write('->'+str(value)+"\n",font=("Consolas",10, "normal"))
t.forward(4)
t.setx(50)
turtle.done()
"""Why all the `x if condition else y`?
To account for the change in head dimensions."""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment