Skip to content

Transformation URL API

MediaMatic provides a powerful URL-based image transformation API that allows you to resize, crop, convert formats, and optimize images on-the-fly using URL parameters. This API is designed to compete with services like Cloudinary while giving you complete control over your media pipeline.

Overview

Instead of pre-generating multiple image sizes and formats, you can request transformed images directly via URL parameters. MediaMatic will process the image on-demand and cache the result for subsequent requests.

Key Benefits:

  • 🚀 On-Demand Processing - Generate image variants as needed
  • 💰 Cost Effective - No vendor lock-in, run on your infrastructure
  • Fast - Intelligent caching with CDN support
  • 🌐 Browser-Aware - Automatically serve optimal formats (AVIF, WebP, JPEG)
  • 🎨 Flexible - Extensive transformation options
  • 📱 Responsive - Device pixel ratio support for retina displays

Quick Start

Basic Usage

Transform an image using the /transform endpoint:

Original:
GET /api/mm/fs/default/files/products/shoe.jpg

Transformed (400x300, WebP format):
GET /api/mm/fs/default/transform/w_400,h_300,f_webp/products/shoe.jpg

Common Examples

bash
# Thumbnail (200x200, cover crop)
GET /transform/w_200,h_200,c_cover,q_auto,f_auto/products/shoe.jpg

# Responsive image (16:9, fit to width)
GET /transform/w_1920,ar_16:9,c_fit,q_85,f_webp/hero.jpg

# Retina display (2x DPR)
GET /transform/w_400,h_400,dpr_2,f_png/logo.png

# Browser-optimized (auto format selection)
GET /transform/w_800,c_fit,q_auto,f_auto/gallery/photo.jpg

URL Structure

Endpoint Format

GET /api/mm/fs/{filesourceId}/transform/{transformations}/{*filePath}

Components:

  • {filesourceId} - Your filesource identifier (e.g., "default", "s3", "cdn")
  • {transformations} - Comma-separated transformation parameters (e.g., "w_400,h_300,c_fill")
  • {*filePath} - Path to the original file (e.g., "products/shoe.jpg")

Why transformations before path? This prevents conflicts with user folder names (like "t", "meta", "transform") and keeps the catch-all parameter at the end of the URL where ASP.NET Core routing requires it.

With Buckets (S3/Azure)

For storage providers that support buckets:

GET /api/mm/fs/{filesourceId}/bu/{bucketName}/transform/{transformations}/{*filePath}

Example:

GET /api/mm/fs/s3-prod/bu/media-assets/transform/w_1920,h_1080,c_fill,f_webp/images/hero.jpg

Transformation Parameters

Dimensions

Width (w_)

Set the target width in pixels.

w_400           - Width of 400 pixels
w_1920          - Width of 1920 pixels

Height (h_)

Set the target height in pixels.

h_300           - Height of 300 pixels
h_1080          - Height of 1080 pixels

Aspect Ratio (ar_)

Set the aspect ratio (width:height or decimal).

ar_16:9         - 16:9 aspect ratio (widescreen)
ar_4:3          - 4:3 aspect ratio (standard)
ar_1:1          - 1:1 aspect ratio (square)
ar_1.5          - 1.5 aspect ratio (decimal notation)

Note: When using ar_ with only w_ or h_, the missing dimension is calculated automatically.

Examples:

bash
# Width 1920, height calculated for 16:9
GET /transform/w_1920,ar_16:9
/hero.jpg

# Height 1080, width calculated for 16:9
GET /transform/h_1080,ar_16:9
/hero.jpg

# Square thumbnail, width 300
GET /transform/w_300,ar_1:1
/thumbnail.jpg

Device Pixel Ratio (dpr_)

Multiply dimensions for high-density displays (retina).

dpr_1           - Standard density [default]
dpr_2           - 2x density (retina displays)
dpr_3           - 3x density (some mobile devices)

Example:

bash
# Request 400x300, but receive 800x600 for retina
GET /transform/w_400,h_300,dpr_2,f_png
/logo.png

Crop Modes (c_)

Control how the image is resized when aspect ratio doesn't match.

