WWDC Quick Look đź’“ By SwiftGGTeam
Create high-quality images using Image Playground

Create high-quality images using Image Playground

Watch original video

Highlight

Apple has moved the Image Playground generation model to Private Cloud Compute, letting developers integrate high-quality image generation into their apps with realistic styles, multiple sizes, custom styles, and visual references based on photos and drawings.

Core Ideas

Integrating AI image generation into an app used to require handling a long list of hard problems: applying for API keys, configuring servers, managing usage limits, building a style picker, and addressing user privacy concerns. Nontechnical users often do not know how to describe the image they want.

Apple packages these capabilities into the ImagePlayground framework. The same experience has already been validated in system apps such as Messages and Freeform, so users know how to use it. Developers only need to add a view modifier to get a complete image generation interface.

The generation model now runs on Private Cloud Compute. That brings a major jump in image quality, including truly realistic photo-style images, while ensuring user data is not stored or shared. From a developer’s point of view, there is no server to maintain, and usage limits are handled automatically by the system.

Details

00:00 Framework overview

The Image Playground framework supports iOS, iPadOS, macOS, and visionOS on devices that support Apple Intelligence. Image generation runs on Apple’s Private Cloud Compute, and user data is not stored or shared.

The framework provides these core capabilities: generating images from text descriptions, supporting scenes with multiple people, offering multiple preset styles such as animation, illustration, sketch, and Genmoji, supporting multiple sizes and aspect ratios such as landscape, portrait, and square, importing people from the photo library, and generating from existing images and sketches.

05:28 SwiftUI integration

Adopting Image Playground in SwiftUI only requires one view modifier:

// Adopt Image Playground in SwiftUI

@State private var showingPlayground = false

var body: some View {
    Button("Create image") {
        showingPlayground = true
    }
    .imagePlaygroundSheet(
        isPresented: $showingPlayground,
        onCompletion: { url in
            var updated = currentCard
            store.saveImage(url, for: &updated)
        }
    )
}

Key points:

  • isPresented is a Binding<Bool> that controls sheet presentation.
  • The onCompletion callback returns the generated image URL. The URL points to a temporary location inside the app container.
  • Save the image somewhere else before the session ends.

06:29 Context seeds

You can provide initial context for the sheet so users do not need to start from a blank prompt:

// Seed the sheet with context from your card

var concepts: [ImagePlaygroundConcept] {
    [
        .text(card.theme),
        .extracted(from: card.message, title: card.theme),
    ]
}

var body: some View {
    Button("Create image") {
        showingPlayground = true
    }
    .imagePlaygroundSheet(
        isPresented: $showingPlayground,
        concepts: concepts,
        onCompletion: { url in
            var updated = card
            store.saveImage(url, for: &updated)
        }
    )
}

Key points:

  • .text() directly wraps a text description.
  • .extracted() extracts the most relevant concepts from longer text.
  • After you pass these into the sheet, they automatically populate the prompt input.

07:11 Generating from a reference image

You can pass in an image as a visual reference:

// Start from a reference photo

@State private var sourceImage: Image?

var body: some View {
    Button("Create image") {
        showingPlayground = true
    }
    .imagePlaygroundSheet(
        isPresented: $showingPlayground,
        concepts: concepts,
        sourceImage: sourceImage,
        onCompletion: { url in
            var updated = card
            store.saveImage(url, for: &updated)
        }
    )
}

Key points:

  • sourceImage accepts any SwiftUI Image.
  • The image acts as visual inspiration, and users can replace or adjust it inside the sheet.
  • This works well when users choose a photo from the library as a starting point.

07:42 Generating from a sketch

With PencilKit, a sketch can guide generation:

// Provide a visual suggestion using a drawing

@State private var drawing = PKDrawing()

var concepts: [ImagePlaygroundConcept] {
    var result: [ImagePlaygroundConcept] = [
        .text(card.theme),
        .extracted(from: card.message)
    ]
    if !drawing.strokes.isEmpty {
        result.append(.drawing(drawing))
    }
    return result
}

Key points:

  • .drawing() accepts a PencilKit PKDrawing.
  • Strokes act as visual suggestions that guide composition without locking the result.
  • This is useful for iPad apps that provide hand-drawn input.

08:06 UIKit and AppKit integration

UIKit and AppKit use ImagePlaygroundViewController:

// Adopt Image Playground in UIKit or AppKit

func presentViewController() {
    let viewController = ImagePlaygroundViewController()
    viewController.concepts = [
        .text(card.theme),
        .extracted(from: card.message)
    ]
    viewController.delegate = self
    present(viewController, animated: true)
}

func imagePlaygroundViewController(
    _ viewController: ImagePlaygroundViewController,
    didCreateImageAt url: URL
) {
    var updated = card
    store.saveImage(url, for: &updated)
    dismiss(animated: true)
}

Key points:

  • Set the concepts property before presentation.
  • Receive the result through the delegate pattern.
  • The API is consistent with the SwiftUI version.

09:02 Size configuration

ImagePlaygroundOptions can configure image size:

// Size specification

var options: ImagePlaygroundOptions {
    var options = ImagePlaygroundOptions()
    options.sizeSpecification = .closest(to: card.format.size)
    return options
}

var body: some View {
    Button("Create image") { showingPlayground = true }
        .imagePlaygroundSheet(
            isPresented: $showingPlayground,
            concepts: concepts,
            onCompletion: { url in
                var updated = card
                store.saveImage(url, for: &updated)
            }
        )
        .imagePlaygroundOptions(options)
}

