Sunday, April 19, 2026

Fast Thumbnails With CGImageSource

Max Seelemann:

The parameters are documented, but the optimal combination is not. Here’s what I learned:

  • kCGImageSourceCreateThumbnailFromImageAlways: While this seems optional for correct functionality, without it there will be error logged for images that might include embedded thumbnails (like JPEG or HEIC), but don’t. There’s a FromImageIfAbsent variant, but it did not silence these logs in all cases.
  • kCGImageSourceCreateThumbnailWithTransform: Required for the thumbnail to respect the EXIF orientation of the image, in case it has one (which is not uncommon for JPEG).
  • kCGImageSourceThumbnailMaxPixelSize: Specifies the largest dimension of the desired thumbnail; the returned image will then be equal or smaller than this.

The first test showed incredible improvements: The same 12MP JPEG image now took just about 26ms on macOS. That’s almost 30 times faster than the naive approach.

Image I/O has some very useful APIs, although unfortunately it hasn’t always been well tested. I ended up writing four different versions of an image resizer because different parts of the API would fail on certain files with different macOS versions. The resizer keeps trying different techniques until it finds one that works. Also, sometimes the APIs raise C++ exceptions. If you don’t catch these from Objective-C using @catch (...) (literally, three periods), your app will crash.

Brent Simmons:

Avoid bug in CGImageSourceCreateImageAtIndex with indexed-color (4-bit palette) ICO files — always use CGImageSourceCreateThumbnailAtIndex.

Previously:

1 Comment RSS · Twitter · Mastodon


I saw this was about thumbnails and immediately though of my old thumbnailing code…and it's been so long that I forgot I used vImage instead of CGImage! I've not tested performance in a decade, so it would be interesting to see how it stacks up against modern APIs. I profiled the snot out of the framework with Shark and MallocDebug, since I was producing scaled thumbnails at multiple sizes, but vImage was not easy to use.

https://github.com/amaxwell/fileview/blob/master/FVCGImageUtilities.mm
https://github.com/amaxwell/fileview/blob/master/FVImageBuffer.h

Leave a Comment