Contents

sirv/sirv-image-swift

A Swift package for building [Sirv](https://sirv.com) image transformation URLs using a fluent builder pattern.

Requirements

  • Swift 5.7+
  • Any platform supported by Swift (macOS, iOS, tvOS, watchOS, Linux)

Installation

Swift Package Manager

Add to your Package.swift:

dependencies: [
    .package(url: "https://github.com/sirv/sirv-image-transformation.git", from: "1.0.0")
]

Then add "SirvImage" to your target's dependencies.

Quick Start

import SirvImage

let url = SirvImage(url: "https://demo.sirv.com/photo.jpg")
    .resize(width: 400, height: 300)
    .format(.webp)
    .quality(80)
    .toUrl()
// https://demo.sirv.com/photo.jpg?w=400&h=300&format=webp&q=80

Initialization

// From a full URL
let img = SirvImage(url: "https://demo.sirv.com/photo.jpg")

// From base URL + path
let img = SirvImage(baseUrl: "https://demo.sirv.com", path: "/photo.jpg")

Existing query parameters are preserved:

let img = SirvImage(url: "https://demo.sirv.com/photo.jpg?profile=my-preset")
    .width(400)
    .toUrl()
// https://demo.sirv.com/photo.jpg?profile=my-preset&w=400

URL Output

// Explicit
let url: String = img.toUrl()

// Via CustomStringConvertible
print("URL: \(img)")

API Reference

Resize

.resize(width: 400, height: 300)
.resize(width: 400, height: 300, option: .fill)
.width(400)
.height(300)
.scaleByLongest(800)
.thumbnail(150)

ResizeOption values: .fill, .fitWidth, .fitHeight, .force, .ignore

Crop

.crop(width: 200, height: 200, x: 50, y: 50)
.crop(width: 300, height: 300, type: .face)
.crop(width: 200, height: 200, type: .trim, padWidth: 10, padHeight: 10)
.clipPath("circle(50%)")

CropType values: .fill, .face, .trim

Rotation

.rotate(90)
.flip()    // vertical
.flop()    // horizontal

Format

.format(.webp)
.quality(80)
.webpFallback("jpg")
.subsampling(.s420)
.pngOptimize()
.gifLossy(80)

ImageFormat values: .jpg, .png, .webp, .gif, .bmp, .tiff, .original

Subsampling values: .s420, .s422, .s444

Color Adjustments

.brightness(10)       // -100 to 100
.contrast(15)         // -100 to 100
.exposure(5)          // -100 to 100
.hue(30)              // -360 to 360
.saturation(-20)      // -100 to 100
.lightness(10)        // -100 to 100
.shadows(20)          // -100 to 100
.highlights(-10)      // -100 to 100
.grayscale()
.colorLevel(black: 10, white: 245)
.histogram(.rgb)

Color Effects

// Preset colortone
.colortone("sepia")

// Custom colortone
.colortone(color: "ff6600", level: 50, mode: .highlights)

// Colorize
.colorize(color: "ff0000", opacity: 50)

ColortoneMode values: .solid, .highlights, .shadows

Effects

.blur(5)
.sharpen(3)
.vignette(value: 50, color: "000000")
.opacity(75)

Text Overlays

.text("Hello World", options: TextOptions(
    fontSize: 32,
    fontFamily: "Arial",
    fontWeight: .bold,
    color: "ffffff",
    position: .center
))

Multiple text layers are supported -- each .text() call adds a new layer:

.text("Title", options: TextOptions(fontSize: 48, position: .north))
.text("Subtitle", options: TextOptions(fontSize: 24, position: .south))

TextOptions fields:

| Field | Type | Description | |-------|------|-------------| | size | Int? | Text box size | | fontSize | Int? | Font size in pixels | | fontFamily | String? | Font family name | | fontStyle | FontStyle? | .normal, .italic | | fontWeight | FontWeight? | .normal, .bold, .w100....w900 | | color | String? | Text color (hex) | | opacity | Int? | Text opacity (0-100) | | outlineWidth | Int? | Outline width | | outlineColor | String? | Outline color (hex) | | outlineOpacity | Int? | Outline opacity (0-100) | | outlineBlur | Int? | Outline blur radius | | backgroundColor | String? | Background color (hex) | | backgroundOpacity | Int? | Background opacity (0-100) | | align | TextAlign? | .left, .center, .right | | position | Position? | Position preset | | positionX | Int? | Horizontal offset | | positionY | Int? | Vertical offset | | positionGravity | PositionGravity? | Gravity for position offset |

Watermarks

.watermark("/logo.png", options: WatermarkOptions(
    position: .southEast,
    opacity: 50,
    scaleWidth: 200
))

Multiple watermarks are supported -- each .watermark() call adds a new layer:

.watermark("/logo.png", options: WatermarkOptions(position: .northWest))
.watermark("/badge.png", options: WatermarkOptions(position: .southEast))

WatermarkOptions fields:

| Field | Type | Description | |-------|------|-------------| | position | Position? | Position preset | | positionX | Int? | Horizontal offset | | positionY | Int? | Vertical offset | | positionGravity | PositionGravity? | Gravity for position offset | | scaleWidth | Int? | Scale to width | | scaleHeight | Int? | Scale to height | | scaleOption | WatermarkScaleOption? | .fit, .fill, .ignore, .noup | | rotate | Int? | Rotation angle | | opacity | Int? | Opacity (0-100) | | layer | WatermarkLayer? | .overlay, .background | | canvasColor | String? | Canvas color (hex) | | canvasOpacity | Int? | Canvas opacity (0-100) | | canvasWidth | Int? | Canvas width | | canvasHeight | Int? | Canvas height | | cropX | Int? | Crop X offset | | cropY | Int? | Crop Y offset | | cropWidth | Int? | Crop width | | cropHeight | Int? | Crop height |

Canvas

.canvas(CanvasOptions(
    width: 500,
    height: 400,
    color: "f0f0f0",
    position: .center
))

CanvasOptions fields: width, height, color, opacity, position, positionX, positionY, positionGravity

Frame

.frame(FrameOptions(
    style: "solid",
    color: "333333",
    width: 10
))

FrameOptions fields: style, color, width, rimColor, rimWidth

Other

.page(3)           // multi-page document page selection
.profile("srgb")   // ICC profile

Method Chaining

All transformation methods return Self, enabling fluent chaining:

let url = SirvImage(url: "https://demo.sirv.com/photo.jpg")
    .resize(width: 800, option: .fill)
    .crop(width: 400, height: 400, type: .face)
    .format(.webp)
    .quality(85)
    .brightness(5)
    .sharpen(2)
    .watermark("/logo.png", options: WatermarkOptions(
        position: .southEast,
        opacity: 30
    ))
    .toUrl()

Running Tests

cd swift
swift test

License

MIT

Package Metadata

Repository: sirv/sirv-image-swift

Default branch: main

README: README.md