iOS এর জন্য ফটো ফিল্টার অ্যাপ তৈরি

অ্যাপল প্লাটফর্মে ইমেজ নিয়ে কাজ করার জন্য রয়েছে কোর ইমেজ ফ্রেমওয়ার্ক। যেখানে বিল্টইন ২০০+ ফিল্টার রয়েছে। প্রয়োজন অনুযায়ী যেগুলো আমরা আমাদের প্রজেক্টে ব্যবহার করতে পারি। এমনকি চাইলে নিচের মত করে সব গুলো ফিল্টারের লিস্ট বের করতে পারিঃ

Button("All available filters"){
                      print(CIFilter.filterNames(inCategory: nil))
     }

পুরা উদাহরণঃ

import SwiftUI
import CoreImage

struct ContentView: View {
    var body: some View {
        Button("All available filters"){
            print(CIFilter.filterNames(inCategory: nil))
        }
    }
}

আমরা দেখব ২০০+ ফিল্টারের লিস্ট।  যেমন একটা ইমেজে Sepia ফিল্টার প্রয়োগ করার জন্য এভাবে কোড লিখতে পারিঃ

import SwiftUI
import CoreImage
import CoreImage.CIFilterBuiltins

struct ContentView: View {
    @State private var originalImage = UIImage(named: "cat") // Replace with your image name
    @State private var filteredImage: UIImage?
    
    var body: some View {
        VStack {
            if let filteredImage = filteredImage {
                Image(uiImage: filteredImage)
                    .resizable()
                    .scaledToFit()
            } else if let originalImage = originalImage {
                Image(uiImage: originalImage)
                    .resizable()
                    .scaledToFit()
            }

            Button("Apply Sepia Filter") {
                if let originalImage = originalImage {
                    self.filteredImage = applySepiaFilter(to: originalImage)
                }
            }
            .padding()
            .background(Color.blue)
            .foregroundColor(.white)
            .cornerRadius(8)
        }
    }
    
    // Function to apply a sepia filter using Core Image
    func applySepiaFilter(to image: UIImage) -> UIImage? {
        let context = CIContext() // Core Image context
        let filter = CIFilter.sepiaTone() // Sepia filter
        filter.intensity = 0.8 // Adjust intensity (0.0 to 1.0)

        guard let ciImage = CIImage(image: image) else { return nil }
        filter.inputImage = ciImage

        // Get the filtered image
        guard let outputImage = filter.outputImage,
              let cgImage = context.createCGImage(outputImage, from: outputImage.extent) else {
            return nil
        }

        return UIImage(cgImage: cgImage)
    }
}

উপরের কোডে  let filter = CIFilter.sepiaTone() এর যায়গায় অন্য যে কোন ফিল্টার প্রয়োগ করতে পারি। যেমন ব্লার করার জন্য লিখব CIFilter.gaussianBlur()। আবার ফিল্টারের ইন্টেনসিটিও পরিবর্তন করতে পারি। যেটা 0 থেকে 1 পর্যন্ত যে কোন ভ্যালু দিয়ে সেট করতে পারব। 1 মানে সর্বোচ্চ ইন্টেন্সিটি।

সাধারণ ফটো ফিল্টার অ্যাপে ইমেজ সিলেক্ট করার অপশন থাকে, ইমেজ সেভ করার অপশন থাকে। আবার থাকে ফিল্টার গুলো ডেমো। ইমেজ সিলেক্ট করা, ইমেজ সেভ করার উদাহরণ সহ পূর্নাঙ্গ কোডঃ

import SwiftUI
import PhotosUI
import CoreImage
import CoreImage.CIFilterBuiltins

struct ContentView: View {
    @State private var selectedItem: PhotosPickerItem?
    @State private var editedImage: UIImage?
    @State private var originalImage: UIImage?  // Store original image
    
    @State private var contrast: Float = 1.0
    @State private var brightness: Float = 0.0
    @State private var saturation: Float = 1.0
    
    let filterTypes: [(String, CIFilter)] = [
        ("Original", CIFilter.colorControls()),  // Use the stored original image
        ("Sepia", CIFilter.sepiaTone()),
        ("Mono", CIFilter.photoEffectMono()),
        ("Noir", CIFilter.photoEffectNoir()),
        ("Bloom", CIFilter.bloom()),
        ("Blur", CIFilter.gaussianBlur())
    ]
    
