image-processing
Image processing and manipulation
Source facts
- Repository
- ffsshhttiikk/opencode-agents-skills
- Last source activity
- February 28, 2026 at 22:51
- Detected SKILL.md language
- English
- Stars
- 3
- Forks
- 2
Install options
The review-first prompt is selected by default. You can switch to a direct command or download a local copy.
Review the source files
Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.
Showing SKILL.md
SKILL.md
Source instructions · Read-only preview- name
- image-processing
- description
- Image processing and manipulation
- license
- MIT
- compatibility
- opencode
- metadata
- {"audience":"developers","category":"utilities"}
## What I do
- Resize and transform images
- Handle image formats
- Optimize image quality
- Generate thumbnails
- Extract image metadata
- Apply filters and effects
- Handle image uploads securely
- Serve optimized images
## When to use me
When implementing image processing or handling image uploads.
## Image Processing Basics
```python
from PIL import Image, ImageFilter, ImageEnhance
from dataclasses import dataclass
from pathlib import Path
from typing import Optional, List, Tuple
import io
@dataclass
class ImageDimensions:
"""Image dimensions."""
width: int
height: int
@property
def aspect_ratio(self) -> float:
return self.width / self.height
def resize(self, max_width: int, max_height: int) -> 'ImageDimensions':
"""Resize while maintaining aspect ratio."""
ratio = min(max_width / self.width, max_height / self.height)
return ImageDimensions(
width=int(self.width * ratio),
height=int(self.height * ratio)
)
@dataclass
class ImageConfig:
"""Image processing configuration."""
format: str = "JPEG"
quality: int = 85
optimize: bool = True
preserve_metadata: bool = False
class ImageProcessor:
"""Image processing operations."""
def __init__(self, config: ImageConfig = None):
self.config = config or ImageConfig()
def open(self, image_path: Path) -> Image:
"""Open an image file."""
return Image.open(image_path)
def resize(
self,
image: Image,
width: int,
height: int,
maintain_aspect: bool = True
) -> Image:
"""Resize image."""
if maintain_aspect:
current_dims = ImageDimensions(image.width, image.height)
new_dims = current_dims.resize(width, height)
width, height = new_dims.width, new_dims.height
return image.resize((width, height), Image.LANCZOS)
def create_thumbnail(
self,
image: Image,
max_size: Tuple[int, int] = (300, 300)
) -> Image:
"""Create thumbnail preserving aspect ratio."""
image.thumbnail(max_size, Image.LANCZOS)
return image
def crop(
self,
image: Image,
left: int,
top: int,
right: int,
bottom: int
) -> Image:
"""Crop image."""
return image.crop((left, top, right, bottom))
def rotate(self, image: Image, degrees: float) -> Image:
"""Rotate image."""
return image.rotate(-degrees, expand=True)
def flip_horizontal(self, image: Image) -> Image:
"""Flip image horizontally."""
return image.transpose(Image.FLIP_LEFT_RIGHT)
def flip_vertical(self, image: Image) -> Image:
"""Flip image vertically."""
return image.transpose(Image.FLIP_TOP_BOTTOM)
class ImageFilterApplier:
"""Apply filters to images."""
@staticmethod
def blur(image: Image, radius: float = 2) -> Image:
"""Apply Gaussian blur."""
return image.filter(ImageFilter.GaussianBlur(radius))
@staticmethod
def sharpen(image: Image) -> Image:
"""Sharpen image."""
return image.filter(ImageFilter.SHARPEN)
@staticmethod
def contour(image: Image) -> Image:
"""Apply contour filter."""
return image.filter(ImageFilter.CONTOUR)
@staticmethod
def edge_enhance(image: Image) -> Image:
"""Edge enhancement."""
return image.filter(ImageFilter.EDGE_ENHANCE)
@staticmethod
def emboss(image: Image) -> Image:
"""Apply emboss effect."""
return image.filter(ImageFilter.EMBOSS)
@staticmethod
def adjust_brightness(image: Image, factor: float) -> Image:
"""Adjust brightness."""
enhancer = ImageEnhance.Brightness(image)
return enhancer.enhance(factor)
@staticmethod
def adjust_contrast(image: Image, factor: float) -> Image:
"""Adjust contrast."""
enhancer = ImageEnhance.Contrast(image)
return enhancer.enhance(factor)
@staticmethod
def adjust_saturation(image: Image, factor: float) -> Image:
"""Adjust saturation."""
enhancer = ImageEnhance.Color(image)
return enhancer.enhance(factor)
class ImageOptimizer:
"""Optimize images for web."""
def __init__(self, config: ImageConfig = None):
self.config = config or ImageConfig()
def optimize(
self,
image: Image,
output_format: str = None
) -> Image:
"""Optimize image."""
format = output_format or self.config.format
if format.upper() == "JPEG":
image = image.convert("RGB")
return image
def save_with_quality(
self,
image: Image,
output_path: Path,
quality: int = None,
format: str = None
) -> None:
"""Save image with specific quality."""
quality = quality or self.config.quality
format = format or self.config.format
save_kwargs = {
"quality": quality,
"optimize": self.config.optimize,
}
if format.upper() == "JPEG":
save_kwargs["subsampling"] = 0
image.save(output_path, format=format, **save_kwargs)
def save_to_bytes(
self,
image: Image,
format: str = None,
quality: int = None
) -> bytes:
"""Save image to bytes."""
format = format or self.config.format
quality = quality or self.config.quality
buffer = io.BytesIO()
save_kwargs = {
"quality": quality,
"optimize": self.config.optimize,
}
image.save(buffer, format=format, **save_kwargs)
return buffer.getvalue()
def create_responsive_set(
self,
image: Image,
sizes: List[Tuple[int, str]],
output_dir: Path,
prefix: str = "image"
) -> List[dict]:
"""Create responsive image set."""
results = []
for width, suffix in sizes:
new_height = int(image.height * (width / image.width))
resized = self.resize(
image,
width,
new_height,
maintain_aspect=True
)
filename = f"{prefix}_{suffix}.jpg"
output_path = output_dir / filename
self.save_with_quality(resized, output_path)
results.append({
"filename": filename,
"width": resized.width,
"height": resized.height,
"url": f"/images/{filename}"
})
return results
```
## Image Upload Handling
```python
from pathlib import Path
from typing import Optional
import magic
import hashlib
class SecureImageUploader:
"""Secure image upload handling."""
ALLOWED_TYPES = {
"image/jpeg": ".jpg",
"image/png": ".png",
"image/gif": ".gif",
"image/webp": ".webp",
}
MAX_SIZE = 10 * 1024 * 1024 # 10MB
def __init__(self, upload_dir: Path, processor: ImageProcessor):
self.upload_dir = upload_dir
self.processor = processor
self.upload_dir.mkdir(parents=True, exist_ok=True)
async def save_upload(
self,
file_content: bytes,
original_filename: str
) -> dict:
"""Save uploaded image securely."""
# Validate file type
mime_type = magic.from_buffer(file_content, mime=True)
if mime_type not in self.ALLOWED_TYPES:
raise InvalidImageError(
f"Invalid file type: {mime_type}"
)
# Validate size
if len(file_content) > self.MAX_SIZE:
raise InvalidImageError(
f"File too large: {len(file_content)} bytes"
)
# Generate safe filename
ext = self.ALLOWED_TYPES[mime_type]
safe_filename = self._generate_safe_filename(original_filename, ext)
file_path = self.upload_dir / safe_filename
# Save file
file_path.write_bytes(file_content)
# Process image
image = self.processor.open(file_path)
# Create thumbnail
thumbnail = self.processor.create_thumbnail(image)
thumbnail_path = self.upload_dir / f"thumb_{safe_filename}"
self.processor.save_with_quality(thumbnail, thumbnail_path)
return {
"original": str(file_path),
"thumbnail": str(thumbnail_path),
"filename": safe_filename,
"width": image.width,
"height": image.height,
"size": len(file_content),
"type": mime_type,
}
def _generate_safe_filename(
self,
original_filename: str,
extension: str
) -> str:
"""Generate safe, unique filename."""
# Get base name
stem = Path(original_filename).stem
# Sanitize
safe_stem = "".join(
c for c in stem
if c.isalnum() or c in "-_"
)
safe_stem = safe_stem[:50] # Limit length
# Add hash for uniqueness
hash_suffix = hashlib.md5(
f"{original_filename}{datetime.utcnow().isoformat()}".encode()
).hexdigest()[:8]
return f"{safe_stem}_{hash_suffix}{extension}"
```
## Image Analysis
```python
from PIL import ImageDraw, ImageFont
from collections import Counter
class ImageAnalyzer:
"""Analyze image properties."""
@staticmethod
def get_dimensions(image: Image) -> Tuple[int, int]:
"""Get image dimensions."""
return image.width, image.height
@staticmethod
def get_format(image: Image) -> str:
"""Get image format."""
return image.format or "Unknown"
@staticmethod
def get_mode(image: Image) -> str:
"""Get image mode (RGB, L, etc.)."""
return image.mode
@staticmethod
def get_info(image: Image) -> dict:
"""Get comprehensive image info."""
return {
"format": image.format,
"mode": image.mode,
"width": image.width,
"height": image.height,
"size_bytes": image.size[0] * image.size[1],
"has_alpha": image.mode in ("RGBA", "LA", "P"),
"aspect_ratio": image.width / image.height if image.height else 0,
}
@staticmethod
def get_color_histogram(image: Image) -> dict:
"""Get color histogram."""
if image.mode != "RGB":
image = image.convert("RGB")
colors = list(image.getdata())
color_counts = Counter(colors)
return {
"unique_colors": len(color_counts),
"top_colors": color_counts.most_common(10),
}
@staticmethod
def is_portrait(image: Image) -> bool:
"""Check if image is portrait orientation."""
return image.height > image.width
@staticmethod
def is_landscape(image: Image) -> bool:
"""Check if image is landscape orientation."""
return image.width > image.height
@staticmethod
def is_square(image: Image) -> bool:
"""Check if image is square."""
return image.width == image.height
@staticmethod
def estimate_quality(image: Image) -> str:
"""Estimate image quality level."""
width = image.width
height = image.height
if width < 300 or height < 300:
return "low"
elif width < 800 or height < 800:
return "medium"
elif width < 2000 or height < 2000:
return "high"
else:
return "very_high"
# Watermark application
class WatermarkApplier:
"""Apply watermarks to images."""
def __init__(self, text: str, font_size: int = 24):
self.text = text
self.font_size = font_size
def add_text_watermark(
self,
image: Image,
position: str = "bottom-right",
opacity: float = 0.5
) -> Image:
"""Add text watermark."""
if image.mode != "RGBA":
image = image.convert("RGBA")
watermark = Image.new("RGBA", image.size, (255, 255, 255, 0))
draw = ImageDraw.Draw(watermark)
# Calculate position
width, height = image.size
if position == "bottom-right":
x = width - 200
y = height - 50
elif position == "bottom-left":
x = 20
y = height - 50
View on GitHubThis SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub