Home > Software design >  resize image size then store it in database flask
resize image size then store it in database flask

Time:10-23

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.

  • Related