// // FileUtils.swift // SimpleX (iOS) // // Created by JRoberts on 15.04.2022. // Copyright © 2022 SimpleX Chat. All rights reserved. // import Foundation import SwiftUI // maximum image file size to be auto-accepted let maxImageSize = 236700 let maxFileSize = 1893600 func getDocumentsDirectory() -> URL { return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! } func getAppFilesDirectory() -> URL { return getDocumentsDirectory().appendingPathComponent("app_files", isDirectory: true) } func getStoredFilePath(_ file: CIFile?) -> String? { if let file = file, file.stored, let savedFile = file.filePath { return getAppFilesDirectory().appendingPathComponent(savedFile).path } return nil } func getStoredImage(_ file: CIFile?) -> UIImage? { if let filePath = getStoredFilePath(file) { return UIImage(contentsOfFile: filePath) } return nil } // image utils func dropImagePrefix(_ s: String) -> String { dropPrefix(dropPrefix(s, "data:image/png;base64,"), "data:image/jpg;base64,") } private func dropPrefix(_ s: String, _ prefix: String) -> String { s.hasPrefix(prefix) ? String(s.dropFirst(prefix.count)) : s } func cropToSquare(_ image: UIImage) -> UIImage { let size = image.size let side = min(size.width, size.height) let newSize = CGSize(width: side, height: side) var origin = CGPoint.zero if size.width > side { origin.x -= (size.width - side) / 2 } else if size.height > side { origin.y -= (size.height - side) / 2 } return resizeImage(image, newBounds: CGRect(origin: .zero, size: newSize), drawIn: CGRect(origin: origin, size: size)) } func resizeImageToDataSize(_ image: UIImage, maxDataSize: Int) -> Data? { var img = image var data = img.jpegData(compressionQuality: 0.85) var dataSize = data?.count ?? 0 while dataSize != 0 && dataSize > maxDataSize { let ratio = sqrt(Double(dataSize) / Double(maxDataSize)) let clippedRatio = min(ratio, 2.0) img = reduceSize(img, ratio: clippedRatio) data = img.jpegData(compressionQuality: 0.85) dataSize = data?.count ?? 0 } logger.debug("resizeImageToDataSize final \(dataSize)") return data } func resizeImageToStrSize(_ image: UIImage, maxDataSize: Int) -> String? { var img = image var str = compressImageStr(img) var dataSize = str?.count ?? 0 while dataSize != 0 && dataSize > maxDataSize { let ratio = sqrt(Double(dataSize) / Double(maxDataSize)) let clippedRatio = min(ratio, 2.0) img = reduceSize(img, ratio: clippedRatio) str = compressImageStr(img) dataSize = str?.count ?? 0 } logger.debug("resizeImageToStrSize final \(dataSize)") return str } func compressImageStr(_ image: UIImage, _ compressionQuality: CGFloat = 0.85) -> String? { if let data = image.jpegData(compressionQuality: compressionQuality) { return "data:image/jpg;base64,\(data.base64EncodedString())" } return nil } private func reduceSize(_ image: UIImage, ratio: CGFloat) -> UIImage { let newSize = CGSize(width: floor(image.size.width / ratio), height: floor(image.size.height / ratio)) let bounds = CGRect(origin: .zero, size: newSize) return resizeImage(image, newBounds: bounds, drawIn: bounds) } private func resizeImage(_ image: UIImage, newBounds: CGRect, drawIn: CGRect) -> UIImage { let format = UIGraphicsImageRendererFormat() format.scale = 1.0 format.opaque = true return UIGraphicsImageRenderer(bounds: newBounds, format: format).image { _ in image.draw(in: drawIn) } }