Last active
May 17, 2023 13:55
-
-
Save werdl/dd7808150a6c4cd74bc5ecc70c886b45 to your computer and use it in GitHub Desktop.
Photofit
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
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