def add_text(self, text, font_name, color, align=CENTER): """Add a new text. :param text: text to draw :type text: str :param font_name: name or path to font file :type font_name: str :param color: RGB tuple :type color: tuple :param align: text alignment: left, right or center :type align: str """ assert align in [self.CENTER, self.RIGHT, self.LEFT], "Unknown aligment '{}'".format(align) self._texts.append((text, fonts.get_filename(font_name), color, align)) if self.is_portrait: self._texts_height = 600 else: self._texts_height = 300 self._final = None # Force rebuild
def _update_print_number(self): """Update the number of files in the printer queue. """ if not self._print_number: return # Dont show counter: no file in queue smaller = self.size[1] if self.size[1] < self.size[0] else self.size[0] side = int(smaller * 0.05) # 5% of the window if side > 0: if self._print_failure: image = pictures.get_pygame_image('printer_failure.png', (side, side)) else: image = pictures.get_pygame_image('printer.png', (side, side)) y = self.surface.get_rect().height - image.get_rect().height - 10 self.surface.blit(image, (10, y)) font = pygame.font.Font(fonts.get_filename("Amatic-Bold"), side) label = font.render(str(self._print_number), True, (255, 255, 255)) self.surface.blit(label, (side + 20, y))
def _build_submenu(self, section, width, height): """Build sub-menu""" menu = pgm.Menu( self.window.surface, width, height, fonts.get_filename("Amatic-Bold"), section.capitalize(), font_size=30, font_color=(133, 153, 0), color_selected=(203, 75, 22), menu_color=(253, 246, 227), menu_color_title=(238, 232, 213), dopause=False, ) for name, option in DEFAULT[section].items(): if option[2]: if isinstance(option[3], str): menu.add_text_input( option[2], onchange=self._on_text_changed, default=self.config.get(section, name), # Additional parameters: section=section, option=name) else: values = [(v, ) for v in option[3]] menu.add_selector( option[2], values, onchange=self._on_selector_changed, default=_find(values, self.config.get(section, name)), # Additional parameters: section=section, option=name) return menu
import pibooth from pibooth import fonts from pibooth.utils import LOGGER from pibooth.config.parser import DEFAULT pgm.controls.KEY_BACK = pygame.K_ESCAPE THEME_WHITE = pgm.themes.Theme( background_color=(255, 255, 255), scrollbar_thick=14, scrollbar_slider_pad=2, scrollbar_slider_color=(35, 149, 135), selection_color=(29, 120, 107), title_background_color=(35, 149, 135), title_font=fonts.get_filename("Monoid-Regular"), title_font_size=33, title_font_color=(255, 255, 255), widget_margin=(0, 20), widget_font=fonts.get_filename("Monoid-Retina"), widget_font_size=30, widget_font_color=(0, 0, 0), ) SUBTHEME1_WHITE = THEME_WHITE.copy() SUBTHEME1_WHITE.background_color = (255, 255, 255) SUBTHEME1_WHITE.scrollbar_slider_color = (252, 151, 0) SUBTHEME1_WHITE.selection_color = (241, 125, 1) SUBTHEME1_WHITE.title_background_color = (252, 151, 0) SUBTHEME1_WHITE.widget_alignment = pgm.locals.ALIGN_LEFT SUBTHEME1_WHITE.widget_margin = (40, 10)
def concatenate_pictures_portrait(pictures, footer_texts, bg_color, text_color, inter_width=None): """ Merge up to 4 PIL images in portrait orientation. +---------+ +---------+ +---+-+---+ +---------+ | | | +-+ | | |1| | | +-+ +-+ | | | | |1| | | +-+ | | |1| |2| | | +-+ | | +-+ | | +-+ | | +-+ +-+ | | |1| | | | | |2| | | | | +-+ | | +-+ | | +-+ | | +-+ +-+ | | | | |2| | | +-+ | | |3| |4| | | | | +-+ | | |3| | | +-+ +-+ | +---------+ +---------+ +---+-+---+ +---------+ """ widths, heights = zip(*(i.size for i in pictures)) # starting here we consider that all the images have the same height and widths if inter_width is None: inter_width = max(heights) // 20 if len(pictures) == 1: new_width = max(widths) + inter_width * 2 new_height = max(heights) + inter_width * 2 elif len(pictures) == 2: new_width = max(widths) + inter_width * 2 new_height = max(heights) * 2 + inter_width * 3 elif len(pictures) == 3: new_width = max(widths) + inter_width * 2 new_height = max(heights) * 3 + inter_width * 4 elif len(pictures) == 4: new_width = max(widths) * 2 + inter_width * 3 new_height = max(heights) * 2 + inter_width * 3 else: raise ValueError("List of max 4 pictures expected, got {}".format( len(pictures))) matrix = Image.new('RGBA', (new_width, new_height)) x_offset = inter_width y_offset = inter_width # Consider that the photo are correctly ordered matrix.paste(pictures[0], (x_offset, y_offset)) if len(pictures) == 2: y_offset += (pictures[0].size[1] + inter_width) matrix.paste(pictures[1], (x_offset, y_offset)) elif len(pictures) == 3: y_offset += (pictures[0].size[1] + inter_width) matrix.paste(pictures[1], (x_offset, y_offset)) y_offset += (pictures[1].size[1] + inter_width) matrix.paste(pictures[2], (x_offset, y_offset)) elif len(pictures) == 4: x_offset += (pictures[0].size[0] + inter_width) matrix.paste(pictures[1], (x_offset, y_offset)) y_offset += (pictures[1].size[1] + inter_width) x_offset = inter_width matrix.paste(pictures[2], (x_offset, y_offset)) x_offset += (pictures[2].size[0] + inter_width) matrix.paste(pictures[3], (x_offset, y_offset)) final_width, final_height = 2400, 3600 if not footer_texts[0] and not footer_texts[1]: matrix_width, matrix_height = final_width, final_height footer_size = 0 else: matrix_width, matrix_height = 2400, 3000 footer_size = 600 matrix = matrix.resize( sizing.new_size_keep_aspect_ratio(matrix.size, (matrix_width, matrix_height)), Image.ANTIALIAS) final_image = new_image_with_background(final_width, final_height, bg_color) final_image.paste(matrix, ((final_width - matrix.size[0]) // 2, (final_height - footer_size - matrix.size[1]) // 2), mask=matrix) if footer_size: # Text part draw = ImageDraw.Draw(final_image) # Footer 1 name_font = ImageFont.truetype(fonts.get_filename("Amatic-Bold.ttf"), int(2 / 3. * footer_size)) name_width, name_height = draw.textsize(footer_texts[0], font=name_font) footer_x = (final_width - name_width) // 2 footer_y = final_height - footer_size - 100 draw.text((footer_x, footer_y), footer_texts[0], text_color, font=name_font) # Footer 2 date_font = ImageFont.truetype( fonts.get_filename("AmaticSC-Regular.ttf"), int(1 / 3. * footer_size)) date_width, date_height = draw.textsize(footer_texts[1], font=date_font) footer_x = (final_width - date_width) // 2 footer_y = final_height - footer_size + 300 draw.text((footer_x, footer_y), footer_texts[1], text_color, font=date_font) return final_image
def create_qr_code_print(qr_code_image, result_image, texts, pic_crypt_name): width = 580 background = Image.new('RGB', (width, 650), color=(255, 255, 255)) img_qr = Image.open(qr_code_image) qr_size = (int(400), int(400)) resized_img_qr = img_qr.resize(qr_size, Image.ANTIALIAS) background.paste(resized_img_qr, (90 + 30,0)) #('Amatic-Bold', 'AmaticSC-Regular'), draw = ImageDraw.Draw(background) text_y = 370 font_string = 'Roboto-Light' help = ["http://example.org", "Code: {}".format(pic_crypt_name)] max_width = 500 max_height = 50 color = (0, 0, 0) font_name = fonts.get_filename(font_string) # Use PIL to draw text because better support for fonts than OpenCV font = fonts.get_pil_font(help[0], font_name, max_width, max_height) for text in help: text_x = 70 _, text_height = font.getsize(text) (text_width, _baseline), (offset_x, offset_y) = font.font.getsize(text) text_x += (max_width - text_width) // 2 draw.text((text_x - offset_x // 2, text_y + (max_height - text_height) // 2 - offset_y // 2), text, color, font=font) text_y += text_height # text_y = 400 font_string = 'Amatic-Bold' max_height = (650 - text_y )/2 for text in texts: if not text: # Empty string: go to next text position continue max_width = 520 text_x = 60 color = (0, 0, 0) font_name = fonts.get_filename(font_string) # Use PIL to draw text because better support for fonts than OpenCV font = fonts.get_pil_font(text, font_name, max_width, max_height) _, text_height = font.getsize(text) (text_width, _baseline), (offset_x, offset_y) = font.font.getsize(text) text_x += (max_width - text_width) // 2 draw.text((text_x - offset_x // 2, text_y + (max_height - text_height) // 2 - offset_y // 2), text, color, font=font) text_y += text_height background.save(result_image) return background
def concatenate_pictures(pictures, footer_texts, bg_color, text_color): """ Merge up to 4 PIL images and retrun concatenated image as a new PIL image object. Configuration of the final picture depends on the number of given pictues:: +---------+ +---------+ +---+-+---+ +---------+ | | | +-+ | | |1| | | +-+ +-+ | | | | |1| | | +-+ | | |1| |2| | | +-+ | | +-+ | | +-+ | | +-+ +-+ | | |1| | | | | |2| | | | | +-+ | | +-+ | | +-+ | | +-+ +-+ | | | | |2| | | +-+ | | |3| |4| | | | | +-+ | | |3| | | +-+ +-+ | +---------+ +---------+ +---+-+---+ +---------+ """ widths, heights = zip(*(i.size for i in pictures)) # starting here we consider that all the images have the same height and widths inter_width = max(heights) // 20 if len(pictures) == 1: new_width = max(widths) + inter_width * 2 new_height = max(heights) + inter_width * 2 elif len(pictures) == 2: new_width = max(widths) + inter_width * 2 new_height = max(heights) * 2 + inter_width * 3 elif len(pictures) == 3: new_width = max(widths) + inter_width * 2 new_height = max(heights) * 3 + inter_width * 4 elif len(pictures) == 4: new_width = max(widths) * 2 + inter_width * 3 new_height = max(heights) * 2 + inter_width * 3 else: raise ValueError("List of max 4 pictures expected, got {}".format( len(pictures))) matrix = Image.new('RGB', (new_width, new_height), color=bg_color) x_offset = inter_width y_offset = inter_width # Consider that the photo are correctly ordered matrix.paste(pictures[0], (x_offset, y_offset)) if len(pictures) == 2: y_offset += (pictures[0].size[1] + inter_width) matrix.paste(pictures[1], (x_offset, y_offset)) elif len(pictures) == 3: y_offset += (pictures[0].size[1] + inter_width) matrix.paste(pictures[1], (x_offset, y_offset)) y_offset += (pictures[1].size[1] + inter_width) matrix.paste(pictures[2], (x_offset, y_offset)) elif len(pictures) == 4: x_offset += (pictures[0].size[0] + inter_width) matrix.paste(pictures[1], (x_offset, y_offset)) y_offset += (pictures[1].size[1] + inter_width) x_offset = inter_width matrix.paste(pictures[2], (x_offset, y_offset)) x_offset += (pictures[2].size[0] + inter_width) matrix.paste(pictures[3], (x_offset, y_offset)) matrix = matrix.resize(resize_keep_aspect_ratio(matrix.size, (2400, 3000)), Image.ANTIALIAS) final_width, final_height = 2400, 3600 final_image = Image.new('RGB', (final_width, final_height), color=bg_color) final_image.paste(matrix, ((final_width - matrix.size[0]) // 2, (3000 - matrix.size[1]) // 2)) # Text part x_offset = 300 y_offset = 2900 draw = ImageDraw.Draw(final_image) name_font = ImageFont.truetype(fonts.get_filename("Amatic-Bold.ttf"), 400) name_width, _ = draw.textsize(footer_texts[0], font=name_font) draw.text(((final_width - name_width) // 2, y_offset), footer_texts[0], text_color, font=name_font) date_font = ImageFont.truetype(fonts.get_filename("AmaticSC-Regular.ttf"), 200) date_width, _ = draw.textsize(footer_texts[1], font=date_font) draw.text(((final_width - date_width) // 2, y_offset + 400), footer_texts[1], text_color, font=date_font) return final_image