    var body: some View {
        ScrollView{
            
            HStack(spacing: 30){
                PhotosPicker("Select Image", selection: $selectedItem, matching: .images)
                    .padding()
                if let image = editedImage{
                    Button {
                        UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
                    } label: {
                        Label("Save", systemImage: "photo")
                    }
                }
            }
            
            if let image = editedImage {
                Image(uiImage: image)
                    .resizable()
                    .scaledToFit()
                    .frame(height: 250)
                    .border(Color.gray, width: 1)
                
                
                ScrollView(.horizontal, showsIndicators: false) {
                    LazyHStack{
                        ForEach(filterTypes, id: \.0) { filterName, filter in
                            VStack {
                                if let filtered = applyFilter(filter, to: image, isOriginal: filterName == "Original") {
                                    Image(uiImage: filtered)
                                        .resizable()
                                        .scaledToFill()
                                        .frame(width: 80, height: 80)
                                        .clipped()
                                        .border(Color.gray, width: 1)
                                        .onTapGesture {
                                            self.editedImage = filtered
                                        }
                                }
                                Text(filterName).font(.caption)
                            }
                        }
                    }
                }.padding()
                
                VStack {
                    SliderControl(title: "Contrast", value: $contrast, range: 0.5...2.0, onChange: applyAdjustments)
                    SliderControl(title: "Brightness", value: $brightness, range: -1.0...1.0, onChange: applyAdjustments)
                    SliderControl(title: "Saturation", value: $saturation, range: 0.0...2.0, onChange: applyAdjustments)
                }
                .padding()
            }
        }
        .onChange(of: selectedItem) { oldItem, newItem in
            Task {
                if let data = try? await newItem?.loadTransferable(type: Data.self),
                   let image = UIImage(data: data) {
                    self.editedImage = image
                    self.originalImage = image  // Save the original image
                }
            }
            
        }
    }
    func applyFilter(_ filter: CIFilter, to image: UIImage?, isOriginal: Bool = false) -> UIImage? {
        guard let image = image else { return nil }
        let ciImage = CIImage(image: isOriginal ? originalImage ?? image : image)
        let context = CIContext()
        filter.setValue(ciImage, forKey: kCIInputImageKey)
        
        if let outputImage = filter.outputImage,
           let cgImage = context.createCGImage(outputImage, from: outputImage.extent) {
            return UIImage(cgImage: cgImage)
        }
        return nil
    }
    
    func applyAdjustments() {
        if let image = editedImage, let ciImage = CIImage(image: image) {
            let filter = CIFilter.colorControls()
            filter.inputImage = ciImage
            filter.contrast = contrast
            filter.brightness = brightness
            filter.saturation = saturation
            let context = CIContext()
            if let outputImage = filter.outputImage,
               let cgImage = context.createCGImage(outputImage, from: outputImage.extent) {
                self.editedImage = UIImage(cgImage: cgImage)
            }
        }
    }
}


struct SliderControl: View {
    let title: String
    @Binding var value: Float
    let range: ClosedRange<Float>
    let onChange: () -> Void
    
    var body: some View {
        VStack {
            Text("\(title): \(String(format: "%.2f", value))").font(.caption)
            Slider(value: $value, in: range, onEditingChanged: { _ in onChange() })
        }
    }
}

যার আউটপুট পাবো এমনঃ

ফটো গ্যালারিতে ইমেজ সেভ করার জন্য Info.plist এ প্রাইভেসি ডেসক্রিপশন যোগ করতে হবে।

যেমন We need access to your Photo Library to save images. লেখা যোগ করতে পারি। এই তো, হয়ে গেলো একটা মিনিমাল ফটো ফিল্টার অ্যাপ। যদিও আমি উদাহরণ হিসেবে iOS ব্যবহার করেছি, তবে একই কোড macOS এও কাজ করবে। SwiftUI ব্যবহার করে iOS অ্যাপ ডেভেলপমেন্ট শেখার জন্য প্র্যাক্টিক্যাল SwiftUI ই-বুক দেখতে পারেন। যেখানে প্রতিটা অধ্যায় একটি করে অ্যাপ তৈরি করা শেখানো হয়েছে। 🙂

Leave a Reply