Skip to content

Commit cf3edc6

Browse files
feat: enhance QR code generation with TECH_FLORIPA logo integration and update certificate generation process
1 parent b66878f commit cf3edc6

2 files changed

Lines changed: 33 additions & 11 deletions

File tree

certified_builder/certified_builder.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import logging
2-
import tempfile
32
import os
43
from typing import List
54
from PIL import Image, ImageDraw, ImageFont
6-
from io import BytesIO
75
from models.participant import Participant
6+
from config import config
87
from certified_builder.utils.fetch_file_certificate import fetch_file_certificate
98
from certified_builder.certificates_on_solana import CertificatesOnSolana
109
from certified_builder.make_qrcode import MakeQRCode
@@ -33,6 +32,7 @@ def build_certificates(self, participants: List[Participant]):
3332
# Cache for background and logo if they are the same for all participants
3433
certificate_template = None
3534
logo = None
35+
logo_tech_floripa = None
3636

3737
# Check if all participants share the same background and logo
3838
if participants:
@@ -46,6 +46,9 @@ def build_certificates(self, participants: List[Participant]):
4646
if all_same_logo:
4747
logo = self._download_image(first_participant.certificate.logo)
4848

49+
if not logo_tech_floripa:
50+
logo_tech_floripa = self._download_image(config.TECH_FLORIPA_LOGO_URL)
51+
4952
for participant in participants:
5053
try:
5154
# Register certificate on Solana, with returned data extract url for verification
@@ -57,7 +60,7 @@ def build_certificates(self, participants: List[Participant]):
5760
"certificate_code": participant.formated_validation_code()
5861
}
5962
)
60-
63+
6164
# alteração: agora usamos a função renomeada que apenas extrai o explorer_url
6265
participant.authenticity_verification_url = extract_solana_explorer_url(solana_response=solana_response)
6366

@@ -71,7 +74,7 @@ def build_certificates(self, participants: List[Participant]):
7174
logo = self._download_image(participant.certificate.logo)
7275

7376
# Generate and save certificate
74-
certificate_generated = self.generate_certificate(participant, certificate_template, logo)
77+
certificate_generated = self.generate_certificate(participant, certificate_template, logo, logo_tech_floripa)
7578
certificate_path = self.save_certificate(certificate_generated, participant)
7679

7780
results.append({
@@ -121,7 +124,7 @@ def _ensure_valid_rgba(self, img: Image) -> Image:
121124
new_img.paste(img.convert('RGB'), (0, 0))
122125
return new_img
123126

124-
def generate_certificate(self, participant: Participant, certificate_template: Image, logo: Image):
127+
def generate_certificate(self, participant: Participant, certificate_template: Image, logo: Image, logo_tech_floripa: Image):
125128
"""Generate a certificate for a participant."""
126129
try:
127130
# Ensure images have valid transparency channels
@@ -145,9 +148,10 @@ def generate_certificate(self, participant: Participant, certificate_template: I
145148
# Fallback without using the logo as its own mask
146149
overlay.paste(logo, (50, 50))
147150

148-
151+
url_qr_code = f"{config.TECH_FLORIPA_CERTIFICATE_VALIDATE_URL}?validate_code={participant.formated_validation_code()}"
149152
qrcode_size = (150, 150)
150-
qr_code_image_io = MakeQRCode.generate_qr_code(participant.authenticity_verification_url)
153+
logger.info(f"URL do QR code: {url_qr_code} para o certificado de {participant.name_completed()}")
154+
qr_code_image_io = MakeQRCode.generate_qr_code(url_qr_code, logo_tech_floripa=logo_tech_floripa)
151155
qr_code_image = Image.open(qr_code_image_io).convert("RGBA")
152156
# comentário: para manter o QR nítido, usamos NEAREST ao redimensionar
153157
if qr_code_image.size != qrcode_size:

certified_builder/make_qrcode.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,19 @@
22
import qrcode
33
import logging
44
from io import BytesIO
5+
from PIL import Image
56
from qrcode.image.pil import PilImage
67

78
logger = logging.getLogger(__name__)
89

910
class MakeQRCode:
1011
@staticmethod
11-
def generate_qr_code(data: str) -> BytesIO:
12+
def generate_qr_code(data: str, logo_tech_floripa: Image) -> BytesIO:
1213
try:
13-
logger.info("Generating QR code ")
14+
logger.info(f"Generating QR code for {data}")
1415
qr = qrcode.QRCode(
1516
version=1,
16-
error_correction=qrcode.constants.ERROR_CORRECT_L,
17+
error_correction=qrcode.constants.ERROR_CORRECT_H,
1718
box_size=10,
1819
border=4,
1920
)
@@ -22,10 +23,27 @@ def generate_qr_code(data: str) -> BytesIO:
2223
qr.make(fit=True)
2324
img = qr.make_image(fill_color="black", back_color="transparent", image_factory=PilImage)
2425
img = img.convert("RGBA")
26+
27+
# Redimensiona o logo para aproximadamente 30% do tamanho do QR code
28+
# Tamanho limitado para não interferir nos padrões de detecção nos cantos
29+
qr_width, qr_height = img.size
30+
logo_size = int(min(qr_width, qr_height) * 0.3)
31+
logo_resized = logo_tech_floripa.copy()
32+
logo_resized.thumbnail((logo_size, logo_size), Image.Resampling.LANCZOS)
33+
logo_resized = logo_resized.convert("RGBA")
34+
35+
# Calcula a posição central para colar o logo
36+
logo_width, logo_height = logo_resized.size
37+
position = ((qr_width - logo_width) // 2, (qr_height - logo_height) // 2)
38+
39+
# Cola o logo no centro do QR code mantendo transparência
40+
# Com ERROR_CORRECT_H (30% redundância), o QR code permanece legível mesmo com o logo
41+
img.paste(logo_resized, position, logo_resized)
42+
2543
byte_io = BytesIO()
2644
img.save(byte_io, format='PNG')
2745
byte_io.seek(0)
28-
logger.info("QR code generated successfully")
46+
logger.info(f"QR code generated successfully for {data}")
2947
return byte_io
3048
except Exception as e:
3149
logging.error(f"Failed to generate QR code: {e}")

0 commit comments

Comments
 (0)