-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathapp.py
205 lines (166 loc) · 7.98 KB
/
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
from flask import Flask, render_template, request, send_file
from PIL import Image, ImageDraw, ImageFont # From pillow
import simplejson as json
from image_utils import ImageText # Fork from https://gist.github.com/pojda/8bf989a0556845aaf4662cd34f21d269
from copy import deepcopy
import datetime
from glob import glob
import io
import os
import sys
app = Flask(__name__, static_url_path='/static/')
# Below was an effort to try to get this working on WSGI
# rootpath = os.path.realpath(os.path.dirname(__file__))
# print(rootpath)
# with open(os.path.join(rootpath, "euchreconfig.json"), "r") as infile:
with open("euchreconfig.json", "r") as infile:
config = json.load(infile)
shapesources = config['shapesources']
backgroundtransparencychoices = config['backgroundtransparencychoices']
textcolorchoices = config['textcolorchoices']
defaults = config['defaults']
stockartdir = "static/stockart/"
stockthumbsdir = "static/stockthumbs/"
mainartfound = []
def build_stock_images():
global mainartfound
thumbsfound = []
thumbstobuild = []
os.makedirs(stockthumbsdir, exist_ok=True) # Make the directory if we don't already have it
for stockart in sorted(glob(stockartdir + "*.jpg")):
basename = stockart.replace("\\", "/").replace(stockartdir, "")
mainartfound.append(basename)
for stockthumb in glob(stockthumbsdir + "*.jpg"):
basename = stockthumb.replace("\\", "/").replace(stockthumbsdir, "")
thumbsfound.append(basename)
for mainart in mainartfound:
if mainart not in thumbsfound:
thumbstobuild.append(mainart)
for thumbfound in thumbsfound:
if thumbfound not in mainartfound:
print(f"You somehow got an extra thumbnail -- {thumbfound} -- but don't have the main art. What did you do?")
if len(thumbstobuild) > 0:
print(f"Need to build {len(thumbstobuild):,} thumbnails.")
thumbnailsize = 480, 360
for thumbtobuild in thumbstobuild:
beer = Image.open(stockartdir + thumbtobuild)
beer.thumbnail(thumbnailsize)
beer.save(stockthumbsdir + thumbtobuild)
beer = None # NOOOOOOOOOOoooooooooooooooooooooo
return()
@app.route('/')
def choose_template():
return(render_template('choose.html',
shapesources=shapesources,
backgroundtransparencychoices=backgroundtransparencychoices,
textcolorchoices=textcolorchoices,
mainartfound=mainartfound))
# https://stackoverflow.com/questions/11017466/flask-to-return-image-stored-in-database
@app.route('/generate/', methods=['GET', 'POST'])
def generate():
z = request.form
# print(z) # HEY!!!! Useful for debugging but not production
# if z['uploadedimage']:
# print(f"File length: {len(z['uploadedimage'])}")
if 'maintext1' not in z or not z['maintext1']:
print(f"No maintext1 -- what did you do?")
# ******************** Should go to an error message web page
else:
maintext = z['maintext1']
if 'shape1' not in z or not z['shape1'] or z['shape1'] not in shapesources:
shapewanted = defaults['shape1']
print(f"\tDefaulting on shape1")
else:
shapewanted = z['shape1']
if 'stockart1' not in z or not z['stockart1'] or z['stockart1'] not in mainartfound:
print(f"Missing or bad stockart1. Defaulting.")
sourceimage = stockartdir + defaults['stockart1']
else:
sourceimage = stockartdir + z['stockart1']
if 'transparency1' not in z or not z['transparency1'] or z['transparency1'] not in backgroundtransparencychoices:
print(f"Missing or bad transparency1. Defaulting.")
transparencywanted = defaults['transparency1']
else:
transparencywanted = z['transparency1']
if 'textcolor1' not in z or not z['textcolor1'] or z['textcolor1'] not in textcolorchoices:
print(f"Missing or bad textcolor1. Defaulting.")
fontcolor = defaults['textcolor1']
else:
fontcolor = z['textcolor1']
if 'fontsize1' not in z or not z['fontsize1'] or not str(z['fontsize1']).isdigit():
print(f"Missing or bad fontsize1. Defaulting.")
fontsize1 = defaults['fontsize1']
else:
fontsize1 = int(z['fontsize1'])
fontdir = "static/fonts/"
mainfont = fontdir + "NotoSans-SemiBold.ttf" # ExtraLight, Light, Regular, Medium, SemiBold, Bold, ExtraBold
targetw, targeth = shapesources[shapewanted]
targeta = float(targetw) / float(targeth)
# https://stackoverflow.com/questions/4744372/reducing-the-width-height-of-an-image-to-fit-a-given-aspect-ratio-how-python
bgimage = Image.open(sourceimage)
sourcew, sourceh = bgimage.size
sourcea = float(sourcew) / float(sourceh)
if sourcea > targeta:
# Then crop the left and right edges:
new_width = int(targeta * sourceh)
offset = (sourcew - new_width) / 2
resize = (offset, 0, sourcew - offset, sourceh)
else:
# ... crop the top and bottom:
new_height = int(sourcew / targeta)
offset = (sourceh - new_height) / 2
resize = (0, offset, sourcew, sourceh - offset)
transparencysetting = 255 - int(float(backgroundtransparencychoices[transparencywanted]) / float(100) * float(255))
bgimage = bgimage.crop(resize).resize((targetw, targeth), Image.Resampling.LANCZOS) # Slowest, but best quality https://pillow.readthedocs.io/en/stable/handbook/concepts.html#filters-comparison-table
# bgimage.show()
if transparencysetting > 0:
filler = Image.new('RGBA', (targetw, targeth), "white")
bgimage.putalpha(transparencysetting)
bgimage = Image.alpha_composite(filler, bgimage)
# bgimage.show()
bgimage = bgimage.convert('RGB')
# Don't need to save the image any more
# bgimage.save('bgimage.jpg') # Check quality settings -- default to 80 maybe?
# Let's figure out some text overlays. Jody's textwrap use isn't really evaluating the actual width of the characters used.
# Some alternatives are here:
# https://gist.github.com/turicas/1455973
# leads to fork at https://gist.github.com/pojda/8bf989a0556845aaf4662cd34f21d269
# for textindex, text in enumerate(texts):
text = maintext
tempimagefilename = "temp-textimage.png"
localimage = deepcopy(bgimage)
fullmarginpct = 0.26 # What percentage for margins
textwidth = int(targetw * (1-float(fullmarginpct)))
insetwidth = int(fullmarginpct / 2 * float(targetw))
textimage = ImageText((targetw, targeth), background=(255, 255, 255, 0))
textimage.write_text_box((insetwidth, insetwidth), text, box_width=textwidth, font_filename=mainfont,
font_size=fontsize1, color=fontcolor)
textimage = textimage.image # Bring this back to a PIL object so we can combine it
localimage = localimage.convert('RGBA')
localimage = Image.alpha_composite(localimage, textimage)
localimage = localimage.convert('RGB')
# Don't need to save sample image any more
# localimage.save(f"sample-test.jpg")
# localimage.show()
timestamp = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S-%f") # Generate fresh time stamp on each export
filename = f"test-{timestamp}.jpg"
binarycontents = io.BytesIO()
localimage.save(binarycontents, "JPEG")
binarycontents.seek(0)
return(send_file(binarycontents,
mimetype='image/jpeg',
as_attachment=True,
download_name=filename))
# return(render_template('done.html',
# filename=filename))
build_stock_images() # Run all that code above.
@app.route('/stockimages/')
def show_stock_images():
return(render_template('stockimages.html',
stockthumbsdir=stockthumbsdir,
mainartfound=mainartfound))
# main driver function
if __name__ == '__main__':
# run() method of Flask class runs the application
# on the local development server.
app.run()