def getFontSizeByLanguage(string, font, renderer_lib, remove_height_offset=False): # get fontsize according to language string = cgi.escape(string) # Here preparing string to render if any special symbol found then convert into html code for render like(& to &) if int(renderer_lib) == 1: size = font.getsize(string) if remove_height_offset: size[1] -= font.getoffset(string)[1] else: size = pyImage.text(string, dpi=font['normal_font_size'], fontfile=font['normal_font_file']).width, pyImage.text(string, dpi=font['normal_font_size'], fontfile=font['normal_font_file']).height x = pyImage.text(string, dpi=font['normal_font_size'], fontfile=font['normal_font_file']) return size
def renderTextOnImage(text, abs_x, abs_y, background_image, font_file, text_color, font_size, max_width, renderer_lib=1, manage_abs_y=None, manage_abs_x=None, max_height=None, text_resizable=False, hide_extra_text=False, font_family=None, get_details=False, custom_offset=2): """ draw text on image on the basis of height width of a particular box and also make resizable to make best fit to the box The variables are used in method: text: your input text abs_x: absolute value of axis x to render text from abs_y: ablsolute value of axis y to render text from background_image: background or base image to render text on it font_file: font_file to render text with this font text_color: give your custom color for text font_size: give your own font size font_family: this is font family name of the given font(like "Arial Bold" for Arial_Bold font) max_width: maximum width for given aria(box width where text is to render) renderer_lib: this is text renderer library if value is "1" then it will use "pillow" lib and if vlaue is "2" then it will use pyvips to render the text manage_abs_x and y: these variables are to manage axis x and y in the given box(hieght, width) on image if vlaue is "center" then text will be in center(with respect y) bellow: by default manage x and y manage_x= default and y="center" manage_x= default and y="down" manage_x= "center" and y=default manage_x= "right" and y=default manage_x= "center" and y="center" __________________ ______________________ _____________________ ______________________ ______________________ ______________________ |text | | | | | | text | | text| | | | | |text | | | | | | | | text | |________________| |_____________________| |text ________________| |_____________________| |_____________________| |_____________________| max_height: maximun height of the given box text_resizable: It enamble the text resize to fit in the box according to height anbd width hide_extra_text: removes extra text wich is overlapping the given box(in this situation text will not resize automatic) get_details: return only details like(font, text_width, text_total_hieght) custom offset: custom offset between two lines """ if font_size is None: # There are situation when "font_size" is not known but the maximum height that a text will occupy is known. So with "text_resizable" set to true by default # the correct "font_size" will automatically be obtained. And so we make the task easy for the user by ignoring passing an explicit value for it. if max_height is None: raise Exception("Both 'font_size' and 'max_height' cannot be None") if int(renderer_lib) == 1: font_size = max_height else: font_size = max_height*7 if int(renderer_lib) == 1: custom_offset = 0 # background_image = Image.open(background_image) draw = ImageDraw.Draw(background_image) font = ImageFont.truetype(font_file, size=font_size) else: # background_image = pyImage.new_from_file(background_image) font = {'normal_font_file': font_file, 'normal_font_size': font_size} wrapped_text_array, text_width, text_total_height = getWrappedTextMaxHeightWidth(text, font, max_width, renderer_lib) if text_resizable: while (text_width > max_width or text_total_height>max_height) and font_size>0: # Limiting lines count by decreasing font_size and text_writing_space_width_in_pixel if int(renderer_lib) == 1: font_size -= 1 font = ImageFont.truetype(font_file, size=font_size) else: font_size -= 1 font.update({'normal_font_size': font_size}) wrapped_text_array, text_width, text_total_height = getWrappedTextMaxHeightWidth(text, font, max_width, renderer_lib) text_total_height = text_total_height + (custom_offset*(len(wrapped_text_array)-1)) if hide_extra_text: copy_text = "".join(wrapped_text_array) while (text_width > max_width or text_total_height>max_height) and font_size>0: # Limiting lines count by decreasing font_size and text_writing_space_width_in_pixel text = text[:-1] wrapped_text_array, text_width, text_total_height = getWrappedTextMaxHeightWidth(text, font, max_width, renderer_lib) text_total_height = text_total_height + (custom_offset*(len(wrapped_text_array)-1)) if len("".join(wrapped_text_array)) != len(copy_text): wrapped_text_array[-1] = wrapped_text_array[-1][:-3] + "..." if get_details: return font, text_width, text_total_height if manage_abs_y and max_height: if manage_abs_y=="center" and (max_height-text_total_height)>0: abs_y = abs_y + (max_height-text_total_height)/2 if manage_abs_y=="down" and (max_height-text_total_height)>0: abs_y = abs_y + (max_height-text_total_height) reset_abs_x = abs_x for line in wrapped_text_array: if manage_abs_x: text_line_width = getFontSizeByLanguage(line, font, renderer_lib)[0] if manage_abs_x=="center" and (max_width-text_line_width)>0: abs_x = reset_abs_x + (max_width-text_line_width)/2 if manage_abs_x=="right" and (max_width-text_line_width)>0: abs_x = reset_abs_x + (max_width-text_line_width) if int(renderer_lib) == 1: text_height = font.getsize(line)[1] abs_y -= font.getoffset(line)[1] # remove top y_offset value from abs_y to draw text from exact axis(x, y) draw.text((abs_x, abs_y), line, fill=text_color, font=font) abs_y += text_height + font.getoffset(line)[1] else: text_height = getFontSizeByLanguage(line, font, renderer_lib)[1] line = cgi.escape(line) # Here preparing string to render if any special symbol found then convert into html code for render like(& to &) text = pyImage.text(line, dpi=font['normal_font_size'], font=font_family, fontfile=font_file, align = "centre") # print(font_file, line, font['normal_font_size']) # we'll use that as the alpha scale down to make it transparent alpha = (text).cast("uchar") # make a blue rectangle the same size and tag as srgb overlay = text.new_from_image(list(text_color)).copy(interpretation="srgb") # attach the alpha overlay = overlay.bandjoin(alpha) # load an image and composite on the overlay background_image = background_image.composite2(overlay, 'over', x = abs_x, y = abs_y) abs_y += text_height + custom_offset return font, background_image