Key points:

  • .closest(to:) accepts a CGSize.
  • The system automatically maps it to the closest supported aspect ratio and resolution.
  • This is useful for apps that support multiple formats.

09:39 Style configuration

You can limit and preset the available styles:

// Styles

var options: ImagePlaygroundOptions {
    var options = ImagePlaygroundOptions()
    options.sizeSpecification = .closest(to: card.format.size)
    return options
}

var body: some View {
    Button("Create image") { showingPlayground = true }
        .imagePlaygroundSheet(
            isPresented: $showingPlayground,
            concepts: concepts,
            onCompletion: { url in
                var updated = card
                store.saveImage(url, for: &updated)
            }
        )
        .imagePlaygroundOptions(options)
        .imagePlaygroundGenerationStyle(
            pendingStylePreset.defaultStyle,
            in: pendingStylePreset.allowedStyles
        )
}

Key points:

  • The first parameter is the default selected style.
  • The second parameter is the list of allowed styles.
  • If you pass only one style, the picker locks to that style.
  • Preset styles include illustration, sketch, animation, and emoji.

10:27 Third-party style support

You can support third-party generation services configured by the user in Settings:

// External provider style

var options: ImagePlaygroundOptions {
    var options = ImagePlaygroundOptions()
    options.sizeSpecification = .closest(to: card.format.size)
    return options
}

var body: some View {
    Button("Create image") { showingPlayground = true }
        .imagePlaygroundSheet(
            isPresented: $showingPlayground,
            concepts: concepts,
            onCompletion: { url in
                var updated = card
                store.saveImage(url, for: &updated)
            }
        )
        .imagePlaygroundOptions(options)
        .imagePlaygroundGenerationStyle(
            pendingStylePreset.defaultStyle,
            in: pendingStylePreset.allowedStyles + [.externalProvider]
        )
}

Key points:

  • .externalProvider is an optional style.
  • After the user configures a provider in Settings, such as ChatGPT, this tab appears automatically.
  • You do not need to check whether the user has configured a provider; the system handles it.

11:02 Genmoji icon generation

When using the emoji style, you can generate adaptive image glyphs that can be embedded in text:

// Generate an expressive icon for the card thumbnail

@State private var showingIconPlayground = false

var body: some View {
    Button("Create icon") {
        showingIconPlayground = true
    }
    Color.clear
        .imagePlaygroundSheet(
            isPresented: $showingIconPlayground,
            concepts: concepts,
            onCompletion: { _ in
            } ,
            onAdaptiveImageGlyphCreation: { glyph in
                var updatedCard = card
                store.saveIcon(glyph, for: &updatedCard)
            }
        )
        .imagePlaygroundGenerationStyle(.emoji, in: [.emoji])
}

Key points:

  • When the emoji style is active, onAdaptiveImageGlyphCreation is triggered.
  • The callback returns an NSAdaptiveImageGlyph rather than a URL.
  • Adaptive image glyphs can be embedded directly in text and displayed like emoji.

12:01 Disabling personalization

You can disable personalization when it does not fit the context:

// Disable personalization when it does not fit your context

var options: ImagePlaygroundOptions {
    var options = ImagePlaygroundOptions()
    options.sizeSpecification = .closest(to: card.format.size)
    options.personalization = .disabled
    return options
}

Key points:

  • Personalization is enabled by default.
  • When disabled, the people picker and name detection disappear from the sheet.
  • This is suitable for product image generation and other contexts that do not need personalization.

12:32 Checking feature availability

Use an environment value to check whether the device supports image generation:

// Supports image generation

@Environment(\.supportsImageGeneration)
private var supportsImageGeneration

var body: some View {
    NavigationLink(card.recipient) {
        if supportsImageGeneration {
            CardEditorView(card: card)
        } else {
            CardPickerView(card: card)
        }
    }
}

Key points:

  • supportsImageGeneration considers device capability, language and region, and user settings.
  • Show the full experience only when it returns true.
  • When it returns false, fall back to another flow such as choosing from the photo library.
  • No additional entitlement or capability check is required.

Key Takeaways

  1. Custom card covers in greeting card apps: Image Playground is a natural fit for generating personalized greeting card covers. Combine the user’s message, relationship to the recipient, and holiday theme to generate a unique image. Users can also choose a photo of the recipient from their library to create a custom card that includes the person’s likeness.

  2. Personalized avatars for social profiles: Many apps let users upload an avatar or cover image. Offer a “Generate with AI” option that creates personalized images from a nickname, bio, and interest tags. This is a good alternative for users who do not want to upload a real photo.

  3. Expressive image enhancements in messaging apps: Following the model in Messages, let users generate images for specific emotions or situations in a conversation. For example, automatically suggest entry points for “celebration,” “comfort,” or “apology” images based on the conversation.

  4. Illustrations for content creation apps: Notes, blogs, and document apps can offer a “Generate an illustration for this content” feature. The system can extract the title, keywords, and emotional tone as context seeds, and users only need to adjust the result.

  5. Custom elements for games and social apps: Let users generate personalized avatars, badges, frames, and similar elements. Use the emoji style to generate adaptive glyphs that can be embedded in text and displayed next to usernames for richer self-expression.

Comments

GitHub Issues · utterances