c_fit           - Fit within bounds (letterbox/pillarbox) [default]
c_fill          - Fill bounds (crop excess) - alias for cover
c_cover         - Cover entire area (crop excess, no empty space)
c_pad           - Pad to exact dimensions (add background)
c_stretch       - Stretch to exact dimensions (ignore aspect ratio)
c_scale         - Alias for fit
c_thumb         - Thumbnail mode (optimized for small sizes)

c_fit (Letterbox/Pillarbox)

Resize to fit within bounds while preserving aspect ratio. May result in empty space.

bash
# Landscape image to portrait bounds
GET /transform/w_400,h_600,c_fit
/landscape.jpg
# Result: Image is 400x267, centered vertically with empty space

c_fill / c_cover (Crop to Fill)

Resize to completely fill bounds, cropping excess content.

bash
# Portrait image to square
GET /transform/w_400,h_400,c_fill
/portrait.jpg
# Result: Image is 400x400, cropped from center

c_pad (Add Background)

Resize to fit, then pad to exact dimensions with background color.

bash
# Add white padding to landscape image
GET /transform/w_600,h_600,c_pad,bg_ffffff
/landscape.jpg
# Result: Image is 600x600 with white bars top/bottom

c_stretch (Distort)

Stretch image to exact dimensions, ignoring aspect ratio.

bash
# Stretch to specific dimensions
GET /transform/w_800,h_400,c_stretch
/image.jpg
# Result: Image may appear distorted

Gravity / Focal Point (g_)

Control which part of the image to keep when cropping (used with c_fill, c_cover, c_thumb).

Named Gravity

g_center        - Center of image [default]
g_north         - Top center
g_south         - Bottom center
g_east          - Right center
g_west          - Left center
g_northeast     - Top right
g_northwest     - Top left
g_southeast     - Bottom right
g_southwest     - Bottom left

Examples:

bash
# Crop to top of image
GET /transform/w_400,h_400,c_fill,g_north
/portrait.jpg

# Crop to bottom-right corner
GET /transform/w_600,h_400,c_fill,g_southeast
/landscape.jpg

Custom Focal Point (g_xy)

Use x_ and y_ parameters to specify exact focal point (0.0 to 1.0).

g_xy            - Enable custom focal point
x_0.3           - X focal point: 30% from left
y_0.4           - Y focal point: 40% from top

Coordinate System:

  • x_0.0 = Left edge, x_1.0 = Right edge
  • y_0.0 = Top edge, y_1.0 = Bottom edge
  • x_0.5,y_0.5 = Center (equivalent to g_center)

Examples:

bash
# Focus on face in portrait (30% from left, 40% from top)
GET /transform/w_400,h_400,c_fill,g_xy,x_0.3,y_0.4
/portrait.jpg

# Focus on product in corner (70% from left, 60% from top)
GET /transform/w_600,h_600,c_cover,g_xy,x_0.7,y_0.6
/product.jpg

Quality (q_)

Control image compression quality (0-100).

q_auto          - Auto optimize quality based on format
q_100           - Maximum quality (largest file size)
q_85            - High quality [recommended for most images]
q_80            - Good quality (good balance)
q_70            - Economy quality (smaller files)
q_best          - Alias for 100
q_good          - Alias for 85
q_eco           - Alias for 70

Quality Guidelines:

  • JPEG: 80-90 for photos, 70 for thumbnails
  • WebP: 85-95 (better compression than JPEG)
  • AVIF: 80-90 (best compression)
  • PNG: Quality parameter ignored (lossless)

Examples:

bash
# Auto-optimize based on format
GET /transform/w_800,q_auto,f_auto
/photo.jpg

# High quality JPEG
GET /transform/w_1920,q_90,f_jpeg
/photo.jpg

# Economy quality for thumbnails
GET /transform/w_200,h_200,q_70,f_jpeg
/thumb.jpg

Format Conversion (f_)

Convert images to different formats.

