Duck
Duck

Reputation: 35953

Creating a thumbnail from UIImage using CGImageSourceCreateThumbnailAtIndex

I want to use the function CGImageSourceCreateThumbnailAtIndex to create a thumbnail from an UIImage. All I have is the UIImage itself. The image is the snapshot on a UIView.

Please, I don't want to use any other method to create the thumbnail, just the one using CGImageSourceCreateThumbnailAtIndex, because I want to compare its performance with the other methods I already have.

Said that, this is the code I have so far.

I have create a UIImage category with this code:

- (UIImage *)createSquaredThumbnailWithWidth:(NSInteger)width {

  CFDictionaryRef options = (__bridge CFDictionaryRef) @{
                                                         (id) kCGImageSourceCreateThumbnailWithTransform : @YES,
                                                         (id) kCGImageSourceCreateThumbnailFromImageAlways : @YES,
                                                         (id) kCGImageSourceThumbnailMaxPixelSize : @(width)
                                                         };

  CGImageRef scaledImageRef = CGImageSourceCreateThumbnailAtIndex(????, 0, options);


  UIImage* scaled = [UIImage imageWithCGImage:scaledImageRef];

  CGImageRelease(scaledImageRef);

  return scaled;
}

My problem is with this line:

  CGImageRef scaledImageRef = CGImageSourceCreateThumbnailAtIndex(????, 0, options);

The first parameter of this function demands a CGImageSourceRef, but like I said, I just have an UIImage, that image is on memory, not on disk, and I don't want to save it to disk, or the performance will go down the drain.

How do I get a CGImageSourceRef from a UIImage that is on memory???

Upvotes: 7

Views: 15985

Answers (4)

Wladislaw
Wladislaw

Reputation: 1250

Swift and iOS 15

func preparingThumbnail(of size: CGSize) -> UIImage?

Example would be:

let image = UIImage(named: "info")
image.preparingThumbnail(of size: CFSize(width: 300, height: 400))

Upvotes: 1

Nirav D
Nirav D

Reputation: 72410

Have you try using CGImageSourceCreateWithData and passing image data as CFDataRef like this:

Note: Using CGImageSourceCreateWithData loses information about image rotation, use the CGImageSourceCreateWithURL for hassle free rotation of final image.

NSData *imageData = UIImagePNGRepresentation(image);
CGImageSourceRef src = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL);
CFDictionaryRef options = (__bridge CFDictionaryRef) @{
                                                     (id) kCGImageSourceCreateThumbnailWithTransform : @YES,
                                                     (id) kCGImageSourceCreateThumbnailFromImageAlways : @YES,
                                                     (id) kCGImageSourceThumbnailMaxPixelSize : @(width)
                                                     };

CGImageRef scaledImageRef = CGImageSourceCreateThumbnailAtIndex(src, 0, options);
CFRelease(src);
UIImage *scaled = [UIImage imageWithCGImage:scaledImageRef];
CGImageRelease(scaledImageRef);
return scaled;

Note: If you have URL of image then you can create CGImageSourceRef using CGImageSourceCreateWithURL.

CGImageSourceRef src = CGImageSourceCreateWithURL((__bridge CFURLRef)(imageFileURL), NULL);

Upvotes: 12

Siempay
Siempay

Reputation: 1002

Swift 5.1 extension

based on Ivan's answer

extension UIImage {

  func getThumbnail() -> UIImage? {

    guard let imageData = self.pngData() else { return nil }

    let options = [
        kCGImageSourceCreateThumbnailWithTransform: true,
        kCGImageSourceCreateThumbnailFromImageAlways: true,
        kCGImageSourceThumbnailMaxPixelSize: 300] as CFDictionary

    guard let source = CGImageSourceCreateWithData(imageData as CFData, nil) else { return nil }
    guard let imageReference = CGImageSourceCreateThumbnailAtIndex(source, 0, options) else { return nil }

    return UIImage(cgImage: imageReference)

  }
}

Upvotes: 16

Ivan Vavilov
Ivan Vavilov

Reputation: 1649

Swift 4 code

let imageData = UIImagePNGRepresentation(image)!
let options = [
    kCGImageSourceCreateThumbnailWithTransform: true,
    kCGImageSourceCreateThumbnailFromImageAlways: true,
    kCGImageSourceThumbnailMaxPixelSize: 300] as CFDictionary
let source = CGImageSourceCreateWithData(imageData, nil)!
let imageReference = CGImageSourceCreateThumbnailAtIndex(source, 0, options)!
let thumbnail = UIImage(cgImage: imageReference)

Upvotes: 24

Related Questions