Zouhair Sassi
Zouhair Sassi

Reputation: 1411

How to Create thumbnail from local files

I want to create a thumbnail image for files (word, excel, video ....) This what i did:

import QuickLook

class ThumbsCreator:  NSObject {

    private var file : File?

    init(file: File?) {
        super.init()
        self.file = file
    }

    func createThumb() {
     let url = URL(string: (self.file?.path()))
 }  
}

Upvotes: 5

Views: 6349

Answers (4)

Ceylo
Ceylo

Reputation: 412

Starting from iOS 13 and macOS 10.15, there is the QuickLook Thumbnailing API. It supports any file format for which the OS can provide a preview: either because the OS knows this format or because the owner of the third-party format provided a QuickLook plugin.

Here is an example based on Apple's tutorial:

func thumbnail(for fileURL: URL, size: CGSize, scale: CGFloat) {
    let request = QLThumbnailGenerator
        .Request(fileAt: fileURL, size: size, scale: scale,
                 representationTypes: .lowQualityThumbnail)

    QLThumbnailGenerator.shared.generateRepresentations(for: request)
    { (thumbnail, type, error) in
        DispatchQueue.main.async {
            if thumbnail == nil || error != nil {
                // Handle the error case gracefully.
            } else {
                // Display the thumbnail that you created.
            }
        }
    }
}

On macOS before 10.15, in my app I fallback to NSWorkspace.shared.icon(forFile:) which provides a document icon based on the file type (but not a thumbnail).

Upvotes: 7

Zouhair Sassi
Zouhair Sassi

Reputation: 1411

After a lot of search, I found this solution :

import PDFKit
import AVKit
import WebKit

func createThumb() {
     let url = URL(string: (self.file?.path()))
     switch file?.type {
     case: FileType.image.rawValue:
          let image = UIImage(contentsOfFile: (url?.path)!)
          _finalImage = self.createScaledImage(image: image!)
          break 
     case: FileType.office.rawValue:  
          //Loading.......
          break
     case FileType.Pdf.rawValue:
          guard let doc = PDFDocument(url: url!) else {return}
          guard let page = doc.page(at: 0) else {return}
          _finalImage = page.thumbnail(of: CGSize(width: 768, height: 1024), for: .cropBox)
          break
     case: FileType.video.rawValue:
          let asset = AVAsset(url: url!)
          let imageGenerator = AVAssetImageGenerator(asset: asset)
          imageGenerator.appliesPreferredTrackTransform = true
          let time = CMTime(seconds: 2, preferredTimescale: 1)
          do {
          let imageRef = try imageGenerator.copyCGImage(at: time, actualTime: nil)
          _finalImage = UIImage(cgImage: imageRef)
          } catch let error{
            print("Error: \(error)")
          }
         break

}
 } 

func createScaledImage(image: UIImage) {

    let THUMB_WIDTH = 150.0 - 40.0
    let THUMB_HEIGHT = THUMB_WIDTH - 23.0
    var itemThumb = resizeImage(image: image, constraintSize: CGSize(width: THUMB_WIDTH, height: THUMB_HEIGHT))
    let thumbRect = CGRect(x: 0, y: 0, width: 10, height: 10)
    UIGraphicsBeginImageContextWithOptions(thumbRect.size, true, 0.0)
    let context = UIGraphicsGetCurrentContext()

    // Fill a white rect
    context?.setFillColor(gray: 1.0, alpha: 1.0)
    context?.fill(thumbRect)

    // Stroke a gray rect
    let comps : [CGFloat] = [0.8, 0.8, 0.8, 1]
    let colorSpace = CGColorSpaceCreateDeviceRGB()
    let strokeColor = CGColor(colorSpace: colorSpace, components: comps)
    context?.setStrokeColor(strokeColor!)
    UIRectFrame(thumbRect)
    //CGColorRelease(strokeColor!)

    itemThumb.draw(in: thumbRect.insetBy(dx: 1, dy: 1))

    itemThumb = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()
    self.finishThumCreation(image: image)
} 
}

Upvotes: 6

Shehata Gamal
Shehata Gamal

Reputation: 100533

You can use https://developer.apple.com/documentation/uikit/uidocumentinteractioncontroller/1616801-icons

var icons: [UIImage] { get }


let controller = UIDocumentInteractionController(url:someUrl) 
print(controller.icons.first)

Only for a video

extension UIViewController {

    func thumbnail(_ sourceURL:URL) -> UIImage {
        let asset = AVAsset(url: sourceURL)
        let imageGenerator = AVAssetImageGenerator(asset: asset)
        imageGenerator.appliesPreferredTrackTransform = true
        let time = CMTime(seconds: 1, preferredTimescale: 1)

        do {
            let imageRef = try imageGenerator.copyCGImage(at: time, actualTime: nil)
            return UIImage(cgImage: imageRef)
        } catch {
            print(error)
            return UIImage(named: "NoVideos")!
        }
    }

}

Upvotes: 3

Thomas Deniau
Thomas Deniau

Reputation: 2573

There's no good API for this yet. There is NSURLThumbnailDictionaryKey, but YMMV. You can indeed get icons via UIDocumentInteractionController.

Upvotes: 0

Related Questions