Claude
Skills
Sign in
Back

image-optimization

Included with Lifetime
$97 forever

Use when implementing responsive images, format conversion, focal point cropping, or image processing pipelines. Covers srcset generation, WebP/AVIF conversion, lazy loading, and image transformation APIs for headless CMS.

Ads & Marketing

What this skill does


# Image Optimization

Guidance for implementing responsive images, format optimization, and image processing pipelines for headless CMS.

## When to Use This Skill

- Implementing responsive image delivery
- Converting images to modern formats (WebP, AVIF)
- Building image processing pipelines
- Implementing focal point cropping
- Optimizing image loading performance

## Responsive Image Patterns

### Srcset for Resolution Switching

```html
<!-- Basic srcset with width descriptors -->
<img
  src="/images/hero.jpg"
  srcset="
    /images/hero-400w.jpg 400w,
    /images/hero-800w.jpg 800w,
    /images/hero-1200w.jpg 1200w,
    /images/hero-1600w.jpg 1600w
  "
  sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 800px"
  alt="Hero image"
>

<!-- Srcset with pixel density -->
<img
  src="/images/logo.png"
  srcset="
    /images/logo.png 1x,
    /images/[email protected] 2x,
    /images/[email protected] 3x
  "
  alt="Logo"
>
```

### Picture Element for Art Direction

```html
<picture>
  <!-- Mobile: Square crop -->
  <source
    media="(max-width: 600px)"
    srcset="/images/hero-mobile.webp"
    type="image/webp"
  >
  <source
    media="(max-width: 600px)"
    srcset="/images/hero-mobile.jpg"
  >

  <!-- Desktop: Wide crop -->
  <source
    srcset="/images/hero-desktop.webp"
    type="image/webp"
  >

  <!-- Fallback -->
  <img src="/images/hero-desktop.jpg" alt="Hero">
</picture>
```

## Image Processing Service

### Core Processing

```csharp
public class ImageProcessingService
{
    public async Task<Stream> ProcessAsync(
        Stream source,
        ImageProcessingOptions options)
    {
        using var image = await Image.LoadAsync(source);

        // Resize
        if (options.Width.HasValue || options.Height.HasValue)
        {
            var resizeOptions = new ResizeOptions
            {
                Size = new Size(
                    options.Width ?? 0,
                    options.Height ?? 0),
                Mode = options.ResizeMode,
                Position = options.FocalPoint != null
                    ? CalculateAnchor(options.FocalPoint, image.Size)
                    : AnchorPositionMode.Center
            };

            image.Mutate(x => x.Resize(resizeOptions));
        }

        // Apply effects
        if (options.Blur > 0)
        {
            image.Mutate(x => x.GaussianBlur(options.Blur));
        }

        if (options.Grayscale)
        {
            image.Mutate(x => x.Grayscale());
        }

        // Encode to target format
        var outputStream = new MemoryStream();
        await EncodeAsync(image, outputStream, options);

        outputStream.Position = 0;
        return outputStream;
    }

    private async Task EncodeAsync(
        Image image,
        Stream output,
        ImageProcessingOptions options)
    {
        switch (options.Format)
        {
            case ImageFormat.WebP:
                await image.SaveAsWebpAsync(output, new WebpEncoder
                {
                    Quality = options.Quality,
                    Method = WebpEncodingMethod.BestQuality
                });
                break;

            case ImageFormat.Avif:
                await image.SaveAsAvifAsync(output, new AvifEncoder
                {
                    Quality = options.Quality
                });
                break;

            case ImageFormat.Jpeg:
                await image.SaveAsJpegAsync(output, new JpegEncoder
                {
                    Quality = options.Quality,
                    ColorType = JpegEncodingColor.YCbCrRatio420
                });
                break;

            case ImageFormat.Png:
                await image.SaveAsPngAsync(output, new PngEncoder
                {
                    CompressionLevel = PngCompressionLevel.BestCompression
                });
                break;
        }
    }
}

public class ImageProcessingOptions
{
    public int? Width { get; set; }
    public int? Height { get; set; }
    public ResizeMode ResizeMode { get; set; } = ResizeMode.Max;
    public FocalPoint? FocalPoint { get; set; }
    public ImageFormat Format { get; set; } = ImageFormat.WebP;
    public int Quality { get; set; } = 80;
    public float Blur { get; set; }
    public bool Grayscale { get; set; }
}

public class FocalPoint
{
    public float X { get; set; } // 0-1, left to right
    public float Y { get; set; } // 0-1, top to bottom
}

public enum ImageFormat
{
    Jpeg,
    Png,
    WebP,
    Avif,
    Gif
}
```

