Archive for October 22, 2015

Thursday, October 22, 2015

Real-time Resizing of Flickr Images Using GPUs

Archie Russell:

The selection of sizes has grown semi-organically over the years, and all told, we serve eleven different resizes per photo which, in sum, use nearly as much storage as the original photo. Almost 90% of this storage is held in the handful of resizes 640px and larger, so we targeted our efforts at eliminating some of these sizes.

[…]

Instead we took on a pretty ambitious goal: maintain our largest resize, usually 2048px wide, as a source image and create any other moderate or large-sized resizes on-the-fly from this source, without sacrificing image quality or significantly affecting performance. Using the original uploaded photo as a resize source image was impractical, as these can be very large and exist in a variety of formats.

[…]

Our resize daemons transfer JPEGs from shared memory to GPU device memory. Once here, the real image processing takes place. The JPEGs are decoded, cropped, sharpened, resized, re-sharpened as needed, re-encoded as JPEGs, and finally transferred back to shared memory. From shared memory, our Apache module returns the resized JPEG to the caller.

[…]

With significant optimization, this code is able to resize our 2048px JPEGs to 1600px in under 16ms. This is more than 15x faster than GraphicsMagick and nearly 10x faster than Ymagine.

The 10 Best Feed Readers

Vicky Cassidy:

At their core, RSS reader apps let you subscribe to content from your favorite sites. Typically, they’ll download images and text from articles so you can read them offline, and will list all of the stories in chronological order. Many RSS apps then include tools to discover sites based on your favorite topics, and let you save favorite articles to reference later.

[…]

The beauty of hosted applications is that they’re easy to set up and use—simply sign up for the app and you’re ready to get started. The bad news is that you don’t own your data, and if the company decides to close up shop (like Google Reader did in 2013) you’ll have to start over again.

Currently, I’m using ReadKit and am happy with it except for the lack of AppleScript and share extension support—a common problem. I find that iOS is better for reading longer articles, and the Mac is much better for skimming and processing RSS feeds, so I haven’t used any of these iOS apps in years.

MVVM in Swift

Ash Furrow:

View models don’t have any access to the user interface. You should not even import UIKit in a view model. Typically, a view controller observes the view model somehow to know when there’s new data to display. This can be done through KVO or FRP.

[…]

My solution was to put the enum in the view model, and have the view model expose a signal defining which of the two layouts should be used. Based on the selected segment index, the view model decides which layout should be used and sends that value on a signal. The view controller is responsible for mapping that signal into a configured layout, then setting that layout on the collection view.

[…]

Defining these signals on a view model can be tricky. Swift initializers have strict rules around when properties are assigned. The signals need access to the internal state of the view model, so they need to be created after calling super.init(). However, we can’t call super.init() until all our properties have been assigned to, including the signal properties.

[…]

While writing tests, I found it difficult to subclass the existing view model (for stubbing purposes). Since the view model’s initializer has side-effects (starting recurring network requests), I can’t call super.init(). Instead, I made a ListingsViewModelType protocol. The view controller only interacts with the view model through this protocol – it has no reference to the class itself. Now creating a stubbed view model is as easy as conforming to a protocol.

GCD Sugar for Swift

Tobias Due Munk’s Async (via Swift Sandbox):

Async sugar looks like this:

Async.background {
    println("This is run on the background queue")
}.main {
    println("This is run on the main queue, after the previous block")
}

Instead of the familiar syntax for GCD:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), {
    println("This is run on the background queue")

    dispatch_async(dispatch_get_main_queue(), {
        println("This is run on the main queue, after the previous block")
    })
})

The way it work is by using the new notification API for GCD introduced in OS X 10.10 and iOS 8. Each chaining block is called when the previous queue has finished.

Update (2015-10-23): See also Run.

Searching Apple’s Stores With Google

Kirk McElhearn:

iTunes used to have a Power Search feature, but it has been removed from the iTunes app (though you can still access it this way). Power searching is really useful when you want to home in on something in the iTunes Store, App Store, or Mac App Store.

In the absence of a real power search, you can search another way: with Google. A Google search works because Apple has Web pages for all its iTunes Store content. With Google, you can search for more specific keywords and use quotes to search for specific phrases.