From 820eacf9c67cf5353953a5a8541f11aeed8c510c Mon Sep 17 00:00:00 2001 From: Alexander Smirnov <145155732+smalyu@users.noreply.github.com> Date: Mon, 2 Sep 2024 23:59:30 +0500 Subject: [PATCH] Optimize QRColorMask apply_mask method for enhanced performance This commit introduces optimizations to the apply_mask method in the QRColorMask class to improve performance. Changes include: 1. Replacing getpixel and putpixel with direct pixel manipulation using the load() method, which speeds up the process. 2. Implementing a caching mechanism to reuse color transformations for identical pixel colors, reducing redundant calculations. 3. Adding conditions to skip processing for background color pixels to reduce computational load. These optimizations have significantly reduced the method's execution time. In some experiments, these changes have resulted in performance improvements of over ten times compared to the original method, especially for larger images. --- qrcode/image/styles/colormasks.py | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/qrcode/image/styles/colormasks.py b/qrcode/image/styles/colormasks.py index 3b9a8084..cb3815ef 100644 --- a/qrcode/image/styles/colormasks.py +++ b/qrcode/image/styles/colormasks.py @@ -32,22 +32,27 @@ def initialize(self, styledPilImage, image): def apply_mask(self, image): width, height = image.size + pixels = image.load() + fg_color_cache = {} for x in range(width): for y in range(height): - norm = self.extrap_color( - self.back_color, self.paint_color, image.getpixel((x, y)) - ) + current_color = pixels[x, y] + if current_color == self.back_color: + continue + if current_color in fg_color_cache: + pixels[x, y] = fg_color_cache[current_color] + continue + norm = self.extrap_color(self.back_color, self.paint_color, current_color) if norm is not None: - image.putpixel( - (x, y), - self.interp_color( - self.get_bg_pixel(image, x, y), - self.get_fg_pixel(image, x, y), - norm, - ), + new_color = self.interp_color( + self.get_bg_pixel(image, x, y), + self.get_fg_pixel(image, x, y), + norm ) + pixels[x, y] = new_color + fg_color_cache[current_color] = new_color else: - image.putpixel((x, y), self.get_bg_pixel(image, x, y)) + pixels[x, y] = self.get_bg_pixel(image, x, y) def get_fg_pixel(self, image, x, y): raise NotImplementedError("QRModuleDrawer.paint_fg_pixel")