Swift

Deze prompt is een voorbeeld prompt van het boek: Het Basisboek AI. De prompt hoort bij tabel 17 van het boek en geeft aan hoe je van een HTML code een mobiele app kunt maken in Swift.

CodeBoek

Customize your prompt

Prompt

Vertaal deze HTML-code [VOER HIER DE CODE VAN THEFUTURE.IM/PROMPTS/WEBP IN] naar Swift. De Swift-code moet een mobiele app maken met dezelfde functionaliteit. 

Example Output

import SwiftUI
import PhotosUI
import UniformTypeIdentifiers
import ImageIO

struct ConvertedImage: Identifiable {
    let id = UUID()
    let original: UIImage
    let webPData: Data
    var originalSize: Int { original.jpegData(compressionQuality: 1)?.count ?? 0 }
    var webPSize: Int { webPData.count }
    var reduction: Int {
        guard originalSize > 0 else { return 0 }
        return Int(round(Double(originalSize - webPSize) / Double(originalSize) * 100))
    }
}

class ViewModel: ObservableObject {
    @Published var selectedImages: [UIImage] = []
    @Published var results: [ConvertedImage] = []
    @Published var quality: Double = 0.8
    
    func convert() {
        results = selectedImages.compactMap { image in
            guard let webp = image.webpData(quality: quality) else { return nil }
            return ConvertedImage(original: image, webPData: webp)
        }
    }
}

extension UIImage {
    func webpData(quality: Double) -> Data? {
        guard let cgImage = self.cgImage else { return nil }
        let options = [kCGImageDestinationLossyCompressionQuality: quality] as CFDictionary
        let data = NSMutableData()
        guard let dest = CGImageDestinationCreateWithData(data, UTType.webP.identifier as CFString, 1, nil) else { return nil }
        CGImageDestinationAddImage(dest, cgImage, options)
        guard CGImageDestinationFinalize(dest) else { return nil }
        return data as Data
    }
}

struct PhotoPicker: UIViewControllerRepresentable {
    @Binding var images: [UIImage]
    
    func makeUIViewController(context: Context) -> PHPickerViewController {
        var cfg = PHPickerConfiguration(photoLibrary: .shared())
        cfg.selectionLimit = 0
        cfg.filter = .images
        let picker = PHPickerViewController(configuration: cfg)
        picker.delegate = context.coordinator
        return picker
    }
    
    func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) {}
    
    func makeCoordinator() -> Coordinator { Coordinator(self) }
    
    class Coordinator: NSObject, PHPickerViewControllerDelegate {
        let parent: PhotoPicker
        init(_ parent: PhotoPicker) { self.parent = parent }
        
        func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
            parent.images = []
            let group = DispatchGroup()
            for r in results {
                if r.itemProvider.canLoadObject(ofClass: UIImage.self) {
                    group.enter()
                    r.itemProvider.loadObject(ofClass: UIImage.self) { obj, _ in
                        if let img = obj as? UIImage {
                            DispatchQueue.main.async {
                                self.parent.images.append(img)
                            }
                        }
                        group.leave()
                    }
                }
            }
            group.notify(queue: .main) { picker.dismiss(animated: true) }
        }
    }
}

func formatBytes(_ bytes: Int) -> String {
    let k = 1024.0
    let sizes = ["Bytes","KB","MB","GB"]
    var value = Double(bytes)
    var i = 0
    while value > k && i < sizes.count-1 {
        value /= k
        i += 1
    }
    return String(format: "%.2f %@", value, sizes[i])
}

struct ContentView: View {
    @StateObject private var vm = ViewModel()
    @State private var showingPicker = false
    
    var body: some View {
        VStack(spacing: 20) {
            Text("Afbeelding naar WebP Converter")
                .font(.title)
                .foregroundColor(.blue)
            Text("Converteer uw JPG- en PNG-afbeeldingen naar WebP.")
                .multilineTextAlignment(.center)
                .foregroundColor(.secondary)
            
            Button("Kies afbeeldingen") { showingPicker = true }
            Text("\(vm.selectedImages.count) geselecteerd")
                .foregroundColor(vm.selectedImages.isEmpty ? .red : .primary)
            
            HStack {
                Text("Kwaliteit: \(Int(vm.quality * 100))%")
                Slider(value: $vm.quality, in: 0...1, step: 0.05)
            }.padding(.horizontal)
            
            Button("Converteren") {
                vm.convert()
            }
            .disabled(vm.selectedImages.isEmpty)
            
            ScrollView {
                ForEach(vm.results) { item in
                    VStack(spacing: 10) {
                        Text(item.original.accessibilityIdentifier ?? "Afbeelding")
                            .font(.headline)
                        HStack {
                            VStack {
                                Text("Origineel")
                                Image(uiImage: item.original)
                                    .resizable()
                                    .scaledToFit()
                                    .frame(height: 120)
                                Text(formatBytes(item.originalSize))
                            }
                            VStack {
                                Text("WebP")
                                Image(uiImage: UIImage(data: item.webPData)!)
                                    .resizable()
                                    .scaledToFit()
                                    .frame(height: 120)
                                Text("\(formatBytes(item.webPSize)) (\(item.reduction >= 0 ? "-" : "+")\(abs(item.reduction))%)")
                                    .foregroundColor(item.reduction >= 0 ? .green : .red)
                                Button("Sla op") {
                                    saveToPhotos(data: item.webPData)
                                }
                            }
                        }
                        Divider()
                    }
                    .padding()
                }
            }
        }
        .padding()
        .sheet(isPresented: $showingPicker) {
            PhotoPicker(images: $vm.selectedImages)
        }
    }
    
    func saveToPhotos(data: Data) {
        UIImageWriteToSavedPhotosAlbum(UIImage(data: data)!, nil, nil, nil)
    }
}

@main
struct WebPConverterApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}