Image Applications
This document covers practical image applications including QR code generation and image compression.
QR Code Generation
Generate and visualize QR codes using the qrcode library.
QR Code Video Explanation
Installation
Basic Usage
import matplotlib.pyplot as plt
import qrcode
def main():
# Make QR code image
img = qrcode.make('https://www.youtube.com/watch?v=03qMfonukno')
# Save QR code image as jpg
img.save('YouTubeQRCode.jpg')
# Show QR code image
fig, ax = plt.subplots()
ax.imshow(img, cmap='binary')
ax.axis('off')
plt.show()
if __name__ == "__main__":
main()
QR Code Content Types
URL
url_qr = qrcode.make('https://www.example.com')
Text
text_qr = qrcode.make('Hello, World! This is a QR code.')
vcard = """BEGIN:VCARD
VERSION:3.0
N:Doe;John
FN:John Doe
ORG:Example Inc.
TEL:+1234567890
EMAIL:john.doe@example.com
END:VCARD"""
vcard_qr = qrcode.make(vcard)
WiFi Connection
# WiFi QR code format: WIFI:T:WPA;S:NetworkName;P:Password;;
wifi_config = "WIFI:T:WPA;S:MyWiFiNetwork;P:MyPassword;;"
wifi_qr = qrcode.make(wifi_config)
Advanced QR Code Generation
import matplotlib.pyplot as plt
import qrcode
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=10,
border=4,
)
qr.add_data('https://www.example.com')
qr.make(fit=True)
img = qr.make_image(fill_color="black", back_color="white")
fig, ax = plt.subplots()
ax.imshow(img, cmap='binary')
ax.axis('off')
plt.show()
Error Correction Levels
| Level |
Constant |
Recovery |
| L |
ERROR_CORRECT_L |
~7% |
| M |
ERROR_CORRECT_M |
~15% |
| Q |
ERROR_CORRECT_Q |
~25% |
| H |
ERROR_CORRECT_H |
~30% |
import matplotlib.pyplot as plt
import qrcode
data = 'https://www.example.com'
fig, axes = plt.subplots(1, 4, figsize=(16, 4))
corrections = [
(qrcode.constants.ERROR_CORRECT_L, 'L (~7%)'),
(qrcode.constants.ERROR_CORRECT_M, 'M (~15%)'),
(qrcode.constants.ERROR_CORRECT_Q, 'Q (~25%)'),
(qrcode.constants.ERROR_CORRECT_H, 'H (~30%)')
]
for ax, (level, name) in zip(axes, corrections):
qr = qrcode.QRCode(error_correction=level, box_size=10, border=2)
qr.add_data(data)
qr.make(fit=True)
img = qr.make_image()
ax.imshow(img, cmap='binary')
ax.set_title(f'Error Correction: {name}')
ax.axis('off')
plt.tight_layout()
plt.show()
Custom Colors
import matplotlib.pyplot as plt
import qrcode
qr = qrcode.QRCode(box_size=10, border=2)
qr.add_data('https://www.example.com')
qr.make(fit=True)
colors = [
("black", "white"),
("darkblue", "lightyellow"),
("darkgreen", "lightgray"),
("darkred", "white")
]
fig, axes = plt.subplots(1, 4, figsize=(16, 4))
for ax, (fill, back) in zip(axes, colors):
img = qr.make_image(fill_color=fill, back_color=back)
ax.imshow(img)
ax.set_title(f'{fill} on {back}')
ax.axis('off')
plt.tight_layout()
plt.show()
Business Card QR Example
import matplotlib.pyplot as plt
import qrcode
contact_info = """BEGIN:VCARD
VERSION:3.0
N:Smith;Jane
FN:Jane Smith
TITLE:Software Engineer
ORG:Tech Company
TEL;TYPE=WORK:+1-555-123-4567
EMAIL:jane.smith@techcompany.com
URL:https://janesmith.dev
END:VCARD"""
qr = qrcode.QRCode(
error_correction=qrcode.constants.ERROR_CORRECT_H,
box_size=10,
border=4
)
qr.add_data(contact_info)
qr.make(fit=True)
img = qr.make_image(fill_color="#2c3e50", back_color="white")
fig, ax = plt.subplots(figsize=(6, 6))
ax.imshow(img)
ax.set_title('Scan for Contact Info', fontsize=14, fontweight='bold')
ax.axis('off')
plt.tight_layout()
plt.show()
Image Compression
Understanding image compression techniques and their effects on image quality.
Compression Types
| Type |
Description |
Formats |
Use Case |
| Lossless |
No data loss |
PNG, BMP, TIFF |
Graphics, screenshots |
| Lossy |
Some data discarded |
JPEG, WebP |
Photos, web images |
JPEG Quality Comparison
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
import io
# Load original image
img = Image.open('image.jpg')
# Save at different quality levels
qualities = [10, 30, 50, 70, 90]
compressed_images = []
for q in qualities:
buffer = io.BytesIO()
img.save(buffer, format='JPEG', quality=q)
buffer.seek(0)
compressed_images.append(Image.open(buffer))
# Display comparison
fig, axes = plt.subplots(1, 5, figsize=(20, 4))
for ax, comp_img, q in zip(axes, compressed_images, qualities):
ax.imshow(comp_img)
ax.set_title(f'Quality: {q}')
ax.axis('off')
plt.tight_layout()
plt.show()
File Size vs Quality
import matplotlib.pyplot as plt
from PIL import Image
import io
img = Image.open('image.jpg')
qualities = range(10, 101, 10)
sizes = []
for q in qualities:
buffer = io.BytesIO()
img.save(buffer, format='JPEG', quality=q)
sizes.append(len(buffer.getvalue()) / 1024) # KB
fig, ax = plt.subplots(figsize=(10, 6))
ax.plot(qualities, sizes, 'bo-', linewidth=2, markersize=8)
ax.set_xlabel('JPEG Quality')
ax.set_ylabel('File Size (KB)')
ax.set_title('JPEG Quality vs File Size')
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
Compression Artifacts
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
import io
# Create image with sharp edges (prone to artifacts)
gradient = np.zeros((100, 200, 3), dtype=np.uint8)
gradient[:, :100] = [255, 0, 0] # Red
gradient[:, 100:] = [0, 0, 255] # Blue
img = Image.fromarray(gradient)
# Heavy compression
buffer = io.BytesIO()
img.save(buffer, format='JPEG', quality=5)
buffer.seek(0)
compressed = Image.open(buffer)
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
axes[0].imshow(img)
axes[0].set_title('Original')
axes[0].axis('off')
axes[1].imshow(compressed)
axes[1].set_title('JPEG Quality=5 (Artifacts visible)')
axes[1].axis('off')
plt.tight_layout()
plt.show()
Generational Loss
import matplotlib.pyplot as plt
from PIL import Image
import io
def recompress_jpeg(img, quality, generations):
"""Simulate multiple JPEG saves (generational loss)."""
current = img
for _ in range(generations):
buffer = io.BytesIO()
current.save(buffer, format='JPEG', quality=quality)
buffer.seek(0)
current = Image.open(buffer)
return current
img = Image.open('image.jpg')
generations = [1, 5, 10, 20]
fig, axes = plt.subplots(1, 4, figsize=(16, 4))
for ax, gen in zip(axes, generations):
degraded = recompress_jpeg(img.copy(), quality=70, generations=gen)
ax.imshow(degraded)
ax.set_title(f'{gen} generations')
ax.axis('off')
plt.suptitle('JPEG Generational Loss (Quality=70)', fontsize=14)
plt.tight_layout()
plt.show()
import matplotlib.pyplot as plt
from PIL import Image
import io
img = Image.open('image.png').convert('RGB')
formats = {
'JPEG (Q=85)': ('JPEG', {'quality': 85}),
'JPEG (Q=50)': ('JPEG', {'quality': 50}),
'PNG': ('PNG', {}),
'WebP (Q=85)': ('WEBP', {'quality': 85})
}
results = {}
for name, (fmt, kwargs) in formats.items():
buffer = io.BytesIO()
img.save(buffer, format=fmt, **kwargs)
size_kb = len(buffer.getvalue()) / 1024
buffer.seek(0)
results[name] = (Image.open(buffer), size_kb)
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
for ax, (name, (comp_img, size)) in zip(axes.flat, results.items()):
ax.imshow(comp_img)
ax.set_title(f'{name}\n{size:.1f} KB')
ax.axis('off')
plt.tight_layout()
plt.show()
Matplotlib Save Compression
import matplotlib.pyplot as plt
import numpy as np
# Create sample plot
fig, ax = plt.subplots(figsize=(8, 6))
x = np.linspace(0, 10, 100)
ax.plot(x, np.sin(x), 'b-', linewidth=2)
ax.set_title('Sample Plot')
# Save with different settings
fig.savefig('plot_low.jpg', dpi=72, quality=50)
fig.savefig('plot_high.jpg', dpi=150, quality=95)
fig.savefig('plot.png', dpi=150)
plt.show()
| Content Type |
Recommended Format |
Reason |
| Photographs |
JPEG (Q=80-90) |
Good compression, acceptable loss |
| Screenshots |
PNG |
Sharp edges preserved |
| Graphics/Logos |
PNG or SVG |
No artifacts |
| Web photos |
WebP |
Best compression ratio |
| Scientific figures |
PDF/SVG |
Vector, scalable |
Quality Recommendations
| Quality Range |
Description |
| 90-100 |
Maximum quality, large files |
| 80-90 |
High quality, good for printing |
| 60-80 |
Good quality, web standard |
| 40-60 |
Medium quality, smaller files |
| 20-40 |
Low quality, thumbnails |
| 1-20 |
Very low, visible artifacts |
Image Optimization Workflow
import matplotlib.pyplot as plt
from PIL import Image
import io
import os
def optimize_image(input_path, output_path, max_size_kb=100, min_quality=30):
"""Optimize image to target file size."""
img = Image.open(input_path)
# Convert to RGB if necessary
if img.mode in ('RGBA', 'P'):
img = img.convert('RGB')
# Binary search for quality
low, high = min_quality, 95
best_quality = high
while low <= high:
mid = (low + high) // 2
buffer = io.BytesIO()
img.save(buffer, format='JPEG', quality=mid)
size_kb = len(buffer.getvalue()) / 1024
if size_kb <= max_size_kb:
best_quality = mid
low = mid + 1
else:
high = mid - 1
# Save with best quality
img.save(output_path, format='JPEG', quality=best_quality)
final_size = os.path.getsize(output_path) / 1024
return best_quality, final_size
# Usage
quality, size = optimize_image('large_image.jpg', 'optimized.jpg', max_size_kb=200)
print(f"Optimized to quality={quality}, size={size:.1f}KB")
Summary
QR Code Quick Reference
import qrcode
# Simple QR
img = qrcode.make('data')
# Advanced QR
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_H,
box_size=10,
border=4
)
qr.add_data('data')
qr.make(fit=True)
img = qr.make_image(fill_color="black", back_color="white")
Compression Quick Reference
from PIL import Image
import io
# JPEG compression
img.save('output.jpg', format='JPEG', quality=85)
# PNG compression
img.save('output.png', format='PNG', compress_level=6)
# In-memory compression
buffer = io.BytesIO()
img.save(buffer, format='JPEG', quality=70)