#!/usr/bin/env python3 import os import sys from PIL import Image, ImageDraw, ImageFont import textwrap MAX_FONT_SIZE = 15 # Maximum font size WORD_SPACING = 10 # Word spacing in pixels SIDE_SPACING = 3 # Space from image sides in pixels TOP_BOTTOM_SPACING = 10 # Space from top and bottom of image in pixels def calculate_font_size(text, image_size, font_path): # Create a dummy image to get the text size dummy_img = Image.new('RGB', (1, 1)) draw = ImageDraw.Draw(dummy_img) # Start from a large font size font_size = 200 font = ImageFont.truetype(font_path, font_size) # Decrease the font size until the text fits the image width while draw.textbbox((0, 0), text, font)[2] > image_size[0] - 2 * SIDE_SPACING: font_size -= 1 font = ImageFont.truetype(font_path, font_size) return font_size def split_text(text, max_font_size, image_size, font_path): # Wrap the text based on word spacing and /n wrapper = WordSpacingTextWrapper(width=image_size[0], word_spacing=WORD_SPACING) wrapped_text = [] for line in text.split('\n'): lines = wrapper.wrap(line) wrapped_text.extend(lines) return wrapped_text class WordSpacingTextWrapper(textwrap.TextWrapper): def __init__(self, word_spacing=0, **kwargs): super().__init__(**kwargs) self.word_spacing = word_spacing def _wrap_chunks(self, chunks): # Add word spacing between chunks chunks = super()._wrap_chunks(chunks) lines = [] for i, line in enumerate(chunks): if i < len(chunks) - 1: line += ' ' * self.word_spacing lines.append(line) return lines def main(text, debug=False): image_width = 200 image_height = image_width // 4 image_size = (image_width, image_height) font_path = "/home/devdesk/.local/share/fonts/5x5_pixel.ttf" text_for_filename = text.replace(' ', '_').replace('/', '_').replace('\n', '') filename = f"labels/{text_for_filename}.png" font_size = calculate_font_size(text, image_size, font_path) # Split the text into multiple lines if the font size is less than 20 if font_size < 20: lines = split_text(text, 20, image_size, font_path) # Recalculate the font size and image height with the split text font_size = calculate_font_size('\n'.join(lines), image_size, font_path) num_lines = len(lines) line_height = font_size line_spacing = line_height // 2 # Adjust line spacing as needed image_height = line_height * num_lines + 2 * TOP_BOTTOM_SPACING + (num_lines - 1) * line_spacing image_size = (image_width, image_height) else: lines = [text] num_lines = 1 line_height = font_size line_spacing = line_height // 2 # Adjust line spacing as needed image_height = line_height + 2 * TOP_BOTTOM_SPACING # Create the image img = Image.new('RGB', image_size, color='white') d = ImageDraw.Draw(img) font = ImageFont.truetype(font_path, font_size) # Draw the text for each line y = TOP_BOTTOM_SPACING for line in lines: words = line.split(' ') word_widths = [d.textbbox((0, 0), word, font)[2] - d.textbbox((0, 0), word, font)[0] for word in words] total_width = sum(word_widths) + (WORD_SPACING * (len(words) - 1)) x = (image_width - total_width) // 2 + SIDE_SPACING for i, word in enumerate(words): d.text((x, y), word, fill='black', font=font) x += word_widths[i] + WORD_SPACING y += line_height + line_spacing img.save(filename) print(f"PNG file created: {filename}") if not debug: os.system( f'sudo brother_ql -b pyusb --model QL-570 -p usb://0x04f9:0x2028/000M6Z401370 --debug print -l 62 {filename}' ) if __name__ == "__main__": if len(sys.argv) < 2: print("Usage: ./text_to_image.py [debug]") sys.exit(1) text = sys.argv[1].replace('\\n', '\n') # Add this line debug = sys.argv[2] == 'debug' if len(sys.argv) > 2 else False main(text, debug)