f_auto          - Auto select format based on Accept header
f_jpeg          - Convert to JPEG
f_jpg           - Alias for JPEG
f_png           - Convert to PNG
f_webp          - Convert to WebP (better compression than JPEG)
f_avif          - Convert to AVIF (best compression, modern browsers)
f_bmp           - Convert to BMP
f_gif           - Convert to GIF

f_auto - Browser-Aware Format Selection

MediaMatic automatically detects browser capabilities and serves the optimal format:

Format Priority:

  1. AVIF - Newest browsers (Chrome 85+, Firefox 93+, Safari 16+)
  2. WebP - Modern browsers (Chrome, Firefox, Edge, Opera)
  3. JPEG/PNG - Legacy browsers and fallback

Detection Method:

  • Parses Accept header from browser
  • Uses DeviceDetector.NET for User-Agent analysis
  • Falls back to original format if no better option

Example:

bash
# Same URL returns different formats based on browser
GET /transform/w_800,f_auto
/photo.jpg

# Chrome 100: Returns AVIF (smallest)
# Safari 15: Returns WebP
# IE 11: Returns JPEG (original format)

Format Comparison

FormatCompressionQualityTransparencyBrowser SupportUse Case
AVIFBestExcellentModernNew sites, progressive enhancement
WebPVery GoodExcellentModernWide compatibility
JPEGGoodGoodUniversalPhotos, maximum compatibility
PNGLosslessPerfectUniversalGraphics, logos, transparency
BMPNonePerfectUniversalUncompressed (large files)
GIFGoodLimitedUniversalAnimations, simple graphics

Background Color (bg_)

Set background color for c_pad mode or transparent areas.

bg_ffffff       - White background (hex RGB)
bg_000000       - Black background
bg_ff0000       - Red background
bg_00ff00       - Green background
bg_0000ff       - Blue background
bg_transparent  - Transparent background (PNG/WebP/AVIF only)

