How to Merge Images into PDF on iOS using Swift
Sometimes, we may need to merge multiple images into a single PDF file. For example, we scan the front side and the back side of an ID card and want to store them in a single PDF file.
In this article, we are going to talk about how to build an iOS app using Swift to merge images into a PDF file with the help of Dynamsoft Document Normalizer.
New Project
Open Xcode and create a new app project.
Add Dependencies
Next, add Dynamsoft Document Normalizer and its dependencies via cocoapods.
-
Init a pod project.
pod init
-
Add the following to
Podfile
.target 'PDFCreator' do pod 'DynamsoftCaptureVisionRouter','2.2.30' pod 'DynamsoftCore','3.2.30' pod 'DynamsoftDocumentNormalizer','2.2.11' pod 'DynamsoftImageProcessing','2.2.30' pod 'DynamsoftLicense','3.2.20' pod 'DynamsoftUtility','1.2.20' end
-
Install the pods.
pod install
UI Design
Open Main.storyboard
and add the following controls:
It contains a button to select images from the gallery, a switch to enable auto cropping of the document in the image and a picker view to select which color mode to use for the images in the PDF.
The picker view is configured with the following code:
@IBOutlet weak var colorModeUIPickerView: UIPickerView!
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return 3
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int,
forComponent component: Int) -> String? {
if row == 0 {
return "Black & White"
}else if row == 1 {
return "Grayscale"
}else{
return "Color"
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
colorModeUIPickerView.dataSource = self
colorModeUIPickerView.delegate = self
}
Pick Images from Gallery
Here, we use PHPickerViewController
to pick multiple images.
@IBAction func selectImagesUIButton_clicked(_ sender: Any) {
var configuration = PHPickerConfiguration(photoLibrary: .shared())
//0 - unlimited 1 - default
configuration.selectionLimit = 0
configuration.filter = .images
let pickerViewController = PHPickerViewController(configuration: configuration)
pickerViewController.delegate = self
present(pickerViewController, animated: true)
}
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
print(results.count)
picker.dismiss(animated: true)
}
We can convert the results into an array of UIImage for further use.
DispatchQueue.main.async {
var images:[UIImage] = []
var processed = 0
let size = results.count
for item in results {
if (item.itemProvider.canLoadObject(ofClass: UIImage.self)) {
item.itemProvider.loadObject(ofClass: UIImage.self) { image , error in
if let error{
print(error)
}
if let selectedImage = image as? UIImage{
print(selectedImage.size)
images.append(selectedImage)
processed = processed + 1
}
}
}
}
}
Use Dynamsoft Document Normalizer to Merge Images into PDF
-
Initialize the license for Dynamsoft Document Normalizer in
AppDelegate.swift
. You can apply for a license here.import DynamsoftLicense func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. let oneDayTrial = "LICENSE-KEY" LicenseManager.initLicense(oneDayTrial, verificationDelegate: self) return true } func onLicenseVerified(_ isSuccess: Bool, error: (any Error)?) { if isSuccess == false { print("license invalid") }else{ print("license valid") } }
-
Create an instance of Capture Vision Router to call Dynamsoft Document Normalizer.
import DynamsoftCore import DynamsoftCaptureVisionRouter let cvr:CaptureVisionRouter = CaptureVisionRouter()
-
Process images and save them to a PDF file. It uses Capture Vision Router to process the images, uses Image Manager to save them to a PDF file and then share it so that we can save the PDF file to
Files
.If
enableAutoCroppingUISwitch
is on, it will detect the document boundaries and get the cropped image. Otherwise, process the whole image.It also updates the color mode. Converting an image to black and white can clean the background and save the file’s size while converting to grayscale has a balance of details and size.
import DynamsoftDocumentNormalizer import DynamsoftUtility func mergeImagesIntoPDF(images:[UIImage]) { var enableAutoCropping = false var selectedColorModeIndex = 0 DispatchQueue.main.sync { statusLabel.text = "Processing..." if enableAutoCroppingUISwitch.isOn { enableAutoCropping = true } selectedColorModeIndex = colorModeUIPickerView.selectedRow(inComponent: 0) } let templateName:String; if enableAutoCropping { templateName = PresetTemplate.detectAndNormalizeDocument.rawValue }else{ templateName = PresetTemplate.normalizeDocument.rawValue } var settings = try? cvr.getSimplifiedSettings(templateName) if selectedColorModeIndex == 0 { settings?.documentSettings?.colourMode = ImageColourMode.binary }else if selectedColorModeIndex == 1 { settings?.documentSettings?.colourMode = ImageColourMode.grayscale }else{ settings?.documentSettings?.colourMode = ImageColourMode.colour } if enableAutoCropping == false { settings?.roi = Quadrilateral(pointArray: [CGPoint(x:0,y:0),CGPoint(x:100,y:0),CGPoint(x:100,y:100),CGPoint(x:0,y:100)]) settings?.roiMeasuredInPercentage = true } try? cvr.updateSettings(templateName, settings: settings!) let imageManager = ImageManager() let url = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString) .appendingPathExtension("pdf") for image in images { let capturedResult:CapturedResult = cvr.captureFromImage(image, templateName: templateName) let items = capturedResult.items ?? [] for item in items { if item.type == CapturedResultItemType.normalizedImage { let image:NormalizedImageResultItem = item as! NormalizedImageResultItem try? imageManager.saveToFile(image.imageData!, path: url.path, overWrite: true) } } } DispatchQueue.main.async { self.statusLabel.text = "" let objectsToShare = [url] let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil) self.present(activityVC, animated: true, completion: nil) } }
Screenshot of converted files:
Source Code
You can check out the source code to have a try: https://github.com/tony-xlh/Merge-Images-to-PDF/tree/main/iOS/PDFCreator