YOUR QUESTION IS:
"Is it possible to compress image size intelligently without specifying how much to compress?
If the end-user does not choose how much to compress the image, then someone else does choose.
An "intelligent" function which automatically chooses the output image size is guaranteed to be a wrapper around a function for which quality must be manually specified.
def automagically_intelligently_compress_picture(in_pic):
# output will be 500 pixels by 680 pixels
out_pic = manually_compress(in_pic, (500, 680))
return out_pic
To compress pictures, you can use PIL
(The Python Imaging Library).
The following code outputs photographs which are almost always smaller than 24000 bytes (24 KB, or 0.024 MB):
import math
from PIL import Image
# Note that when installing the `PIL` library,
# you must write "Pillow", not "PIL"
# EXAMPLE: C:\Users\user>pip install Pillow
big_photo_path_string = "C:\\Users\\user\\Desktop\\rrefwf.png"
# Note that when writing paths when using
# the Microsoft Windows Operatings System:
#
# blackslash (\) is an escape sequence for strings
# For example "\n" means:
# 1. leave the program
# 2. insert a new-line character
# 3. return to program"]
#
# str.__repr__() will...
# ... convert new-lines into slash-n ("\n")
# ... convert carriage returns into slash-r ("\r")
# ... convert tabs into slash-t ("\t")
# ... et cetra
big_photo_path_string = repr(big_photo_path_string)[1:-1]
bigphoto = Image.open(big_photo_path_string)
# Establish Target Size
target_byte_count = 24000
target_pixel_count = 2.8114*target_byte_count
# Note that an image which measures
# 1920 by 1080
# pixels is approximately
# 737,581 bytes
# So we have
# 2.8114 pixels per byte
scale_factor = target_pixel_count/math.prod(bigphoto.size)
# if
# the image is already smaller than the target size
# then
# Do not enlarge the image.
# keep the image the same size.
scale_factor = 1 if scale_factor > 1 else scale_factor
# set new photographs size
# `bigphoto.size` is something like (20000, 37400)
sml_size = list(scale_factor*dim for dim in bigphoto.size)
# We cannot have two-and-a-half pixels
# convert decimal numbers into whole numbers
sml_size = [int(number) for number in sml_size]
# cast `sml_size` to the same data-type as `bigphoto.size`
copy_constructor = type(bigphoto.size)
sml_size = copy_constructor(sml_size)
# create new photograph
sml_photo = bigphoto.resize(sml_size, resample=Image.LANCZOS)
# The new (small/compressed) photo will have different
# name than old (large/un-compressed) photo
#
# EXAMPLE:
# OLD NAME: my_photo.jpg
# NEW NAME: my_photo_out.jpg
p = big_photo_path_string
parts = p.split(".")
out_path = "".join(parts[0:1]) + "_out." + parts[-1]
# save new (small) photograph
sml_photo.save(out_path, optimize=True, quality=95)