Format: 6-character hex RGB (without # prefix).

Examples:

bash
# Pad with white background
GET /transform/w_600,h_600,c_pad,bg_ffffff,f_png
/logo.png

# Pad with black background
GET /transform/ar_16:9,w_1920,c_pad,bg_000000,f_jpeg
/image.jpg

# Keep transparency (PNG/WebP/AVIF)
GET /transform/w_400,h_400,c_pad,bg_transparent,f_webp
/logo.png

Metadata Handling (m_)

Control whether to strip or preserve image metadata (EXIF, GPS, etc.).

m_keep          - Keep all metadata [default for non-optimized]
m_strip         - Strip all metadata (EXIF, GPS, camera info)

Why Strip Metadata?

  • Privacy - Remove GPS coordinates, camera info, timestamps
  • File Size - EXIF data can add 50-500KB to file size
  • Security - Prevent leaking sensitive information

Examples:

bash
# Strip metadata for privacy
GET /transform/w_800,q_80,m_strip,f_jpeg
/user-upload.jpg

# Keep metadata for archival
GET /transform/w_1920,q_90,m_keep,f_jpeg
/professional-photo.jpg

Effects (e_) - Coming Soon

Note: Effects are planned for Phase 3 implementation.

e_grayscale     - Convert to grayscale
e_sepia         - Apply sepia tone effect
e_blur_10       - Blur with radius 10
e_sharpen_5     - Sharpen with amount 5
e_brightness_20 - Adjust brightness (+/- 100)
e_contrast_15   - Adjust contrast (+/- 100)
e_saturation_-30 - Adjust saturation (+/- 100)

Cache Control (v_)

Version identifier for cache busting.

v_1             - Version 1
v_20250124      - Date-based version
v_abc123        - Git commit hash

Example:

bash
# Original request (cached by browser/CDN)
GET /transform/w_400,f_png,v_1
/logo.png

# Update logo, increment version to bust cache
GET /transform/w_400,f_png,v_2
/logo.png

Query Parameters

Force Download (download)

Force the browser to download the transformed image instead of displaying it inline:

bash
# Display image inline (default)
GET /transform/w_800,f_webp/photo.jpg

# Force download
GET /transform/w_800,f_webp/photo.jpg?download=true

Save Transformed Result (saveTo)

Save the transformed image to a specific path for caching/pre-generation:

bash
# Transform and save to thumbs folder
GET /transform/w_400,f_webp/images/photo.jpg?saveTo=thumbs/photo_400.webp

Behavior:

  • Transforms the image
  • Saves to the specified path (overwrites if exists)
  • Returns the transformed image

POST Transform Endpoints (CMS Pre-Generation)

For CMS workflows where you want to pre-generate thumbnails without streaming the image back, use the POST endpoints. These return metadata instead of the image, making them more efficient for batch operations.

Single Transform

POST /api/mm/fs/{filesourceId}/transform/{transformations}/{*filePath}

Request Body:

json
{
  "saveTo": "thumbs/photo_400.webp"
}

Response (201 Created):

json
{
  "path": "thumbs/photo_400.webp",
  "size": 12345,
  "width": 400,
  "height": 300,
  "format": "webp",
  "success": true
}

Example:

bash
curl -X POST "https://example.com/api/mm/fs/default/transform/w_400,h_300,f_webp/images/photo.jpg" \
  -H "Content-Type: application/json" \
  -d '{"saveTo": "thumbs/photo_400x300.webp"}'

Batch Transform

Generate multiple variants of a source image in one request:

POST /api/mm/fs/{filesourceId}/transform-batch/

Request Body:

json
{
  "source": "images/photo.jpg",
  "variants": [
    { "transformations": "w_400,f_webp", "saveTo": "thumbs/photo_400.webp" },
    { "transformations": "w_800,f_webp", "saveTo": "thumbs/photo_800.webp" },
    { "transformations": "w_1200,f_webp", "saveTo": "thumbs/photo_1200.webp" },
    { "transformations": "w_200,h_200,c_cover,f_webp", "saveTo": "thumbs/photo_square.webp" }
  ]
}

Response (201 Created):

json
{
  "results": [
    { "path": "thumbs/photo_400.webp", "size": 12345, "width": 400, "height": 300, "format": "webp", "success": true },
    { "path": "thumbs/photo_800.webp", "size": 34567, "width": 800, "height": 600, "format": "webp", "success": true },
    { "path": "thumbs/photo_1200.webp", "size": 56789, "width": 1200, "height": 900, "format": "webp", "success": true },
    { "path": "thumbs/photo_square.webp", "size": 8901, "width": 200, "height": 200, "format": "webp", "success": true }
  ]
}

CMS Pre-Generation Workflow

A typical CMS workflow for handling image uploads:

1. User uploads original image
   POST /api/mm/fs/default/files/images/photo.jpg

2. CMS generates all required variants
   POST /api/mm/fs/default/transform-batch/
   Body: {
     "source": "images/photo.jpg",
     "variants": [
       { "transformations": "w_400,f_webp", "saveTo": "thumbs/photo_400.webp" },
       { "transformations": "w_800,f_webp", "saveTo": "thumbs/photo_800.webp" },
       { "transformations": "w_200,h_200,c_cover,f_webp", "saveTo": "thumbs/photo_square.webp" }
     ]
   }

3. Website serves pre-generated files directly (no runtime processing)
   GET /api/mm/fs/default/files/thumbs/photo_400.webp

4. When source image changes, CMS re-runs batch transform with same paths

Benefits:

  • No runtime processing overhead for end users
  • Consistent thumbnail generation across deployments
  • Easy to regenerate all variants when source changes
  • Metadata response allows CMS to track file sizes and dimensions

Complete Examples

Responsive Image Set

Generate a complete set of responsive images:

bash
# Mobile (small)
GET /transform/w_640,ar_16:9,c_fill,q_80,f_auto
/hero.jpg

# Tablet (medium)
GET /transform/w_1024,ar_16:9,c_fill,q_85,f_auto
/hero.jpg

# Desktop (large)
GET /transform/w_1920,ar_16:9,c_fill,q_85,f_auto
/hero.jpg

# Desktop Retina (2x)
GET /transform/w_1920,ar_16:9,c_fill,q_85,f_auto,dpr_2
/hero.jpg

Product Thumbnails

bash
# Square thumbnail (centered crop)
GET /transform/w_300,h_300,c_cover,g_center,q_80,f_webp/products/shoe.jpg

# Square thumbnail (custom focal point)
GET /transform/w_300,h_300,c_cover,g_xy,x_0.6,y_0.4,q_80,f_webp/products/shoe.jpg

Profile Avatars

bash
# Square avatar (200x200)
GET /transform/w_200,h_200,c_cover,g_north,q_85,f_webp,m_strip/avatars/user123.jpg

# Retina avatar (400x400 actual pixels)
GET /transform/w_200,h_200,c_cover,g_north,q_85,f_webp,m_strip,dpr_2/avatars/user123.jpg

Hero Images

bash
# Full-width hero (16:9)
GET /transform/w_1920,ar_16:9,c_fill,g_center,q_90,f_auto
/hero.jpg

# Ultra-wide hero (21:9)
GET /transform/w_2560,ar_21:9,c_fill,g_center,q_90,f_auto
/hero.jpg

Logo with Padding

bash
# Logo on white background (square)
GET /transform/w_400,h_400,c_pad,bg_ffffff,f_png/logos/brand.png

# Logo on transparent background
GET /transform/w_400,h_400,c_pad,bg_transparent,f_webp/logos/brand.png

Privacy-Conscious User Uploads

bash
# Strip all metadata, optimize
GET /transform/w_1200,c_fit,q_80,f_jpeg,m_strip/user-photos/vacation.jpg

Integration Examples

HTML <img> Tags

html
<!-- Basic responsive image -->
<img src="/api/mm/fs/default/transform/w_800,c_fit,q_auto,f_auto/products/shoe.jpg"
     alt="Product"
     width="800"
     height="600">

<!-- Retina-ready image -->
<img src="/api/mm/fs/default/transform/w_200,h_200,dpr_2,f_png/logo.png"
     alt="Logo"
     width="200"
     height="200">

HTML <picture> Element

html
<picture>
  <!-- Modern browsers: AVIF -->
  <source srcset="/api/mm/fs/default/transform/w_1920,ar_16:9,c_fill,f_avif/hero.jpg"
          type="image/avif">

  <!-- Modern browsers: WebP -->
  <source srcset="/api/mm/fs/default/transform/w_1920,ar_16:9,c_fill,f_webp/hero.jpg"
          type="image/webp">

  <!-- Fallback: JPEG -->
  <img src="/api/mm/fs/default/transform/w_1920,ar_16:9,c_fill,f_jpeg/hero.jpg"
       alt="Hero Image">
</picture>

Responsive Images with srcset

html
<img
  src="/api/mm/fs/default/transform/w_800,c_fit,q_auto,f_auto/product.jpg"
  srcset="
    /api/mm/fs/default/transform/w_400,c_fit,q_auto,f_auto/product.jpg 400w,
    /api/mm/fs/default/transform/w_800,c_fit,q_auto,f_auto/product.jpg 800w,
    /api/mm/fs/default/transform/w_1200,c_fit,q_auto,f_auto/product.jpg 1200w,
    /api/mm/fs/default/transform/w_1600,c_fit,q_auto,f_auto/product.jpg 1600w
  "
  sizes="(max-width: 600px) 400px,
         (max-width: 1200px) 800px,
         1200px"
  alt="Product Image">

CSS Background Images

css
/* Standard display */
.hero {
  background-image: url('/api/mm/fs/default/transform/w_1920,ar_16:9,c_fill,q_85,f_auto/hero.jpg');
}

/* Retina display */
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
  .hero {
    background-image: url('/api/mm/fs/default/transform/w_1920,ar_16:9,c_fill,q_85,f_auto,dpr_2/hero.jpg');
  }
}

