lincolnloop / python-qrcode

Python QR Code image generator
https://pypi.python.org/pypi/qrcode
Other
4.25k stars 660 forks source link

White lines appearing when generating codes #357

Open UlrikRos opened 4 months ago

UlrikRos commented 4 months ago

I have not been able to find out why, but sometimes when I generate QR codes of a certain size and with the rounded squares I get these white lines between the cells. It only happens when I use the RoundedModuleDrawer to change the shape of the cells. Here are examples of the same QR code, just different Box_size:

Box size 23 qr_code_1

Box size 24 qr_code_1

Here are the functions I made:

    def generate_qr_code(self):
        text = self.input_box.toPlainText()
        save_path = self.save_path_field.text()
        box_size = self.box_size_slider.value()

        # Define QR code settings
        qr = qrcode.QRCode(
            version=1,
            error_correction=qrcode.constants.ERROR_CORRECT_H,
            box_size=box_size,
            border=2,  # Set the border size here. Smaller value = smaller border.
        )

        icon_path = os.path.join(bundle_dir, 'resources', 'MunuAppLogo-1500x.png')

        for i, line in enumerate(text.split('\n'), start=1):
            if line:  # Skip empty lines
                qr.clear()  # Clear the previous QR code
                qr.add_data(line)
                qr.make(fit=True)

                img = qr.make_image(
                    fill_color="black", 
                    back_color="white",
                    image_factory=StyledPilImage,
                    module_drawer=RoundedModuleDrawer(),
                    eye_drawer=RoundedModuleDrawer(),
                    ).convert('RGB')

                            # Load the icon image
                icon = Image.open(icon_path)
                # Resize icon to fit in the QR code
                img_w, img_h = img.size
                factor = 3  # Factor to size down the icon, adjust as needed.
                icon_w = img_w // factor
                icon_h = img_h // factor
                icon = icon.resize((icon_w, icon_h), Image.Resampling.LANCZOS)

                # Calculate position to place the icon (center)
                w_pos = (img_w - icon_w) // 2
                h_pos = (img_h - icon_h) // 2

                # Paste the icon onto the QR code
                img.paste(icon, (w_pos, h_pos), icon)

                file_path = os.path.join(save_path, f'qr_code_{i}.png')
                img.save(file_path)

        QMessageBox.information(self, "Success", "QR codes generated successfully!")

    def update_box_size_label(self):
        input_text = self.input_box.toPlainText()  # Get the current text input
        first_line = input_text.split('\n', 1)[0] if input_text else ""  # Get only the first line
        input_length = len(first_line)  # Calculate the length of the input
        estimated_version = self.estimate_qr_version(input_length)  # Estimate the QR version

        if estimated_version is None:
            self.box_size_label.setText("Input too long for estimation")
            return

        # Assuming a fixed border size of 4 modules
        border_size_modules = 4
        box_size = self.box_size_slider.value()

        # Calculate the number of modules for the estimated version
        qr_code_version_modules = 21 + (estimated_version - 1) * 4
        image_size_pixels = ((qr_code_version_modules * box_size) + (2 * border_size_modules * box_size))
        print(f"Box size = {box_size}")
        print(f"Input length = {input_length}")

        # Update the label to display the estimated total image size in pixels
        self.box_size_label.setText(f'Estimated Image Size: {image_size_pixels}x{image_size_pixels} pixels')

    def estimate_qr_version(self, input_length, error_correction='H'):
        # Simplified capacity for alphanumeric mode with error correction level H
        capacities = [
            (15, 1), (25, 2), (35, 3), (45, 4), (59, 5),
            (65, 6), (85, 7), (99, 8)
        ]
        for capacity, version in capacities:
            if input_length + 1 <= capacity:
                return version
        return None  # Return None if input is too long for estimated capacities