Source code for odoo_xmlrpc_twisted.functions.save_picture

"""
Module saves the picture of an object in Odoo.
"""

import base64
import os
import configparser
import io
from PIL import Image


# call the function "get_settings_odoo" to get the parameters
# for the logging of the model on the "odoo Webservice API"
try:
    from .get_settings_odoo import get_settings_odoo
except ImportError:
    from get_settings_odoo import get_settings_odoo
result   = get_settings_odoo()
db       = result[0]
uid      = result[1]
password = result[3]
models   = result[4]



# ------- for the initialisation get parameters from the File "parameter_google.ini" -------

# Name and full path of the Parameter File
file_name  = "parameter_google.ini"
path_name  = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))  # Go up to repo root
config_path = os.path.join(path_name, 'config')
fullpath   = os.path.join(config_path, file_name)

config     = configparser.ConfigParser()
config.read(fullpath)

# get the aspect ratio for the picture to be saved
aspect_ratio        = config.get('handle_picture', 'aspect_ratio')
custom_aspect_ratio = float(aspect_ratio)
# get the image size for the picture to be saved
# must be either 1920, 1024, 512, 256 or 128
image_size          = config.get('handle_picture', 'image_size')
custom_image_size   = int(image_size)



[docs] def pad_if_needed(img, target_aspect_ratio, padding_color=(0, 0, 0, 0)): """ Adds padding only if the image's aspect ratio does not match the target. Keeps the original image unchanged and centers it on a new canvas if needed. Parameters: img: PIL.Image – input image (any mode) target_aspect_ratio: float – desired aspect ratio (width / height) padding_color: tuple or int – background color (must match img.mode) Returns: PIL.Image – either the original image or a padded one """ current_aspect = img.width / img.height if abs(current_aspect - target_aspect_ratio) < 1e-2: # Already matches → return unchanged return img # Calculate new canvas size if current_aspect > target_aspect_ratio: # Too wide → pad height new_height = int(img.width / target_aspect_ratio) new_width = img.width else: # Too tall → pad width new_width = int(img.height * target_aspect_ratio) new_height = img.height # Create a new canvas in the same mode with the background color padded = Image.new(img.mode, (new_width, new_height), padding_color) # Paste original image in the center offset_x = (new_width - img.width) // 2 offset_y = (new_height - img.height) // 2 padded.paste(img, (offset_x, offset_y)) return padded
[docs] def save_picture(product_id, perspective_or_image, image=None): """ Function saves the picture under the product_template_id of the product. The image will be stored with the image size from 'custom_image_size'. """ # Handle different calling patterns if image is None: # Called with 2 parameters: save_picture(product_id, image_data) perspective = 'general' image = perspective_or_image else: # Called with 3 parameters: save_picture(product_id, perspective, image_data) perspective = perspective_or_image # convert base64 string (= image) to PIL image (= img) buffer = io.BytesIO() imgdata = base64.b64decode(image) img = Image.open(io.BytesIO(imgdata)) # initialize the result custom_id = '' if product_id != '': # get the product_template_id for the product # the picture will be save under the product_template_id as the key value custom_product = models.execute_kw(db,uid, password, 'product.product', 'search_read', [[['id', '=', product_id]]], {'fields': ['product_tmpl_id']}) # if the array is not empty # get the value for 'product_tmpl_id' if custom_product: for key, value in custom_product[0].items(): if key == "product_tmpl_id": custom_product_tmpl_id = value[0] # build the "res_field" name for the picture, must be like for example "image_128" custom_res_field = "image_" + str(custom_image_size) # build the name for the picture, like for example "image_128_front" custom_name = custom_res_field + "_" + perspective # pads the image only if needed, while keeping everything else untouched. img_padded = pad_if_needed(img, custom_aspect_ratio, padding_color=(0, 0, 0, 0)) # Transparent padding img_padded.save(buffer, format="PNG") img_b64 = base64.b64encode(buffer.getvalue()) custom_datas = img_b64.decode('ascii') # store the image in the Odoo database # save the picture under the product_template_id # the value "datas" will keep the picture image custom_id = models.execute_kw(db,uid, password,'ir.attachment', 'create', [{'name': custom_name, 'datas': custom_datas, 'type': 'binary', 'res_id': custom_product_tmpl_id, 'res_field': custom_res_field, 'res_model': 'product.template',}]) # the result is the id of the newly created dataset of the image in the table "ir.attachment" return(custom_id)