React/Next.js Image Component

jsx
import Image from 'next/image';

function ProductImage({ src, alt }) {
  const baseUrl = '/api/mm/fs/default';

  const buildTransformUrl = (path, transforms) =>
    `${baseUrl}/transform/${transforms}/${path}`;

  return (
    <Image
      src={buildTransformUrl(src, 'w_800,c_fit,q_auto,f_auto')}
      alt={alt}
      width={800}
      height={600}
      srcSet={`
        ${buildTransformUrl(src, 'w_400,c_fit,q_auto,f_auto')} 400w,
        ${buildTransformUrl(src, 'w_800,c_fit,q_auto,f_auto')} 800w,
        ${buildTransformUrl(src, 'w_1200,c_fit,q_auto,f_auto')} 1200w
      `}
    />
  );
}

Caching & Performance

HTTP Caching Headers

MediaMatic automatically sets appropriate cache headers:

http
HTTP/1.1 200 OK
Content-Type: image/webp
Cache-Control: public, max-age=31536000, immutable
ETag: "abc123def456"
Last-Modified: Mon, 20 Jan 2025 12:00:00 GMT

Header Explanation:

  • Cache-Control: public, max-age=31536000, immutable - Cache for 1 year (transformed images don't change)
  • ETag - Fingerprint for cache validation
  • Last-Modified - Timestamp for conditional requests

Conditional Requests

MediaMatic supports efficient cache validation:

http
# First request
GET /transform/w_800,f_webp
/photo.jpg
→ 200 OK (full response)

# Subsequent request with ETag
GET /transform/w_800,f_webp
/photo.jpg
If-None-Match: "abc123def456"
→ 304 Not Modified (no body, saves bandwidth)

# Or with Last-Modified
GET /transform/w_800,f_webp
/photo.jpg
If-Modified-Since: Mon, 20 Jan 2025 12:00:00 GMT
→ 304 Not Modified

Server-Side Caching

MediaMatic caches transformed images on disk to avoid re-processing:

Cache Location: ./cache/transformations/{filesourceId}/{filePath}/{transformations}.{ext}

Example:
./cache/transformations/default/products/shoe.jpg/w_400,h_300,c_fill,q_80,f_webp.webp

Cache Configuration:

csharp
builder.Services.AddMediaMatic(options =>
{
    options.TransformationCache = new TransformationCacheSettings
    {
        Enabled = true,
        CacheDirectory = "./cache/transformations",
        MaxCacheSizeBytes = 10_000_000_000, // 10GB
        CacheExpiration = TimeSpan.FromDays(30),
    };
});

CDN Integration

Transformation URLs are CDN-friendly:

Cloudflare:

Cache Everything Page Rule:
  URL Pattern: /api/mm/fs/*/transform/*/*
  Cache Level: Cache Everything
  Edge Cache TTL: 1 month

AWS CloudFront:

json
{
  "PathPattern": "/api/mm/fs/*/transform/*/*",
  "TargetOriginId": "MediaMaticOrigin",
  "ViewerProtocolPolicy": "redirect-to-https",
  "CachePolicyId": "658327ea-f89d-4fab-a63d-7e88639e58f6",
  "Compress": true
}

Cache Key Optimization:

  • Include Accept header in cache key for f_auto
  • Normalize transformation order (MediaMatic does this automatically)
  • Strip unnecessary query parameters

Best Practices

1. Use f_auto for Browser-Aware Serving

Let MediaMatic automatically choose the best format:

bash
# ✅ Good: Auto format selection
GET /transform/w_800,c_fit,q_auto,f_auto
/photo.jpg

# ❌ Avoid: Hardcoding format
GET /transform/w_800,c_fit,q_auto,f_jpeg
/photo.jpg

2. Use q_auto for Quality Optimization

Let MediaMatic optimize quality based on format:

bash
# ✅ Good: Auto quality
GET /transform/w_800,f_auto,q_auto
/photo.jpg

# ❌ Avoid: Fixed quality across formats
GET /transform/w_800,f_auto,q_80
/photo.jpg

3. Generate Responsive Image Sets

Provide multiple sizes for different screen sizes:

html
<img
  src="/transform/w_800,c_fit,q_auto,f_auto"
  srcset="
    /transform/w_400,c_fit,q_auto,f_auto 400w,
    /transform/w_800,c_fit,q_auto,f_auto 800w,
    /transform/w_1200,c_fit,q_auto,f_auto 1200w,
    /transform/w_1600,c_fit,q_auto,f_auto 1600w
  "
  sizes="(max-width: 600px) 400px,
         (max-width: 1200px) 800px,
         1200px"
  alt="Hero">

4. Use Retina Images Sparingly

Only use dpr_2 for critical images (logos, UI elements):

bash
# ✅ Good: Logo (small, visible quality difference)
GET /transform/w_200,h_200,dpr_2,f_png
/logo.png

# ⚠️ Caution: Hero image (large, minimal quality difference)
GET /transform/w_1920,h_1080,dpr_2,f_jpeg/hero.jpg  # Results in 3840x2160!

5. Strip Metadata for User Uploads

Protect user privacy by stripping metadata:

bash
# ✅ Good: Strip metadata from user uploads
GET /transform/w_1200,c_fit,q_80,m_strip,f_jpeg/user-photos/vacation.jpg

# ❌ Avoid: Keeping metadata (may expose GPS, camera info)
GET /transform/w_1200,c_fit,q_80,f_jpeg/user-photos/vacation.jpg

6. Use Appropriate Crop Modes

Choose the right crop mode for your use case:

bash
# Product photos: Fit entire product (may have empty space)
GET /transform/w_600,h_600,c_fit,bg_ffffff/products/shoe.jpg

# Thumbnails: Fill entire area (crop excess)
GET /transform/w_300,h_300,c_cover,g_center/products/shoe.jpg

# Banners: Fill width, specific aspect ratio
GET /transform/w_1920,ar_16:9,c_fill,g_center/banners/sale.jpg

7. Use Version Parameters for Cache Busting

When images change, increment version to force cache refresh:

bash
# Original
GET /transform/w_400,f_png,v_1
/logo.png

# Update logo.png on server, then increment version
GET /transform/w_400,f_png,v_2
/logo.png

8. Optimize for Perceived Performance

Load critical images first, lazy-load below-the-fold images:

html
<!-- Above the fold: Load immediately -->
<img src="/transform/w_1920,ar_16:9,c_fill,f_auto,q_auto"
     alt="Hero"
     loading="eager">

<!-- Below the fold: Lazy load -->
<img src="/transform/w_400,c_fit,f_auto,q_auto"
     alt="Product"
     loading="lazy">

Comparison to Cloudinary

MediaMatic's transformation API is designed to be familiar to Cloudinary users while offering some advantages:

FeatureCloudinaryMediaMaticNotes
URL Syntax/image/upload/w_400,h_300,c_fill/.../fi/{path}/t/w_400,h_300,c_fillSimilar parameter style
Auto Formatf_autof_auto✅ Same behavior
Crop ModesMultiplefit, fill, cover, pad, stretch✅ All common modes
Qualityq_auto, q_80q_auto, q_80✅ Same
Gravityg_center, g_faceg_center, g_xy (custom)⚠️ No face detection (yet)
DPRdpr_2dpr_2✅ Same
EffectsManyComing soon⏳ Grayscale, blur, sharpen planned
Cost$89-249+/monthSelf-hosted (free)💰 Significant savings
Data OwnershipCloudinaryYour infrastructure✅ Full control
CDNIncludedBring your own⚠️ Requires CDN setup
Face Detection❌ (planned)🔮 Future with ML.NET
Video Transforms⏳ (thumbnails available)📋 Transcode via separate endpoint

Migration from Cloudinary

If you're migrating from Cloudinary, most URLs can be adapted with minimal changes:

Cloudinary:

https://res.cloudinary.com/demo/image/upload/w_400,h_300,c_fill,q_auto,f_auto/sample.jpg

MediaMatic:

https://yourdomain.com/api/mm/fs/default/transform/w_400,h_300,c_fill,q_auto,f_auto/sample.jpg

Common Parameter Mapping:

  • w_w_ ✅ Same
  • h_h_ ✅ Same
  • c_fillc_fill ✅ Same
  • c_scalec_fit ⚠️ Different name
  • g_faceg_xy,x_0.5,y_0.4 ⚠️ Manual focal point (no face detection yet)
  • q_autoq_auto ✅ Same
  • f_autof_auto ✅ Same

Troubleshooting

Image Not Transforming

Problem: Original image is returned instead of transformed version.

Solutions:

  1. Check transformation syntax: w_400 not w=400
  2. Verify file path is correct
  3. Check filesource ID exists
  4. Ensure image format is supported (JPEG, PNG, WebP, AVIF, BMP, GIF)

Poor Image Quality

Problem: Transformed images appear pixelated or blurry.

Solutions:

  1. Check original image resolution (can't upscale beyond original quality)
  2. Increase quality: q_85 or q_90
  3. Use f_auto to let MediaMatic choose optimal format
  4. Avoid excessive upscaling (keep dpr_ reasonable)

Slow First Request

Problem: First request for transformation is slow.

Explanation: MediaMatic processes on-demand. First request generates and caches the image.

Solutions:

  1. Pre-warm cache for critical images
  2. Use CDN with long cache times
  3. Consider pre-generating common sizes on upload

404 Not Found

Problem: Transformed image returns 404.

Solutions:

  1. Verify original file exists: GET /transform/...) /{path}(without
  2. Check filesource ID is correct
  3. Verify bucket name (if using S3/Azure)
  4. Check file permissions

Browser Shows Wrong Format

Problem: f_auto not working, always returns JPEG.

Solutions:

  1. Check browser sends Accept: image/webp,image/avif,*/* header
  2. Verify User-Agent is not blocked
  3. Test with f_webp explicitly to confirm format conversion works
  4. Clear browser cache

Advanced Topics

URL Signing (Coming Soon)

Prevent unauthorized transformations with signed URLs:

bash
# Unsigned (anyone can generate transformations)
GET /transform/w_800,f_webp
/photo.jpg

# Signed (requires secret key)
GET /transform/w_800,f_webp?s=abc123def456&e=1706198400
/photo.jpg

Named Transformations (Coming Soon)

Define preset transformations for consistency:

csharp
// Configuration
builder.Services.AddMediaMatic(options =>
{
    options.NamedTransformations.Add("thumbnail", "w_300,h_300,c_cover,g_center,q_80,f_auto");
    options.NamedTransformations.Add("hero", "w_1920,ar_16:9,c_fill,g_center,q_90,f_auto");
});
bash
# Use named transformation
GET /transform/preset_thumbnail
/photo.jpg
GET /transform/preset_hero
/banner.jpg

Chained Transformations (Coming Soon)

Apply multiple transformation steps sequentially:

bash
# First: Resize, Second: Apply blur, Third: Convert format
GET /transform/w_1200,h_800,c_fill/t/e_blur_5/t/q_80,f_webp
/image.jpg

API Reference Summary

Quick Parameter Reference

# Dimensions
w_400                 - Width (pixels)
h_300                 - Height (pixels)
ar_16:9               - Aspect ratio (width:height or decimal)
dpr_2                 - Device pixel ratio (retina)

# Crop Modes
c_fit                 - Fit within bounds [default]
c_fill / c_cover      - Fill bounds (crop excess)
c_pad                 - Pad to exact dimensions (add background)
c_stretch             - Stretch to exact dimensions (distort)

# Gravity / Focal Point
g_center              - Center crop [default]
g_north / g_south     - Top / Bottom
g_east / g_west       - Right / Left
g_northeast, etc.     - Corners
g_xy,x_0.3,y_0.4      - Custom focal point (0.0-1.0)

# Quality
q_auto                - Auto optimize [recommended]
q_80                  - Quality 0-100
q_best / q_good / q_eco - Presets (100 / 85 / 70)

# Format
f_auto                - Auto format (AVIF > WebP > JPEG) [recommended]
f_webp / f_avif       - Specific formats
f_jpeg / f_png        - Legacy formats

# Other
bg_ffffff             - Background color (hex RGB, for c_pad)
m_strip               - Strip metadata (EXIF, GPS)
m_keep                - Keep metadata [default]
v_1                   - Version (cache busting)

See Also


Ready to transform your images? Start with the Getting Started guide to set up MediaMatic!