I am using this way to pic image and store it in my database using flask :
class Gallery(db.Model):
__tablename__ = 'Gallery'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(128), nullable=False)
name = db.Column(db.String(128), nullable=False)
data = db.Column(db.LargeBinary, nullable=False)
rendered_data = db.Column(db.Text, nullable=False)
def render_picture(data):
render_pic = base64.b64encode(data).decode('ascii')
return render_pic
@app.route('/gallery/create', methods=['POST'])
def create_gallery():
title = request.form['title']
file = request.files['file']
data = file.read()
render_file = render_picture(data)
newFile = Gallery(name=file.filename, data=data, rendered_data=render_file, title=title)
db.session.add(newFile)
db.session.commit()
db.session.close()
and it is working fine but I need to reduce image size before I store it in my database I tried Pillow in many ways but it did not work with my way to store the image
can anyone help me reduce image size?
CodePudding user response:
In my example, the uploaded image is scaled and stored in the database as binary data. To display it, there is either the possibility of creating a data url of the data or of downloading the data of the image as a file.
from flask import Flask
from flask import redirect, render_template, request, url_for, send_file
from flask_sqlalchemy import SQLAlchemy
from PIL import Image
import base64
import io
app = Flask(__name__)
db = SQLAlchemy(app)
class Gallery(db.Model):
id = db.Column(db.Integer, primary_key=True)
img_data = db.Column(db.LargeBinary(),
nullable=True, unique=False, index=False)
@property
def b64encoded(self):
return base64.b64encode(self.img_data).decode()
with app.app_context():
db.create_all()
@app.route('/', methods=['GET'])
def index():
galleries = Gallery.query.all()
return render_template('index.html', **locals())
def image_resize(file, size=84):
img = Image.open(file)
img_size = img.size
img_ratio = size/img_size[0]
img.thumbnail((img_size[0]*img_ratio, img_size[1]*img_ratio), Image.ANTIALIAS)
return image_to_bytes(img)
def image_to_bytes(image):
stream = io.BytesIO()
image.save(stream, format='PNG')
return stream.getvalue()
@app.route('/create', methods=['POST'])
def create():
if not 'img' in request.files:
abort(400)
file = request.files['img']
gallery = Gallery()
gallery.img_data = image_resize(file)
db.session.add(gallery)
db.session.commit()
return redirect(url_for('index'))
@app.route('/<int:gallery_id>/image')
def download_image(gallery_id):
gallery = Gallery.query.get_or_404(gallery_id)
if not gallery.img_data:
abort(404)
return send_file(
io.BytesIO(gallery.img_data),
as_attachment=False,
mimetype='image/png'
)
CodePudding user response:
I can't really understand what's in your file and how are you executing it but as long as it works, it's fine. Coming on to your question about resizing image, you are right to use PIL (Python Imaging Library). I am not familiar with base64 and io and I don't think you need them at all. The way I resize my images is:
You can create a function to do this as:
def save_picture(form_picture):
random_hex = secrets.token_hex(8)
I use Python secrets that can be imported as
import secrets
that can be used to generate a random name for image so we don't have many images with same name, I have specified it to be 8 bits as shown above. form_picture
is an argument here:
_,f_ext = os.path.splitext(form_picture.filename)
picture_fn = random_hex f_ext
picture_path = os.path.join(app.root_path, 'static/profile_pics',
picture_fn)
output_size = (125, 125)
i = Image.open(form_picture)
This will define the path of picture, joining "static/profile_pics"
with picture_fn
variable that is name of variable defining the actual name of picture. output_size
function is specifying picture to be of 125 pixels.
i.thumbnail(output_size)
i.save(picture_path)
return picture_fn
and at end to save above picture.