🎯 Exemples recommandés
Balanced sample collections from various categories for you to explore
Exemples de Traitement d'Image macOS Swift
Exemples de traitement d'image macOS Swift incluant le chargement/sauvegarde, le filtrage et les transformations
💻 Chargement/Sauvegarde d'Image swift
🟢 simple
⭐⭐
Charger des images depuis des fichiers, URLs et ressources du bundle, et sauvegarder dans différents formats
⏱️ 25 min
🏷️ swift, macos, image processing, loading
Prerequisites:
Basic Swift, AppKit framework, NSImage
// macOS Swift Image Loading/Saving Examples
// Using AppKit and CoreImage
import Cocoa
import CoreImage
import AppKit
// 1. Load Image from File
class ImageFileLoader {
static func loadFromFile(path: String) -> NSImage? {
print("\n--- Load Image from File ---")
guard FileManager.default.fileExists(atPath: path) else {
print("File does not exist: \(path)")
return nil
}
let imageURL = URL(fileURLWithPath: path)
guard let image = NSImage(contentsOf: imageURL) else {
print("Failed to load image from: \(path)")
return nil
}
print("Loaded image from: \(path)")
print("Size: \(image.size)")
return image
}
static func loadFromAbsolutePath(path: String) -> NSImage? {
print("\n--- Load from Absolute Path ---")
let imagePath = NSString(string: path).expandingTildeInPath
return loadFromFile(path: imagePath as String)
}
}
// 2. Load Image from URL
class ImageURLLoader {
static func loadFromURL(url: URL, completion: @escaping (NSImage?) -> Void) {
print("\n--- Load Image from URL ---")
print("Loading: \(url.absoluteString)")
let task = URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data, error == nil else {
print("Failed to load image: \(error?.localizedDescription ?? "")")
completion(nil)
return
}
let image = NSImage(data: data)
completion(image)
}
task.resume()
}
static func loadFromURLSynchronously(url: URL) -> NSImage? {
print("\n--- Load from URL (Synchronous) ---")
if let data = try? Data(contentsOf: url) {
let image = NSImage(data: data)
print("Loaded from URL: \(url.lastPathComponent)")
return image
}
return nil
}
}
// 3. Load Image from Bundle
class BundleImageLoader {
static func loadFromBundle(name: String, extension: String) -> NSImage? {
print("\n--- Load Image from Bundle ---")
guard let imagePath = Bundle.main.path(forResource: name, ofType: extension) else {
print("Image not found in bundle: \(name).\(extension)")
return nil
}
let image = NSImage(contentsOfFile: imagePath)
if let image = image {
print("Loaded from bundle: \(name).\(extension)")
print("Size: \(image.size)")
}
return image
}
static func loadFromAssetCatalog(assetName: String) -> NSImage? {
print("\n--- Load from Asset Catalog ---")
let image = NSImage(named: assetName)
if let image = image {
print("Loaded asset: \(assetName)")
print("Size: \(image.size)")
} else {
print("Asset not found: \(assetName)")
}
return image
}
}
// 4. Save Image to File
class ImageFileSaver {
static func saveToFile(image: NSImage, path: String, fileType: NSBitmapImageFileType = .png) -> Bool {
print("\n--- Save Image to File ---")
guard let tiffData = image.tiffRepresentation,
let bitmap = NSBitmapImageRep(data: tiffData) else {
print("Failed to get bitmap representation")
return false
}
let imageData = bitmap.representation(using: fileType, properties: [:])
guard let data = imageData else {
print("Failed to convert image")
return false
}
do {
try data.write(to: URL(fileURLWithPath: path))
print("Saved image to: \(path)")
print("Format: \(fileType)")
print("Size: \(data.count) bytes")
return true
} catch {
print("Failed to save: \(error)")
return false
}
}
static func saveAsPNG(image: NSImage, path: String) -> Bool {
return saveToFile(image: image, path: path, fileType: .png)
}
static func saveAsJPEG(image: NSImage, path: String, quality: Float = 0.9) -> Bool {
print("\n--- Save as JPEG ---")
guard let tiffData = image.tiffRepresentation,
let bitmap = NSBitmapImageRep(data: tiffData) else {
return false
}
let imageData = bitmap.representation(using: .jpeg, properties: [.compressionFactor: quality])
guard let data = imageData else {
return false
}
do {
try data.write(to: URL(fileURLWithPath: path))
print("Saved as JPEG to: \(path)")
print("Quality: \(quality)")
print("Size: \(data.count) bytes")
return true
} catch {
print("Failed to save: \(error)")
return false
}
}
}
// 5. Image Information
class ImageInfo {
static func getInfo(_ image: NSImage) -> [String: Any] {
print("\n--- Image Information ---")
var info: [String: Any] = [:]
info["size"] = NSSize(width: image.size.width, height: image.size.height)
print("Size: \(image.size)")
if let tiffData = image.tiffRepresentation,
let bitmap = NSBitmapImageRep(data: tiffData) {
info["pixelsWide"] = bitmap.pixelsWide
info["pixelsHigh"] = bitmap.pixelsHigh
info["bitsPerSample"] = bitmap.bitsPerSample
info["samplesPerPixel"] = bitmap.samplesPerPixel
info["hasAlpha"] = bitmap.hasAlpha
info["isPlanar"] = bitmap.isPlanar
info["colorSpaceName"] = bitmap.colorSpaceName ?? ""
print("Dimensions: \(bitmap.pixelsWide) x \(bitmap.pixelsHigh)")
print("Bits per sample: \(bitmap.bitsPerSample)")
print("Samples per pixel: \(bitmap.samplesPerPixel)")
print("Has alpha: \(bitmap.hasAlpha)")
print("Color space: \(bitmap.colorSpaceName ?? "unknown")")
}
return info
}
static func getEXIFData(from path: String) -> [String: Any]? {
print("\n--- Get EXIF Data ---")
let imageURL = URL(fileURLWithPath: path)
guard let imageSource = CGImageSourceCreateWithURL(imageURL as CFURL, nil),
let properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil) as? [String: Any] else {
print("No EXIF data found")
return nil
}
if let exif = properties[kCGImagePropertyExifDictionary as String] as? [String: Any] {
print("EXIF data found")
if let dateTime = exif[kCGImagePropertyExifDateTimeOriginal as String] {
print("Date taken: \(dateTime)")
}
if let make = exif[kCGImagePropertyExifMake as String] {
print("Camera make: \(make)")
}
if let model = exif[kCGImagePropertyExifModel as String] {
print("Camera model: \(model)")
}
return exif
}
return nil
}
}
// 6. Convert Between Formats
class ImageFormatConverter {
static func convertToData(image: NSImage, type: NSBitmapImageFileType) -> Data? {
print("\n--- Convert to Data ---")
guard let tiffData = image.tiffRepresentation,
let bitmap = NSBitmapImageRep(data: tiffData) else {
return nil
}
let data = bitmap.representation(using: type, properties: [:])
if let imageData = data {
print("Converted to \(type)")
print("Size: \(imageData.count) bytes")
}
return data
}
static func convertToPNG(image: NSImage) -> Data? {
return convertToData(image: image, type: .png)
}
static func convertToJPEG(image: NSImage, quality: Float = 0.9) -> Data? {
guard let tiffData = image.tiffRepresentation,
let bitmap = NSBitmapImageRep(data: tiffData) else {
return nil
}
return bitmap.representation(using: .jpeg, properties: [.compressionFactor: quality])
}
static func convertToTIFF(image: NSImage) -> Data? {
return image.tiffRepresentation
}
}
// 7. Create Image from Data
class ImageFromData {
static func createFromData(_ data: Data) -> NSImage? {
print("\n--- Create Image from Data ---")
let image = NSImage(data: data)
if let image = image {
print("Created image from data (\(data.count) bytes)")
print("Size: \(image.size)")
} else {
print("Failed to create image from data")
}
return image
}
static func createFromPNGData(_ data: Data) -> NSImage? {
print("\n--- Create from PNG Data ---")
return createFromData(data)
}
static func createFromJPEGData(_ data: Data) -> NSImage? {
print("\n--- Create from JPEG Data ---")
return createFromData(data)
}
}
// 8. Resize Image on Load
class ImageResizeOnLoad {
static func loadResized(path: String, maxSize: NSSize) -> NSImage? {
print("\n--- Load Resized Image ---")
let imageURL = URL(fileURLWithPath: path)
guard let imageSource = CGImageSourceCreateWithURL(imageURL as CFURL, nil),
let properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil) as? [String: Any] else {
return nil
}
let options: [String: Any] = [
kCGImageSourceCreateThumbnailFromImageIfAbsent: true,
kCGImageSourceThumbnailMaxPixelSize: max(maxSize.width, maxSize.height)
]
guard let thumbnail = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, options as CFDictionary) else {
return nil
}
let image = NSImage(cgImage: thumbnail, size: maxSize)
print("Loaded resized image: \(image.size)")
return image
}
}
// 9. Batch Image Loading
class BatchImageLoader {
static func loadFromDirectory(directory: String, extensions: [String] = ["jpg", "png", "gif"]) -> [String: NSImage] {
print("\n--- Batch Load Images ---")
var images: [String: NSImage] = [:]
guard let fileURLs = try? FileManager.default.contentsOfDirectory(
at: URL(fileURLWithPath: directory),
includingPropertiesForKeys: nil,
options: [.skipsHiddenFiles]
) else {
return images
}
print("Found \(fileURLs.count) files")
for fileURL in fileURLs {
let pathExtension = fileURL.pathExtension.lowercased()
if extensions.contains(pathExtension) {
if let image = NSImage(contentsOf: fileURL) {
images[fileURL.lastPathComponent] = image
print(" Loaded: \(fileURL.lastPathComponent)")
}
}
}
print("Loaded \(images.count) images")
return images
}
static func loadAsync(paths: [String], completion: @escaping ([String: NSImage]) -> Void) {
print("\n--- Async Batch Load ---")
let group = DispatchGroup()
var images: [String: NSImage] = [:]
let queue = DispatchQueue(label: "imageLoader")
for path in paths {
group.enter()
queue.async {
if let image = NSImage(contentsOfFile: path) {
DispatchQueue.main.async {
images[path] = image
}
}
group.leave()
}
}
group.notify(queue: .main) {
print("Async loaded \(images.count) images")
completion(images)
}
}
}
// 10. Image Thumbnail Generation
class ThumbnailGenerator {
static func generateThumbnail(from imagePath: String, size: NSSize, saveTo: String) -> Bool {
print("\n--- Generate Thumbnail ---")
let imageURL = URL(fileURLWithPath: imagePath)
guard let imageSource = CGImageSourceCreateWithURL(imageURL as CFURL, nil) else {
return false
}
let options: [String: Any] = [
kCGImageSourceCreateThumbnailWithTransform: true,
kCGImageSourceCreateThumbnailFromImageIfAbsent: true,
kCGImageSourceThumbnailMaxPixelSize: max(size.width, size.height)
]
guard let thumbnail = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, options as CFDictionary) else {
print("Failed to create thumbnail")
return false
}
let image = NSImage(cgImage: thumbnail, size: size)
// Save thumbnail
return ImageFileSaver.saveAsPNG(image: image, path: saveTo)
}
static func generateIconThumbnail(from imagePath: String) -> NSImage? {
print("\n--- Generate Icon Thumbnail ---")
let iconSize = NSSize(width: 64, height: 64)
guard let image = NSImage(contentsOfFile: imagePath) else {
return nil
}
let thumbnail = NSImage(size: iconSize)
thumbnail.lockFocus()
image.draw(
in: NSRect(origin: .zero, size: iconSize),
from: NSRect(origin: .zero, size: image.size),
operation: .copy,
fraction: 1.0
)
thumbnail.unlockFocus()
return thumbnail
}
}
// Main demonstration
func demonstrateImageLoadingSaving() {
print("=== macOS Swift Image Loading/Saving Examples ===")
// Create a sample image for testing
let samplePath = "/tmp/test_image.png"
// Create a simple test image
let testImage = NSImage(size: NSSize(width: 200, height: 200))
testImage.lockFocus()
NSColor.blue.set()
NSRect(origin: .zero, size: NSSize(width: 200, height: 200)).fill()
testImage.unlockFocus()
// Save test image
ImageFileSaver.saveAsPNG(image: testImage, path: samplePath)
// Load examples
if let loadedImage = ImageFileLoader.loadFromFile(path: samplePath) {
_ = ImageInfo.getInfo(loadedImage)
// Convert to different formats
if let pngData = ImageFormatConverter.convertToPNG(image: loadedImage) {
print("PNG data: \(pngData.count) bytes")
}
if let jpegData = ImageFormatConverter.convertToJPEG(image: loadedImage) {
print("JPEG data: \(jpegData.count) bytes")
}
}
// Save in different formats
_ = ImageFileSaver.saveAsJPEG(image: testImage, path: "/tmp/test_image.jpg")
_ = ImageFileSaver.saveToFile(image: testImage, path: "/tmp/test_image.tiff", fileType: .tiff)
print("\n=== All Image Loading/Saving Examples Completed ===")
}
// Run demonstration
demonstrateImageLoadingSaving()
💻 Filtrage d'Image swift
🟡 intermediate
⭐⭐⭐
Appliquer divers filtres en utilisant CoreImage, y compris le flou, la netteté et l'ajustement des couleurs
⏱️ 35 min
🏷️ swift, macos, image processing, filtering
Prerequisites:
Intermediate Swift, CoreImage framework, NSImage
// macOS Swift Image Filtering Examples
// Using CoreImage framework
import Cocoa
import CoreImage
import AppKit
// 1. Basic Filter Application
class BasicFilters {
static func applyFilter(to image: NSImage, filterName: String) -> NSImage? {
print("\n--- Apply Filter: \(filterName) ---")
guard let cgImage = image.cgImage(forProposedRect: nil, contextHints: nil) else {
print("Failed to get CGImage")
return nil
}
let ciImage = CIImage(cgImage: cgImage)
guard let filter = CIFilter(name: filterName) else {
print("Filter not found: \(filterName)")
return nil
}
filter.setValue(ciImage, forKey: kCIInputImageKey)
guard let outputImage = filter.outputImage else {
print("Filter failed")
return nil
}
let context = CIContext()
guard let outputCGImage = context.createCGImage(outputImage, from: outputImage.extent) else {
print("Failed to create CGImage")
return nil
}
let result = NSImage(cgImage: outputCGImage, size: image.size)
print("Applied filter: \(filterName)")
return result
}
}
// 2. Blur Filters
class BlurFilters {
static func gaussianBlur(image: NSImage, radius: Double) -> NSImage? {
print("\n--- Gaussian Blur ---")
print("Radius: \(radius)")
guard let cgImage = image.cgImage(forProposedRect: nil, contextHints: nil) else {
return nil
}
let ciImage = CIImage(cgImage: cgImage)
let filter = CIFilter(name: "CIGaussianBlur")
filter?.setValue(ciImage, forKey: kCIInputImageKey)
filter?.setValue(radius, forKey: kCIInputRadiusKey)
guard let outputImage = filter?.outputImage else {
return nil
}
let context = CIContext()
guard let outputCGImage = context.createCGImage(outputImage, from: outputImage.extent) else {
return nil
}
let result = NSImage(cgImage: outputCGImage, size: image.size)
print("Applied Gaussian blur")
return result
}
static func boxBlur(image: NSImage, radius: Double) -> NSImage? {
print("\n--- Box Blur ---")
print("Radius: \(radius)")
guard let cgImage = image.cgImage(forProposedRect: nil, contextHints: nil) else {
return nil
}
let ciImage = CIImage(cgImage: cgImage)
let filter = CIFilter(name: "CIBoxBlur")
filter?.setValue(ciImage, forKey: kCIInputImageKey)
filter?.setValue(radius, forKey: kCIInputRadiusKey)
guard let outputImage = filter?.outputImage else {
return nil
}
let context = CIContext()
guard let outputCGImage = context.createCGImage(outputImage, from: outputImage.extent) else {
return nil
}
return NSImage(cgImage: outputCGImage, size: image.size)
}
static func motionBlur(image: NSImage, radius: Double, angle: Double) -> NSImage? {
print("\n--- Motion Blur ---")
print("Radius: \(radius), Angle: \(angle)")
guard let cgImage = image.cgImage(forProposedRect: nil, contextHints: nil) else {
return nil
}
let ciImage = CIImage(cgImage: cgImage)
let filter = CIFilter(name: "CIMotionBlur")
filter?.setValue(ciImage, forKey: kCIInputImageKey)
filter?.setValue(radius, forKey: kCIInputRadiusKey)
filter?.setValue(angle, forKey: kCIInputAngleKey)
guard let outputImage = filter?.outputImage else {
return nil
}
let context = CIContext()
guard let outputCGImage = context.createCGImage(outputImage, from: outputImage.extent) else {
return nil
}
return NSImage(cgImage: outputCGImage, size: image.size)
}
}
// 3. Color Adjustment Filters
class ColorAdjustmentFilters {
static func adjustBrightness(image: NSImage, brightness: Double) -> NSImage? {
print("\n--- Adjust Brightness ---")
print("Brightness: \(brightness)")
guard let cgImage = image.cgImage(forProposedRect: nil, contextHints: nil) else {
return nil
}
let ciImage = CIImage(cgImage: cgImage)
let filter = CIFilter(name: "CIColorControls")
filter?.setValue(ciImage, forKey: kCIInputImageKey)
filter?.setValue(brightness, forKey: kCIInputBrightnessKey)
return applyFilterWithOutput(filter: filter, originalSize: image.size)
}
static func adjustContrast(image: NSImage, contrast: Double) -> NSImage? {
print("\n--- Adjust Contrast ---")
print("Contrast: \(contrast)")
guard let cgImage = image.cgImage(forProposedRect: nil, contextHints: nil) else {
return nil
}
let ciImage = CIImage(cgImage: cgImage)
let filter = CIFilter(name: "CIColorControls")
filter?.setValue(ciImage, forKey: kCIInputImageKey)
filter?.setValue(contrast, forKey: kCIInputContrastKey)
return applyFilterWithOutput(filter: filter, originalSize: image.size)
}
static func adjustSaturation(image: NSImage, saturation: Double) -> NSImage? {
print("\n--- Adjust Saturation ---")
print("Saturation: \(saturation)")
guard let cgImage = image.cgImage(forProposedRect: nil, contextHints: nil) else {
return nil
}
let ciImage = CIImage(cgImage: cgImage)
let filter = CIFilter(name: "CIColorControls")
filter?.setValue(ciImage, forKey: kCIInputImageKey)
filter?.setValue(saturation, forKey: kCIInputSaturationKey)
return applyFilterWithOutput(filter: filter, originalSize: image.size)
}
static func adjustTemperature(image: NSImage, temperature: Double) -> NSImage? {
print("\n--- Adjust Temperature ---")
print("Temperature: \(temperature)")
guard let cgImage = image.cgImage(forProposedRect: nil, contextHints: nil) else {
return nil
}
let ciImage = CIImage(cgImage: cgImage)
let filter = CIFilter(name: "CITemperatureAndTint")
filter?.setValue(ciImage, forKey: kCIInputImageKey)
filter?.setValue(temperature, forKey: kCIInputNeutral)
filter?.setValue(temperature, forKey: kCIInputTargetNeutral)
return applyFilterWithOutput(filter: filter, originalSize: image.size)
}
static func grayscale(image: NSImage) -> NSImage? {
print("\n--- Grayscale ---")
guard let cgImage = image.cgImage(forProposedRect: nil, contextHints: nil) else {
return nil
}
let ciImage = CIImage(cgImage: cgImage)
let filter = CIFilter(name: "CIPhotoEffectNoir")
filter?.setValue(ciImage, forKey: kCIInputImageKey)
return applyFilterWithOutput(filter: filter, originalSize: image.size)
}
static func sepia(image: NSImage) -> NSImage? {
print("\n--- Sepia ---")
guard let cgImage = image.cgImage(forProposedRect: nil, contextHints: nil) else {
return nil
}
let ciImage = CIImage(cgImage: cgImage)
let filter = CIFilter(name: "CISepiaTone")
filter?.setValue(ciImage, forKey: kCIInputImageKey)
filter?.setValue(0.8, forKey: kCIInputIntensityKey)
return applyFilterWithOutput(filter: filter, originalSize: image.size)
}
static func invertColors(image: NSImage) -> NSImage? {
print("\n--- Invert Colors ---")
guard let cgImage = image.cgImage(forProposedRect: nil, contextHints: nil) else {
return nil
}
let ciImage = CIImage(cgImage: cgImage)
let filter = CIFilter(name: "CIColorInvert")
filter?.setValue(ciImage, forKey: kCIInputImageKey)
return applyFilterWithOutput(filter: filter, originalSize: image.size)
}
private static func applyFilterWithOutput(filter: CIFilter?, originalSize: NSSize) -> NSImage? {
guard let outputImage = filter?.outputImage else {
return nil
}
let context = CIContext()
guard let outputCGImage = context.createCGImage(outputImage, from: outputImage.extent) else {
return nil
}
return NSImage(cgImage: outputCGImage, size: originalSize)
}
}
// 4. Sharpen and Blur Enhancement
class SharpenFilters {
static func sharpen(image: NSImage, intensity: Double) -> NSImage? {
print("\n--- Sharpen ---")
print("Intensity: \(intensity)")
guard let cgImage = image.cgImage(forProposedRect: nil, contextHints: nil) else {
return nil
}
let ciImage = CIImage(cgImage: cgImage)
let filter = CIFilter(name: "CISharpenLuminance")
filter?.setValue(ciImage, forKey: kCIInputImageKey)
filter?.setValue(intensity, forKey: kCIInputSharpnessKey)
guard let outputImage = filter?.outputImage else {
return nil
}
let context = CIContext()
guard let outputCGImage = context.createCGImage(outputImage, from: outputImage.extent) else {
return nil
}
return NSImage(cgImage: outputCGImage, size: image.size)
}
static func unsharpMask(image: NSImage, radius: Double, intensity: Double) -> NSImage? {
print("\n--- Unsharp Mask ---")
print("Radius: \(radius), Intensity: \(intensity)")
guard let cgImage = image.cgImage(forProposedRect: nil, contextHints: nil) else {
return nil
}
let ciImage = CIImage(cgImage: cgImage)
let filter = CIFilter(name: "CIUnsharpMask")
filter?.setValue(ciImage, forKey: kCIInputImageKey)
filter?.setValue(radius, forKey: kCIInputRadiusKey)
filter?.setValue(intensity, forKey: kCIInputIntensityKey)
guard let outputImage = filter?.outputImage else {
return nil
}
let context = CIContext()
guard let outputCGImage = context.createCGImage(outputImage, from: outputImage.extent) else {
return nil
}
return NSImage(cgImage: outputCGImage, size: image.size)
}
}
// 5. Photo Effect Filters
class PhotoEffectFilters {
static func applyVintageEffect(image: NSImage) -> NSImage? {
print("\n--- Vintage Effect ---")
guard let cgImage = image.cgImage(forProposedRect: nil, contextHints: nil) else {
return nil
}
let ciImage = CIImage(cgImage: cgImage)
let filter = CIFilter(name: "CIPhotoEffectInstant")
filter?.setValue(ciImage, forKey: kCIInputImageKey)
guard let outputImage = filter?.outputImage else {
return nil
}
let context = CIContext()
guard let outputCGImage = context.createCGImage(outputImage, from: outputImage.extent) else {
return nil
}
return NSImage(cgImage: outputCGImage, size: image.size)
}
static func applyChromeEffect(image: NSImage) -> NSImage? {
print("\n--- Chrome Effect ---")
guard let cgImage = image.cgImage(forProposedRect: nil, contextHints: nil) else {
return nil
}
let ciImage = CIImage(cgImage: cgImage)
let filter = CIFilter(name: "CIPhotoEffectChrome")
filter?.setValue(ciImage, forKey: kCIInputImageKey)
guard let outputImage = filter?.outputImage else {
return nil
}
let context = CIContext()
guard let outputCGImage = context.createCGImage(outputImage, from: outputImage.extent) else {
return nil
}
return NSImage(cgImage: outputCGImage, size: image.size)
}
static func applyFadeEffect(image: NSImage) -> NSImage? {
print("\n--- Fade Effect ---")
guard let cgImage = image.cgImage(forProposedRect: nil, contextHints: nil) else {
return nil
}
let ciImage = CIImage(cgImage: cgImage)
let filter = CIFilter(name: "CIPhotoEffectFade")
filter?.setValue(ciImage, forKey: kCIInputImageKey)
guard let outputImage = filter?.outputImage else {
return nil
}
let context = CIContext()
guard let outputCGImage = context.createCGImage(outputImage, from: outputImage.extent) else {
return nil
}
return NSImage(cgImage: outputCGImage, size: image.size)
}
static func applyMonoEffect(image: NSImage) -> NSImage? {
print("\n--- Mono Effect ---")
guard let cgImage = image.cgImage(forProposedRect: nil, contextHints: nil) else {
return nil
}
let ciImage = CIImage(cgImage: cgImage)
let filter = CIFilter(name: "CIPhotoEffectMono")
filter?.setValue(ciImage, forKey: kCIInputImageKey)
guard let outputImage = filter?.outputImage else {
return nil
}
let context = CIContext()
guard let outputCGImage = context.createCGImage(outputImage, from: outputImage.extent) else {
return nil
}
return NSImage(cgImage: outputCGImage, size: image.size)
}
static func applyTonalEffect(image: NSImage) -> NSImage? {
print("\n--- Tonal Effect ---")
guard let cgImage = image.cgImage(forProposedRect: nil, contextHints: nil) else {
return nil
}
let ciImage = CIImage(cgImage: cgImage)
let filter = CIFilter(name: "CIPhotoEffectTonal")
filter?.setValue(ciImage, forKey: kCIInputImageKey)
guard let outputImage = filter?.outputImage else {
return nil
}
let context = CIContext()
guard let outputCGImage = context.createCGImage(outputImage, from: outputImage.extent) else {
return nil
}
return NSImage(cgImage: outputCGImage, size: image.size)
}
}
// 6. Vignette Filter
class VignetteFilter {
static func applyVignette(image: NSImage, intensity: Double, radius: Double) -> NSImage? {
print("\n--- Vignette ---")
print("Intensity: \(intensity), Radius: \(radius)")
guard let cgImage = image.cgImage(forProposedRect: nil, contextHints: nil) else {
return nil
}
let ciImage = CIImage(cgImage: cgImage)
let filter = CIFilter(name: "CIVignette")
filter?.setValue(ciImage, forKey: kCIInputImageKey)
filter?.setValue(intensity, forKey: kCIInputIntensityKey)
filter?.setValue(radius, forKey: kCIInputRadiusKey)
guard let outputImage = filter?.outputImage else {
return nil
}
let context = CIContext()
guard let outputCGImage = context.createCGImage(outputImage, from: outputImage.extent) else {
return nil
}
return NSImage(cgImage: outputCGImage, size: image.size)
}
}
// 7. Chain Multiple Filters
class FilterChain {
static func applyChain(to image: NSImage, filters: [(String, [String: Any])]) -> NSImage? {
print("\n--- Filter Chain ---")
print("Applying \(filters.count) filters")
guard let cgImage = image.cgImage(forProposedRect: nil, contextHints: nil) else {
return nil
}
var ciImage = CIImage(cgImage: cgImage)
for (filterName, parameters) in filters {
print(" Applying: \(filterName)")
guard let filter = CIFilter(name: filterName) else {
continue
}
filter.setValue(ciImage, forKey: kCIInputImageKey)
for (key, value) in parameters {
filter.setValue(value, forKey: key)
}
guard let outputImage = filter.outputImage else {
continue
}
ciImage = outputImage
}
let context = CIContext()
guard let outputCGImage = context.createCGImage(ciImage, from: ciImage.extent) else {
return nil
}
let result = NSImage(cgImage: outputCGImage, size: image.size)
print("Filter chain applied successfully")
return result
}
}
// 8. Noise Reduction
class NoiseReduction {
static func reduceNoise(image: NSImage, level: Double, sharpness: Double) -> NSImage? {
print("\n--- Noise Reduction ---")
print("Level: \(level), Sharpness: \(sharpness)")
guard let cgImage = image.cgImage(forProposedRect: nil, contextHints: nil) else {
return nil
}
let ciImage = CIImage(cgImage: cgImage)
let filter = CIFilter(name: "CINoiseReduction")
filter?.setValue(ciImage, forKey: kCIInputImageKey)
filter?.setValue(level, forKey: kCIInputNoiseLevelKey)
filter?.setValue(sharpness, forKey: kCIInputSharpnessKey)
guard let outputImage = filter?.outputImage else {
return nil
}
let context = CIContext()
guard let outputCGImage = context.createCGImage(outputImage, from: outputImage.extent) else {
return nil
}
return NSImage(cgImage: outputCGImage, size: image.size)
}
}
// 9. Edge Detection
class EdgeDetection {
static func detectEdges(image: NSImage, intensity: Double = 1.0) -> NSImage? {
print("\n--- Edge Detection ---")
print("Intensity: \(intensity)")
guard let cgImage = image.cgImage(forProposedRect: nil, contextHints: nil) else {
return nil
}
let ciImage = CIImage(cgImage: cgImage)
let filter = CIFilter(name: "CIEdges")
filter?.setValue(ciImage, forKey: kCIInputImageKey)
filter?.setValue(intensity, forKey: kCIInputIntensityKey)
guard let outputImage = filter?.outputImage else {
return nil
}
let context = CIContext()
guard let outputCGImage = context.createCGImage(outputImage, from: outputImage.extent) else {
return nil
}
return NSImage(cgImage: outputCGImage, size: image.size)
}
static func lineOverlay(image: NSImage) -> NSImage? {
print("\n--- Line Overlay ---")
guard let cgImage = image.cgImage(forProposedRect: nil, contextHints: nil) else {
return nil
}
let ciImage = CIImage(cgImage: cgImage)
let filter = CIFilter(name: "CILineOverlay")
filter?.setValue(ciImage, forKey: kCIInputImageKey)
guard let outputImage = filter?.outputImage else {
return nil
}
let context = CIContext()
guard let outputCGImage = context.createCGImage(outputImage, from: outputImage.extent) else {
return nil
}
return NSImage(cgImage: outputCGImage, size: image.size)
}
}
// 10. Color Matrix Filter
class ColorMatrix {
static func applyColorMatrix(image: NSImage, matrix: [CGFloat], bias: [CGFloat] = []) -> NSImage? {
print("\n--- Color Matrix ---")
guard let cgImage = image.cgImage(forProposedRect: nil, contextHints: nil) else {
return nil
}
let ciImage = CIImage(cgImage: cgImage)
let filter = CIFilter(name: "CIColorMatrix")
filter?.setValue(ciImage, forKey: kCIInputImageKey)
filter?.setValue(CIVector(cgFloat: matrix), forKey: "inputRVector")
filter?.setValue(CIVector(cgFloat: matrix), forKey: "inputGVector")
filter?.setValue(CIVector(cgFloat: matrix), forKey: "inputBVector")
filter?.setValue(CIVector(cgFloat: matrix), forKey: "inputAVector")
if !bias.isEmpty {
filter?.setValue(CIVector(cgFloat: bias), forKey: "inputRBias")
filter?.setValue(CIVector(cgFloat: bias), forKey: "inputGBias")
filter?.setValue(CIVector(cgFloat: bias), forKey: "inputBBias")
filter?.setValue(CIVector(cgFloat: bias), forKey: "inputABias")
}
guard let outputImage = filter?.outputImage else {
return nil
}
let context = CIContext()
guard let outputCGImage = context.createCGImage(outputImage, from: outputImage.extent) else {
return nil
}
return NSImage(cgImage: outputCGImage, size: image.size)
}
// Grayscale using color matrix
static func grayscaleMatrix(image: NSImage) -> NSImage? {
print("\n--- Grayscale (Color Matrix) ---")
// Standard luminance values
let matrix: [CGFloat] = [0.299, 0.587, 0.114, 0]
return applyColorMatrix(image: image, matrix: matrix)
}
}
// Main demonstration
func demonstrateImageFiltering() {
print("=== macOS Swift Image Filtering Examples ===")
// Create a test image
let testImage = NSImage(size: NSSize(width: 300, height: 300))
testImage.lockFocus()
NSColor.red.set()
NSBezierPath(ovalIn: NSRect(origin: .zero, size: NSSize(width: 300, height: 300))).fill()
NSColor.white.set()
NSBezierPath(ovalIn: NSRect(origin: NSPoint(x: 100, y: 100), size: NSSize(width: 100, height: 100))).fill()
testImage.unlockFocus()
// Apply filters
if let blurred = BlurFilters.gaussianBlur(image: testImage, radius: 10) {
print("Blur applied")
}
if let sharpened = SharpenFilters.sharpen(image: testImage, intensity: 2.0) {
print("Sharpen applied")
}
if let vintage = PhotoEffectFilters.applyVintageEffect(image: testImage) {
print("Vintage effect applied")
}
if let vignetted = VignetteFilter.applyVignette(image: testImage, intensity: 1.0, radius: 150) {
print("Vignette applied")
}
if let grayscaled = ColorAdjustmentFilters.grayscale(image: testImage) {
print("Grayscale applied")
}
if let sepia = ColorAdjustmentFilters.sepia(image: testImage) {
print("Sepia applied")
}
if let edges = EdgeDetection.detectEdges(image: testImage) {
print("Edge detection applied")
}
// Chain filters
let filters: [(String, [String: Any])] = [
("CIGaussianBlur", [kCIInputRadiusKey: 5]),
("CIColorControls", [kCIInputBrightnessKey: 0.1, kCIInputContrastKey: 1.1])
]
if let chained = FilterChain.applyChain(to: testImage, filters: filters) {
print("Filter chain applied")
}
print("\n=== All Image Filtering Examples Completed ===")
}
// Run demonstration
demonstrateImageFiltering()
💻 Transformations d'Image swift
🟡 intermediate
⭐⭐⭐
Effectuer des transformations géométriques sur les images incluant le redimensionnement, la rotation, le recadrage et le retournement
⏱️ 30 min
🏷️ swift, macos, image processing, transformations
Prerequisites:
Intermediate Swift, CoreGraphics, NSImage
// macOS Swift Image Transformations Examples
// Using CoreGraphics and CoreImage
import Cocoa
import CoreImage
import AppKit
// 1. Resize Image
class ImageResize {
static func resize(_ image: NSImage, to newSize: NSSize) -> NSImage? {
print("\n--- Resize Image ---")
print("Original size: \(image.size)")
print("New size: \(newSize)")
let resizedImage = NSImage(size: newSize)
resizedImage.lockFocus()
image.draw(
in: NSRect(origin: .zero, size: newSize),
from: NSRect(origin: .zero, size: image.size),
operation: .copy,
fraction: 1.0
)
resizedImage.unlockFocus()
print("Resized successfully")
return resizedImage
}
static func resizeMaintainingAspectRatio(_ image: NSImage, maxWidth: CGFloat, maxHeight: CGFloat) -> NSImage? {
print("\n--- Resize Maintaining Aspect Ratio ---")
let widthRatio = maxWidth / image.size.width
let heightRatio = maxHeight / image.size.height
let ratio = min(widthRatio, heightRatio)
let newSize = NSSize(
width: image.size.width * ratio,
height: image.size.height * ratio
)
print("Target max: \(maxWidth)x\(maxHeight)")
print("Calculated size: \(newSize)")
return resize(image, to: newSize)
}
static func scaleBy(_ image: NSImage, scaleX: CGFloat, scaleY: CGFloat) -> NSImage? {
print("\n--- Scale Image ---")
print("Scale X: \(scaleX), Scale Y: \(scaleY)")
let newSize = NSSize(
width: image.size.width * scaleX,
height: image.size.height * scaleY
)
return resize(image, to: newSize)
}
}
// 2. Crop Image
class ImageCrop {
static func crop(_ image: NSImage, to rect: NSRect) -> NSImage? {
print("\n--- Crop Image ---")
print("Crop rect: \(rect)")
// Handle hi-DPI
guard let rep = image.representations.first as? NSImageRep else {
print("No image representation")
return nil
}
let scaledRect = NSRect(
x: rect.origin.x * rep.pixelsWide / image.size.width,
y: rect.origin.y * rep.pixelsHigh / image.size.height,
width: rect.size.width * rep.pixelsWide / image.size.width,
height: rect.size.height * rep.pixelsHigh / image.size.height
)
guard let cgImage = image.cgImage(forProposedRect: nil, contextHints: nil) else {
return nil
}
let croppedCGImage = cgImage.cropping(to: scaledRect)
let croppedImage = NSImage(cgImage: croppedCGImage, size: rect.size)
print("Cropped to: \(rect.size)")
return croppedImage
}
static func cropToCenter(_ image: NSImage, size: NSSize) -> NSImage? {
print("\n--- Crop to Center ---")
print("Target size: \(size)")
let x = (image.size.width - size.width) / 2
let y = (image.size.height - size.height) / 2
let rect = NSRect(x: x, y: y, width: size.width, height: size.height)
return crop(image, to: rect)
}
static func cropToSquare(_ image: NSImage) -> NSImage? {
print("\n--- Crop to Square ---")
let minDimension = min(image.size.width, image.size.height)
let squareSize = NSSize(width: minDimension, height: minDimension)
return cropToCenter(image, size: squareSize)
}
}
// 3. Rotate Image
class ImageRotation {
static func rotate(_ image: NSImage, byDegrees degrees: CGFloat) -> NSImage? {
print("\n--- Rotate Image ---")
print("Degrees: \(degrees)")
guard let cgImage = image.cgImage(forProposedRect: nil, contextHints: nil) else {
return nil
}
let radians = degrees * .pi / 180
let rotatedRect = CGRectApplyAffineTransform(
CGRect(origin: .zero, size: image.size),
CGAffineTransform(rotationAngle: radians)
)
let newSize = NSSize(
width: abs(rotatedRect.width),
height: abs(rotatedRect.height)
)
let rotatedImage = NSImage(size: newSize)
rotatedImage.lockFocus()
let transform = NSAffineTransform()
transform.translateX(by: newSize.width / 2)
transform.translateY(by: newSize.height / 2)
transform.rotate(byDegrees: degrees)
transform.translateX(by: -image.size.width / 2)
transform.translateY(by: -image.size.height / 2)
transform.concat()
image.draw(at: .zero, from: NSRect(origin: .zero, size: image.size), operation: .copy, fraction: 1.0)
rotatedImage.unlockFocus()
print("Rotated successfully")
return rotatedImage
}
static func rotate90(_ image: NSImage) -> NSImage? {
print("\n--- Rotate 90° ---")
return rotate(image, byDegrees: 90)
}
static func rotate180(_ image: NSImage) -> NSImage? {
print("\n--- Rotate 180° ---")
return rotate(image, byDegrees: 180)
}
static func rotate270(_ image: NSImage) -> NSImage? {
print("\n--- Rotate 270° ---")
return rotate(image, byDegrees: 270)
}
}
// 4. Flip Image
class ImageFlip {
static func flipHorizontal(_ image: NSImage) -> NSImage? {
print("\n--- Flip Horizontal ---")
let flippedImage = NSImage(size: image.size)
flippedImage.lockFocus()
NSGraphicsContext.current?.imageInterpolation = .high
NSAffineTransform.translateX(by: image.size.width, y: 0).concat()
NSAffineTransform.scale(x: -1, y: 1).concat()
image.draw(at: .zero, from: NSRect(origin: .zero, size: image.size), operation: .copy, fraction: 1.0)
flippedImage.unlockFocus()
print("Flipped horizontally")
return flippedImage
}
static func flipVertical(_ image: NSImage) -> NSImage? {
print("\n--- Flip Vertical ---")
let flippedImage = NSImage(size: image.size)
flippedImage.lockFocus()
NSGraphicsContext.current?.imageInterpolation = .high
NSAffineTransform.translateX(by: 0, y: image.size.height).concat()
NSAffineTransform.scale(x: 1, y: -1).concat()
image.draw(at: .zero, from: NSRect(origin: .zero, size: image.size), operation: .copy, fraction: 1.0)
flippedImage.unlockFocus()
print("Flipped vertically")
return flippedImage
}
}
// 5. Border/Padding
class ImagePadding {
static func addPadding(_ image: NSImage, padding: CGFloat, color: NSColor = .white) -> NSImage? {
print("\n--- Add Padding ---")
print("Padding: \(padding)")
let newSize = NSSize(
width: image.size.width + 2 * padding,
height: image.size.height + 2 * padding
)
let paddedImage = NSImage(size: newSize)
paddedImage.lockFocus()
color.set()
NSBezierPath(rect: NSRect(origin: .zero, size: newSize)).fill()
image.draw(
in: NSRect(origin: NSPoint(x: padding, y: padding), size: image.size),
from: NSRect(origin: .zero, size: image.size),
operation: .copy,
fraction: 1.0
)
paddedImage.unlockFocus()
print("Added padding: \(padding)")
return paddedImage
}
static func addBorder(_ image: NSImage, borderWidth: CGFloat, color: NSColor = .black) -> NSImage? {
print("\n--- Add Border ---")
print("Border width: \(borderWidth)")
let newSize = NSSize(
width: image.size.width + 2 * borderWidth,
height: image.size.height + 2 * borderWidth
)
let borderedImage = NSImage(size: newSize)
borderedImage.lockFocus()
// Fill with border color
color.set()
NSBezierPath(rect: NSRect(origin: .zero, size: newSize)).fill()
// Draw image inside
image.draw(
in: NSRect(origin: NSPoint(x: borderWidth, y: borderWidth), size: image.size),
from: NSRect(origin: .zero, size: image.size),
operation: .copy,
fraction: 1.0
)
borderedImage.unlockFocus()
return borderedImage
}
}
// 6. Perspective Transform
class PerspectiveTransform {
static func applyPerspective(_ image: NSImage, topLeft: CGPoint, topRight: CGPoint, bottomLeft: CGPoint, bottomRight: CGPoint) -> NSImage? {
print("\n--- Perspective Transform ---")
print("Top-left: \(topLeft)")
print("Top-right: \(topRight)")
print("Bottom-left: \(bottomLeft)")
print("Bottom-right: \(bottomRight)")
guard let ciImage = CIImage(image: image) else {
return nil
}
// Calculate output size
let maxX = max(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x)
let maxY = max(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y)
let extent = CGRect(x: 0, y: 0, width: maxX, height: maxY)
guard let filter = CIFilter(name: "CIPerspectiveTransform") else {
return nil
}
filter.setValue(ciImage, forKey: kCIInputImageKey)
filter.setValue(CIVector(cgPoint: topLeft), forKey: "inputTopLeft")
filter.setValue(CIVector(cgPoint: topRight), forKey: "inputTopRight")
filter.setValue(CIVector(cgPoint: bottomLeft), forKey: "inputBottomLeft")
filter.setValue(CIVector(cgPoint: bottomRight), forKey: "inputBottomRight")
guard let outputImage = filter.outputImage else {
return nil
}
let context = CIContext(options: [.useSoftwareRenderer: false])
guard let outputCGImage = context.createCGImage(outputImage, from: extent) else {
return nil
}
let result = NSImage(cgImage: outputCGImage, size: extent.size)
print("Perspective transform applied")
return result
}
}
// 7. Rounded Corners
class RoundedCorners {
static func applyRoundedCorners(_ image: NSImage, radius: CGFloat) -> NSImage? {
print("\n--- Rounded Corners ---")
print("Radius: \(radius)")
let roundedImage = NSImage(size: image.size)
roundedImage.lockFocus()
let rect = NSRect(origin: .zero, size: image.size)
let path = NSBezierPath(roundedRect: rect, xRadius: radius, yRadius: radius)
path.clip()
image.draw(in: rect, from: rect, operation: .copy, fraction: 1.0)
roundedImage.unlockFocus()
print("Applied rounded corners")
return roundedImage
}
static func makeCircular(_ image: NSImage) -> NSImage? {
print("\n--- Make Circular ---")
let minDimension = min(image.size.width, image.size.height)
let radius = minDimension / 2
// First crop to square
guard let squared = ImageCrop.cropToSquare(image) else {
return nil
}
// Then apply rounded corners
return applyRoundedCorners(squared, radius: radius)
}
}
// 8. Thumbnail Generation with Transformations
class ThumbnailGenerator {
static func generateThumbnail(_ image: NSImage, size: NSSize, mode: ThumbnailMode = .aspectFit) -> NSImage? {
print("\n--- Generate Thumbnail ---")
print("Target size: \(size), Mode: \(mode)")
switch mode {
case .aspectFit:
return ImageResize.resizeMaintainingAspectRatio(image, maxWidth: size.width, maxHeight: size.height)
case .aspectFill:
// Scale to fill, then crop center
let widthRatio = size.width / image.size.width
let heightRatio = size.height / image.size.height
let ratio = max(widthRatio, heightRatio)
let scaledSize = NSSize(
width: image.size.width * ratio,
height: image.size.height * ratio
)
if let scaled = ImageResize.resize(image, to: scaledSize),
let cropped = ImageCrop.cropToCenter(scaled, size: size) {
return cropped
}
case .stretch:
return ImageResize.resize(image, to: size)
}
return nil
}
enum ThumbnailMode {
case aspectFit
case aspectFill
case stretch
}
}
// 9. Image Composition
class ImageComposition {
static func overlay(_ baseImage: NSImage, overlay: NSImage, at position: NSPoint, alpha: CGFloat = 1.0) -> NSImage? {
print("\n--- Overlay Image ---")
print("Overlay position: \(position)")
print("Alpha: \(alpha)")
let compositedImage = NSImage(size: baseImage.size)
compositedImage.lockFocus()
// Draw base image
baseImage.draw(
in: NSRect(origin: .zero, size: baseImage.size),
from: NSRect(origin: .zero, size: baseImage.size),
operation: .copy,
fraction: 1.0
)
// Draw overlay
overlay.draw(
in: NSRect(origin: position, size: overlay.size),
from: NSRect(origin: .zero, size: overlay.size),
operation: .sourceOver,
fraction: alpha
)
compositedImage.unlockFocus()
print("Overlay applied")
return compositedImage
}
static func blend(_ image1: NSImage, _ image2: NSImage, mode: BlendMode = .normal) -> NSImage? {
print("\n--- Blend Images ---")
print("Mode: \(mode)")
guard let ciImage1 = CIImage(image: image1),
let ciImage2 = CIImage(image: image2) else {
return nil
}
let filter = CIFilter(name: "CIScreenBlendMode")
filter?.setValue(ciImage1, forKey: kCIInputImageKey)
filter?.setValue(ciImage2, forKey: kCIInputBackgroundImageKey)
guard let outputImage = filter?.outputImage else {
return nil
}
let context = CIContext()
guard let outputCGImage = context.createCGImage(outputImage, from: outputImage.extent) else {
return nil
}
return NSImage(cgImage: outputCGImage, size: image1.size)
}
enum BlendMode {
case normal
case multiply
case screen
case overlay
case darken
case lighten
}
}
// 10. Batch Image Transformations
class BatchTransformations {
static func processImages(in directory: String, operations: [(NSImage) -> NSImage?]) {
print("\n--- Batch Process Images ---")
let fileManager = FileManager.default
guard let files = try? fileManager.contentsOfDirectory(
at: URL(fileURLWithPath: directory),
includingPropertiesForKeys: nil
) else {
return
}
let imageFiles = files.filter { file in
["jpg", "jpeg", "png", "tiff"].contains(file.pathExtension.lowercased())
}
print("Processing \(imageFiles.count) images")
for file in imageFiles {
let path = file.path
guard let image = NSImage(contentsOfFile: path) else {
continue
}
var resultImage = image
for operation in operations {
if let processed = operation(resultImage) {
resultImage = processed
}
}
// Save result
let outputName = file.deletingPathExtension().lastPathComponent + "_processed"
let outputPath = (file.deletingLastPathComponent()).appendingPathComponent(outputName).appendingPathExtension("png")
if let tiffData = resultImage.tiffRepresentation,
let bitmap = NSBitmapImageRep(data: tiffData),
let outputData = bitmap.representation(using: .png, properties: [:]) {
try? outputData.write(to: URL(fileURLWithPath: outputPath))
print(" Saved: \(outputPath)")
}
}
print("Batch processing completed")
}
}
// Main demonstration
func demonstrateImageTransformations() {
print("=== macOS Swift Image Transformations Examples ===")
// Create a test image
let testImage = NSImage(size: NSSize(width: 400, height: 300))
testImage.lockFocus()
NSColor.blue.set()
NSRect(origin: .zero, size: NSSize(width: 400, height: 300)).fill()
NSColor.white.set()
NSRect(origin: NSPoint(x: 100, y: 100), size: NSSize(width: 200, height: 100)).fill()
testImage.unlockFocus()
// Resize
if let resized = ImageResize.resize(testImage, to: NSSize(width: 200, height: 150)) {
print("Resize: \(resized.size)")
}
// Crop
if let cropped = ImageCrop.crop(testImage, to: NSRect(x: 50, y: 50, width: 200, height: 150)) {
print("Crop: \(cropped.size)")
}
// Rotate
if let rotated = ImageRotation.rotate90(testImage) {
print("Rotated: \(rotated.size)")
}
// Flip
if let flipped = ImageFlip.flipHorizontal(testImage) {
print("Flipped: \(flipped.size)")
}
// Rounded corners
if let rounded = RoundedCorners.applyRoundedCorners(testImage, radius: 20) {
print("Rounded corners applied")
}
// Make circular
if let circular = RoundedCorners.makeCircular(testImage) {
print("Made circular: \(circular.size)")
}
// Thumbnail
if let thumbnail = ThumbnailGenerator.generateThumbnail(testImage, size: NSSize(width: 100, height: 100), mode: .aspectFit) {
print("Thumbnail: \(thumbnail.size)")
}
// Add padding
if let padded = ImagePadding.addPadding(testImage, padding: 20) {
print("Padded: \(padded.size)")
}
print("\n=== All Image Transformation Examples Completed ===")
}
// Run demonstration
demonstrateImageTransformations()