// // KMFileThumbManager.swift // PDF Reader Pro // // Created by Niehaoyu on 2024/11/22. // import Cocoa import CryptoKit class KMFileThumbManager: NSObject { let thumbFolderPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.applicationSupportDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).last?.stringByAppendingPathComponent(Bundle.main.bundleIdentifier!).stringByAppendingPathComponent("thumb") @objc public static let manager = KMFileThumbManager() private var iconSize: CGSize = CGSizeMake(126*3, 168*3) override init() { super.init() if (!FileManager.default.fileExists(atPath: thumbFolderPath!)) { try?FileManager.default.createDirectory(atPath: thumbFolderPath!, withIntermediateDirectories: true, attributes: nil) } refreshData() } private func refreshData() { let urls: Array = NSDocumentController.shared.recentDocumentURLs var fileNames: [String] = [] for url in urls { let filePath = url.path let fileName = filePath.getLastComponentDeleteExtension let resultPath = thumbFolderPath?.stringByAppendingPathComponent((fileName + ".png")) if (!FileManager.default.fileExists(atPath: resultPath!)) { updateFile(url, iconSize) } fileNames.append((fileName + ".png")) } if let contents = try?FileManager.default.contentsOfDirectory(atPath: thumbFolderPath!) { for name in contents { if name != ".DS_Store" { if let index = fileNames.firstIndex(of: name) { } else { if let path = thumbFolderPath?.stringByAppendingPathComponent(name) { try?FileManager.default.removeItem(atPath: path) } } } } } } private func generateThumbnail(for pdfURL: URL, _ size: NSSize) -> NSImage? { guard let pdfDocument = CGPDFDocument(pdfURL as CFURL), let pdfPage = pdfDocument.page(at: 1) else { return nil } let pageRect = pdfPage.getBoxRect(.mediaBox) // 创建图形上下文 let bitsPerComponent = 8 let bitmapInfo = CGImageAlphaInfo.premultipliedLast.rawValue let context = CGContext(data: nil, width: Int(size.width), height: Int(size.height), bitsPerComponent: bitsPerComponent, bytesPerRow: 0, space: CGColorSpaceCreateDeviceRGB(), bitmapInfo: bitmapInfo) // 绘制PDF页面 // context?.saveGState() // context?.translateBy(x: 0, y: size.height) // context?.scaleBy(x: 1.0, y: -1.0) // 反转坐标系 context?.scaleBy(x: size.width / pageRect.width, y: size.height / pageRect.height) // 缩放 context?.drawPDFPage(pdfPage) context?.restoreGState() // 创建NSImage if let cgImage = context?.makeImage() { return NSImage(cgImage: cgImage, size: NSSize(width: size.width, height: size.height)) } return nil } public func updateFile(_ fileURL: URL, _ iconSize: CGSize) { let filePath = fileURL.path let fileName = filePath.getLastComponentDeleteExtension if let resultPath: String = thumbFolderPath?.stringByAppendingPathComponent((fileName + ".png")) { if let image = generateThumbnail(for: fileURL, iconSize) { guard let data = image.tiffRepresentation else { return } let imageRep = NSBitmapImageRep(data: data) imageRep?.size = image.size if let imageData = imageRep?.representation(using: .png, properties: [:]) { try?imageData.write(to: URL(fileURLWithPath: resultPath)) } } } } public func getFileThumb(_ fileURL: URL) -> NSImage? { let filePath = fileURL.path let fileName = filePath.getLastComponentDeleteExtension if let resultPath: String = thumbFolderPath?.stringByAppendingPathComponent((fileName + ".png")) { return NSImage(contentsOf: URL(fileURLWithPath: resultPath)) } return nil } }