File size: 11,882 Bytes
0f2840d
14c7d5f
0f2840d
 
 
14c7d5f
 
0f2840d
 
 
14c7d5f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cee3d2a
 
 
14c7d5f
 
cee3d2a
 
 
14c7d5f
 
 
 
0f2840d
 
 
 
 
 
14c7d5f
0f2840d
 
 
14c7d5f
 
 
 
 
0f2840d
 
14c7d5f
 
 
 
 
 
 
 
 
0f2840d
14c7d5f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0f2840d
14c7d5f
d65f0be
 
 
 
14c7d5f
 
d65f0be
0f2840d
14c7d5f
 
 
 
 
 
 
 
 
cee3d2a
 
 
 
14c7d5f
d65f0be
14c7d5f
 
d65f0be
14c7d5f
 
 
 
d65f0be
14c7d5f
d65f0be
14c7d5f
d65f0be
14c7d5f
 
 
 
 
d65f0be
cee3d2a
 
 
d65f0be
 
 
 
 
 
 
 
 
 
 
 
14c7d5f
 
 
 
 
 
 
 
cee3d2a
14c7d5f
 
 
cee3d2a
14c7d5f
 
 
 
ee9e957
cee3d2a
 
 
14c7d5f
cee3d2a
14c7d5f
 
cee3d2a
14c7d5f
cee3d2a
14c7d5f
 
cee3d2a
14c7d5f
 
 
cee3d2a
14c7d5f
ee9e957
cee3d2a
 
14c7d5f
 
ee9e957
 
 
14c7d5f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ee9e957
14c7d5f
 
ee9e957
14c7d5f
 
 
 
 
 
0f2840d
 
14c7d5f
0f2840d
14c7d5f
 
 
 
 
 
0f2840d
 
14c7d5f
 
0f2840d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
from flask import Flask, send_file, request, abort
from PIL import Image, ImageDraw, ImageFont, ImageFilter, ImageEnhance
from io import BytesIO
from datetime import datetime
import os
import requests
import math

app = Flask(__name__)

def download_font(url, filename):
    """Download font from URL if it doesn't exist locally"""
    if not os.path.exists(filename):
        try:
            response = requests.get(url)
            response.raise_for_status()
            with open(filename, 'wb') as f:
                f.write(response.content)
            return True
        except:
            return False
    return True

def get_text_dimensions(text, font):
    """Get text dimensions using the new textbbox method"""
    bbox = font.getbbox(text)
    width = bbox[2] - bbox[0]
    height = bbox[3] - bbox[1]
    return width, height

def create_gradient_background(width, height, start_color, end_color):
    """Create a beautiful gradient background"""
    gradient = Image.new('RGB', (width, height), start_color)
    draw = ImageDraw.Draw(gradient)
    
    for y in range(height):
        # Calculate the blend ratio
        ratio = y / height
        
        # Interpolate between start and end colors
        r = int(start_color[0] * (1 - ratio) + end_color[0] * ratio)
        g = int(start_color[1] * (1 - ratio) + end_color[1] * ratio)
        b = int(start_color[2] * (1 - ratio) + end_color[2] * ratio)
        
        draw.line([(0, y), (width, y)], fill=(r, g, b))
    
    return gradient

def add_glow_effect(img, text, font, position, color, glow_radius=3):
    """Add a glow effect to text"""
    # Create a larger image for the glow
    glow_img = Image.new('RGBA', (img.width + glow_radius * 4, img.height + glow_radius * 4), (0, 0, 0, 0))
    glow_draw = ImageDraw.Draw(glow_img)
    
    # Draw the text multiple times with slight offsets for glow
    glow_x = position[0] + glow_radius * 2
    glow_y = position[1] + glow_radius * 2
    
    for offset_x in range(-glow_radius, glow_radius + 1):
        for offset_y in range(-glow_radius, glow_radius + 1):
            if offset_x != 0 or offset_y != 0:
                alpha = max(0, 100 - int(math.sqrt(offset_x**2 + offset_y**2) * 30))
                glow_color = (*color[:3], alpha)
                glow_draw.text((glow_x + offset_x, glow_y + offset_y), text, font=font, fill=glow_color)
    
    # Apply blur to the glow
    glow_img = glow_img.filter(ImageFilter.GaussianBlur(radius=1))
    
    # Composite the glow with the original image
    img_rgba = img.convert('RGBA')
    combined = Image.alpha_composite(img_rgba, glow_img.crop((glow_radius * 2, glow_radius * 2, 
                                                             glow_img.width - glow_radius * 2, 
                                                             glow_img.height - glow_radius * 2)))
    
    return combined.convert('RGB')

