I am coming back to development after years of not working on anything so my skills are rather rusty and I apologize for any improper syntax and formatting issues presented in advance.
I am currently working on a little web app project that takes a text prompt and generates an image using googles aivertex and gemini.
Here is some code snippets for review.
HTML Template
<body>
<h1>Turn your words into art!</h1>
<p>Enter a description of the image you want to generate.</p>
<form target="_blank" id="text-form" action="/my_prompt" onsubmit="dontredict('myindex.html')" method="post">
<label for="text-input">Text Prompt:</label>
<textarea id="text-input" name="text" rows="5" placeholder="e.g. A cat riding a bicycle on Mars"></textarea>
<button type="submit">Generate Image</button>
</form>
<div id="image-container">
{% if img_data %}
<h1>Your generated image will appear here.</h1>
<img id="picture" style="height: 300px;" src="{{url_for('static',filename='my-output.png')}}">
{% else %}
<h1>Image will be render here...</h1>
{% endif %}
</div>
<!--Jquery Cdn -->
<script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc="
crossorigin="anonymous"></script>
<script type="text/javascript">
function dontredict(dynamicUrl){
$(document).on('submit', '#text-form', function (e) {
e.preventDefault();
console.log('button smashed');
$.ajax({
type: 'POST',
url: '/my_prompt',
data: {
text: $("#text-input").val()
},
success: function () {
alert('saved');
}
})
});
}
</script>
</body>
Python text-to-image.py
def disp_image():
if os.path.exists(output_file):
im = Image.open("static/my-output.png")
data = io.BytesIO()
im.save(data, "PNG")
encoded_img_data = base64.b64encode(data.getvalue())
img_data=encoded_img_data.decode('utf-8')
return render_template("myindex.html", img_data=img_data)
#if os.path.exists(output_file):
#return redirect(url_for('static/my-output.png'))
@app.route('/my_prompt', methods = ['POST'])
@cross_origin()
def imggen():
print("inside gen")
if request.method == 'POST':
prompt = request.form.get("text")
logger.info('%s This is the prompt: ', prompt)
print(prompt);
print("after prompt")
model = ImageGenerationModel.from_pretrained("imagegeneration@006")
images = model.generate_images(
prompt=prompt,
# Optional parameters
number_of_images=1,
language="en",
# You can't use a seed value and watermark at the same time.
# add_watermark=False,
# seed=100,
aspect_ratio="1:1",
safety_filter_level="block_some",
person_generation="allow_adult",
)
images[0].save(location=output_file, include_generation_parameters=False)
print(f"Created output image using {len(images[0]._image_bytes)} bytes")
print(disp_image())
return disp_image()
else:
print("error")
The issues I'm having is when the text is posted and comes back with the generated image it get saved properly to the static image folder (using flask and python) but, it does not display or render to the html page. I am also aware that some of the code may be redundant. Let me know what I am doing wrong, in terms of displaying the image to the actual html page, Thank you.
When you use $.ajax
(or built-in modern fetch()
or older XMLHttpRequest()
)
then browser doesn't update HTML. It is your job.
This way you may decide what and when to update on page.
In success()
you have to get response from flask
and you have to add/replace HTML
But first: you don't have to send full page but only some part - like <h1>
and <img>
.
And you can use render_template_string()
for this.
def disp_image():
# ... code ...
return render_template_string('''
<h1>Your generated image will appear here.</h1>
<img id="picture" style="height: 300px;"
src="{{url_for('static',filename='my-output.png')}}">
''')
And later you can replace only content inside <div id="image-container">
$.ajax(
// ... code ...
success: function(response_data) {
$('#image-container').html(response_data);
alert('saved');
}
)
Because browser may not reload image if it will have always the same name - because it will not know that you saved new image with the same name - so you may send image as base64
in src="..."
def disp_image():
# ... code ...
img_data = encoded_img_data.decode('utf-8')
return render_template_string('''
<h1>Your generated image will appear here.</h1>
<img id="picture" style="height: 300px;"
src="data:image/png;base64, {{base64_image}}">
''', base64_image=img_data)
BTW: There is one space after data:image/png;base64,
Of course you can send only base64_image
- ie. as JSON
- and JavaScript can get it and replace only src="..."
(if it already exists on page)
from flask import jsonify
def disp_image():
# ... code ...
img_data = encoded_img_data.decode('utf-8')
return jsonify({'base64_image': img_data})
success: function(response_data) {
var json = $.parseJSON(response_data);
var image = json.base64_image;
$('#picture').attr('src', 'data:image/png;base64, ' + image);
alert('saved');
}
Full working code - with two versions:
h1
and img
img
in JavaScriptBoth uses PIL.Image
to generate image with text
import os
from flask import Flask, request, render_template_string
from PIL import Image, ImageDraw, ImageFont
import io
import base64
os.makedirs('static', exist_ok=True)
app = Flask(__name__)
@app.route('/')
def index():
return render_template_string('''<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc="
crossorigin="anonymous"></script>
</head>
<body>
<form target="_blank" id="text-form" action="/my_prompt" method="POST">
<textarea id="text-input" name="text" rows="5" placeholder="e.g. A cat riding a bicycle on Mars"></textarea></br>
<button type="submit">Generate Image</button>
</form>
<form target="_blank" id="text-form-json" action="/my_prompt_json" method="POST">
<textarea id="text-input-json" name="text" rows="5" placeholder="e.g. A cat riding a bicycle on Mars"></textarea></br>
<button type="submit">Generate Image</button>
</form>
<div id="image-container">
<h1>No Image</h1>
</div>
<script type="text/javascript">
$(document).on('submit', '#text-form', function (e) {
e.preventDefault();
console.log('button smashed');
$.ajax({
type: 'POST',
url: '/my_prompt',
data: {
text: $("#text-input").val()
},
success: function(response_data) {
$('#image-container').html(response_data);
}
})
});
$(document).on('submit', '#text-form-json', function (e) {
e.preventDefault();
console.log('button smashed JSON');
$.ajax({
type: 'POST',
url: '/my_prompt_json',
data: {
text: $("#text-input-json").val()
},
success: function(response_data) {
picture = $('#picture');
if(picture.length === 0) {
picture = $('<img id="picture" style="height: 300px;">');
}
picture.attr('src', 'data:image/png;base64, ' + response_data.base64_image);
$('#image-container').html(picture);
}
})
});
</script>
</body>
</html>''')
def disp_image():
img = Image.open("static/my-output.png")
data = io.BytesIO()
img.save(data, 'PNG')
encoded_img_data = base64.b64encode(data.getvalue())
img_data=encoded_img_data.decode('utf-8')
return render_template_string('''
<h1>Your generated image will appear here.</h1>
<img id="picture" style="height: 300px;"
src="data:image/png;base64, {{base64_image}}">
''', base64_image=img_data)
from flask import jsonify
def disp_image_json():
img = Image.open("static/my-output.png")
data = io.BytesIO()
img.save(data, 'PNG')
encoded_img_data = base64.b64encode(data.getvalue())
img_data=encoded_img_data.decode('utf-8')
return jsonify({'base64_image': img_data})
@app.route('/my_prompt', methods=['POST'])
def image():
if request.method == "POST":
text = request.form.get('text', '???')
print('text:', text)
img = Image.new('RGB', (600, 300))
draw = ImageDraw.Draw(img)
font = ImageFont.truetype("arial.ttf", size=40)
draw.text((10, 10), text, font=font, fill=(255, 255, 255))
img.save('static/my-output.png')
return disp_image()
@app.route('/my_prompt_json', methods=['POST'])
def image_json():
if request.method == "POST":
text = request.form.get('text', '???')
print('text:', text)
img = Image.new('RGB', (600, 300))
draw = ImageDraw.Draw(img)
font = ImageFont.truetype("arial.ttf", size=40)
draw.text((10, 10), text, font=font, fill=(255, 255, 255))
img.save('static/my-output.png')
return disp_image_json()
if __name__ == '__main__':
app.debug = True
app.run()