### Preset-Based Processing

```csharp
public class ImagePresets
{
    public static readonly Dictionary<string, ImageProcessingOptions> Presets = new()
    {
        ["thumbnail"] = new()
        {
            Width = 150,
            Height = 150,
            ResizeMode = ResizeMode.Crop,
            Format = ImageFormat.WebP,
            Quality = 75
        },
        ["card"] = new()
        {
            Width = 400,
            Height = 300,
            ResizeMode = ResizeMode.Crop,
            Format = ImageFormat.WebP,
            Quality = 80
        },
        ["hero"] = new()
        {
            Width = 1920,
            Height = 800,
            ResizeMode = ResizeMode.Crop,
            Format = ImageFormat.WebP,
            Quality = 85
        },
        ["og-image"] = new()
        {
            Width = 1200,
            Height = 630,
            ResizeMode = ResizeMode.Crop,
            Format = ImageFormat.Jpeg,
            Quality = 90
        },
        ["blur-placeholder"] = new()
        {
            Width = 20,
            Height = 20,
            Format = ImageFormat.Jpeg,
            Quality = 30,
            Blur = 5
        }
    };
}
```

## Focal Point Cropping

### Focal Point Model

```csharp
public class FocalPointService
{
    public AnchorPositionMode CalculateAnchor(
        FocalPoint focal,
        Size imageSize,
        Size targetSize)
    {
        // Calculate which part of image will be cropped
        var imageAspect = (float)imageSize.Width / imageSize.Height;
        var targetAspect = (float)targetSize.Width / targetSize.Height;

        if (Math.Abs(imageAspect - targetAspect) < 0.01f)
        {
            return AnchorPositionMode.Center;
        }

        // Determine crop direction
        var cropHorizontal = imageAspect > targetAspect;

        if (cropHorizontal)
        {
            // Cropping sides, use X focal point
            return focal.X switch
            {
                < 0.33f => AnchorPositionMode.Left,
                > 0.66f => AnchorPositionMode.Right,
                _ => AnchorPositionMode.Center
            };
        }
        else
        {
            // Cropping top/bottom, use Y focal point
            return focal.Y switch
            {
                < 0.33f => AnchorPositionMode.Top,
                > 0.66f => AnchorPositionMode.Bottom,
                _ => AnchorPositionMode.Center
            };
        }
    }
}
```

### Storing Focal Point

```csharp
public class MediaItem
{
    public Guid Id { get; set; }
    public string FileName { get; set; } = string.Empty;

    // Focal point for smart cropping
    public FocalPoint? FocalPoint { get; set; }
}

// Set via API
PATCH /api/media/{id}
{
  "focalPoint": { "x": 0.3, "y": 0.2 }
}
```

## On-the-Fly Image Transformation

### URL-Based Transformation

```text
# Base URL
https://cdn.example.com/media/hero.jpg

# With transformations
https://cdn.example.com/media/hero.jpg?w=800&h=600&fit=crop
https://cdn.example.com/media/hero.jpg?w=400&format=webp&q=80
https://cdn.example.com/media/hero.jpg?preset=thumbnail
```

### Transformation Endpoint

```csharp
[Route("media/{*path}")]
public class ImageTransformController : ControllerBase
{
    [HttpGet]
    [ResponseCache(Duration = 31536000, VaryByQueryKeys = new[] { "*" })]
    public async Task<IActionResult> GetTransformed(
        string path,
        [FromQuery] int? w,
        [FromQuery] int? h,
        [FromQuery] string? format,
        [FromQuer

Related in Ads & Marketing