def add_embossed_effect(draw, text, font, position, color, shadow_color):
    """Add an embossed/3D effect to text"""
    x, y = position
    
    # Draw bigger shadow (offset down and right) - scale with font size
    shadow_offset = 6
    draw.text((x + shadow_offset, y + shadow_offset), text, font=font, fill=shadow_color)
    
    # Draw highlight (offset up and left)
    highlight_color = tuple(min(255, c + 60) for c in color)
    highlight_offset = 3
    draw.text((x - highlight_offset, y - highlight_offset), text, font=font, fill=highlight_color)
    
    # Draw main text
    draw.text((x, y), text, font=font, fill=color)

@app.route('/generate', methods=['GET'])
def generate_card():
    # Get code from query string
    code = request.args.get("code")
    if not code:
        return abort(400, description="Missing ?code= parameter")
    
    # Format the code with hyphens every 4 characters
    code = code.replace("-", "").upper()
    formatted_code = '-'.join([code[i:i+4] for i in range(0, len(code), 4)])
    
    # Create card dimensions
    card_width, card_height = 1200, 750
    
    # Try to load background image, otherwise create gradient
    try:
        img = Image.open("image.png").convert("RGB")
        img = img.resize((card_width, card_height), Image.Resampling.LANCZOS)
        
        # Enhance the background image
        enhancer = ImageEnhance.Contrast(img)
        img = enhancer.enhance(1.2)
        
        enhancer = ImageEnhance.Color(img)
        img = enhancer.enhance(1.1)
        
    except FileNotFoundError:
        # Create a stunning gradient background
        img = create_gradient_background(
            card_width, card_height,
            start_color=(15, 32, 68),    # Deep navy blue
            end_color=(45, 12, 35)       # Deep purple
        )
        
        # Add some texture/noise
        overlay = Image.new('RGBA', (card_width, card_height), (0, 0, 0, 0))
        overlay_draw = ImageDraw.Draw(overlay)
        
        # Add subtle geometric patterns
        for i in range(0, card_width, 100):
            for j in range(0, card_height, 100):
                overlay_draw.rectangle([i, j, i+2, j+2], fill=(255, 255, 255, 20))
        
        img = Image.alpha_composite(img.convert('RGBA'), overlay).convert('RGB')
    
    draw = ImageDraw.Draw(img)
    
    # Initialize fonts with defaults first
    code_font = ImageFont.load_default()
    timestamp_font = ImageFont.load_default()
    title_font = ImageFont.load_default()
    fonts_loaded = False
    
    # Try to load premium fonts
    try:
        # Try to download Google Fonts
        font_urls = {
            'orbitron_bold.ttf': 'https://github.com/google/fonts/raw/main/ofl/orbitron/Orbitron-Bold.ttf',
            'roboto_mono.ttf': 'https://github.com/google/fonts/raw/main/apache/robotomono/RobotoMono-Regular.ttf'
        }
        
        for filename, url in font_urls.items():
            download_font(url, filename)
        
        # Load the downloaded fonts with ULTRA MASSIVE code size for 16:9 aspect ratio
        code_font = ImageFont.truetype('orbitron_bold.ttf', 350)
        timestamp_font = ImageFont.truetype('roboto_mono.ttf', 52)
        title_font = ImageFont.truetype('orbitron_bold.ttf', 75)
        fonts_loaded = True
        print("✅ Premium fonts loaded successfully!")
        
    except Exception as e:
        print(f"⚠️ Premium font loading failed: {e}")
        # Fallback to system fonts
        try:
            system_fonts = [
                "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
                "/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf",
                "/System/Library/Fonts/Helvetica.ttc",
                "/System/Library/Fonts/Arial.ttf",
                "C:\\Windows\\Fonts\\arial.ttf",
                "C:\\Windows\\Fonts\\calibri.ttf",
                "arial.ttf"
            ]
            
            for font_path in system_fonts:
                if os.path.exists(font_path):
                    try:
                        code_font = ImageFont.truetype(font_path, 350)
                        timestamp_font = ImageFont.truetype(font_path, 52)
                        title_font = ImageFont.truetype(font_path, 75)
                        fonts_loaded = True
                        print(f"✅ System font loaded: {font_path}")
                        break
                    except Exception as font_error:
                        print(f"❌ Failed to load {font_path}: {font_error}")
                        continue
                        
        except Exception as system_error:
            print(f"⚠️ System font loading failed: {system_error}")
            print("📝 Using default fonts")
    
    print(f"🎨 Fonts loaded: {'Premium' if fonts_loaded else 'Default'}")
    
    # Enhanced color scheme
    primary_color = (0, 255, 136)      # Bright green
    secondary_color = (255, 215, 0)     # Gold
    accent_color = (64, 224, 255)       # Sky blue
    text_color = (240, 240, 240)        # Light gray
    shadow_color = (20, 20, 20)         # Dark shadow
    
    # Add title with better positioning for huge code
    title_text = "DIGITAL ACCESS CARD"
    title_width, title_height = get_text_dimensions(title_text, title_font)
    title_x = (card_width - title_width) // 2
    title_y = 40
    
    # Add embossed effect to title
    add_embossed_effect(draw, title_text, title_font, (title_x, title_y), secondary_color, shadow_color)
    
    # Add bigger decorative lines around title
    line_y = title_y + title_height + 25
    draw.rectangle([60, line_y, card_width - 60, line_y + 8], fill=primary_color)
    draw.rectangle([100, line_y + 15, card_width - 100, line_y + 18], fill=accent_color)
    
    # Position ULTRA MASSIVE code in center (NO CONTAINER!)
    code_width, code_height = get_text_dimensions(formatted_code, code_font)
    code_x = (card_width - code_width) // 2
    code_y = (card_height - code_height) // 2 - 20  # Slight adjustment for better balance
    
    # Add ULTRA MASSIVE embossed effect directly to code (no background container)
    add_embossed_effect(draw, formatted_code, code_font, (code_x, code_y), primary_color, shadow_color)
    
    # Add timestamp with better positioning for massive code
    timestamp = datetime.now().strftime("Generated: %Y-%m-%d %H:%M:%S UTC")
    ts_width, ts_height = get_text_dimensions(timestamp, timestamp_font)
    ts_x = (card_width - ts_width) // 2
    ts_y = code_y + code_height + 60
    
    # Add bigger subtle background for timestamp
    ts_bg_coords = [ts_x - 30, ts_y - 18, ts_x + ts_width + 30, ts_y + ts_height + 18]
    draw.rectangle(ts_bg_coords, fill=(0, 0, 0, 60))
    draw.text((ts_x, ts_y), timestamp, font=timestamp_font, fill=text_color)
    
    # Add bigger corner decorations
    corner_size = 80
    corner_thickness = 8
    
    # Top-left corner
    draw.rectangle([20, 20, 20 + corner_size, 20 + corner_thickness], fill=accent_color)
    draw.rectangle([20, 20, 20 + corner_thickness, 20 + corner_size], fill=accent_color)
    
    # Top-right corner
    draw.rectangle([card_width - 20 - corner_size, 20, card_width - 20, 20 + corner_thickness], fill=accent_color)
    draw.rectangle([card_width - 20 - corner_thickness, 20, card_width - 20, 20 + corner_size], fill=accent_color)
    
    # Bottom-left corner
    draw.rectangle([20, card_height - 20 - corner_thickness, 20 + corner_size, card_height - 20], fill=accent_color)
    draw.rectangle([20, card_height - 20 - corner_size, 20 + corner_thickness, card_height - 20], fill=accent_color)
    
    # Bottom-right corner
    draw.rectangle([card_width - 20 - corner_size, card_height - 20 - corner_thickness, card_width - 20, card_height - 20], fill=accent_color)
    draw.rectangle([card_width - 20 - corner_thickness, card_height - 20 - corner_size, card_width - 20, card_height - 20], fill=accent_color)
    
    # Add bigger serial number
    serial = f"SN: {datetime.now().strftime('%Y%m%d%H%M%S')}"
    serial_width, serial_height = get_text_dimensions(serial, timestamp_font)
    draw.text((card_width - serial_width - 40, card_height - serial_height - 40), 
              serial, font=timestamp_font, fill=(150, 150, 150))
    
    # Apply final enhancement
    enhancer = ImageEnhance.Sharpness(img)
    img = enhancer.enhance(1.1)
    
    # Return image in memory
    buffer = BytesIO()
    img.save(buffer, format="PNG", quality=95, optimize=True)
    buffer.seek(0)
    
    return send_file(buffer, mimetype="image/png", as_attachment=False, download_name="premium_access_card.png")

@app.route('/health', methods=['GET'])
def health_check():
    return {"status": "healthy", "timestamp": datetime.now().isoformat()}

if __name__ == '__main__':
    print("🚀 Premium Card Generator Starting...")
    print("📱 Access your cards at: http://localhost:7860/generate?code=YOUR_CODE")
    app.run(host='0.0.0.0', port=7860, debug=True)