Guest Blog Post: The Story Behind Claquette – Animated Screenshots

[Note: This is a guest blog post written by Thomas Zoechling (@weichsel on twitter), a macOS developer based in Austria, about his Mac app Claquette]

Claquette Mac App Icon

Animated GIF is not a good video format.
Actually it even isn’t a proper video format because it lacks random access and audio support. Nonetheless animated GIFs experienced a rennaisance in recent years.
My theory is, that the format’s success doesn’t stem from the features it has, but from the ones it lacks:

  • No random access: Defaults to autoplay – No playback interaction needed
  • No sound: Guarantees silence – Always “Safe for Work”
  • No support for 32bit colors: Moderate file sizes and a characteristic look

Given those constraints, GIFs are a great way to communicate simple concepts or interactions.
Want to showcase an animation or an application feature? Instead of a static screenshot with paragraphs of text, a 3 second GIF works equally well and also draws more attention.

In my daily life as software developer, I often need a quick way to capture graphical bugs. Those clips can be easily shared with colleagues or included with bug reports.
Sometimes it’s also simpler to attach a GIF to customer support requests instead of explaining how a certain feature works.
To cover my own needs, I wrote a small macOS application that allows me to record the screen and export the result as animated GIF. The app uses a custom recording codec and also covers the rest of the GIF creation workflow like crop, trim and file size optimization.

You can download Claquette from the Mac App Store. For detailed product information, please visit our website.

Development

When I started to implement the Animated GIF feature for Claquette, I began with a naïve approach.
Armed with several years of experience in writing Objective-C and some knowledge about video APIs on the Mac, I wrote a small prototype.
That first version just read a video file frame by frame and sent the resulting frames to ImageIO. ImageIO is a system framework that supports reading and writing several file formats.
It also comes with a basic Animated GIF encoder and so I decided to skip any third party libraries and just use the built-in mechanisms of macOS.
I was able to come up with a working prototype in a single afternoon. The program was just a simple command line utility, but it was able to turn an arbitrary video file into an animated GIF.

There was just one problem… Or actually there were several of them: Due to the inner workings of ImageIO, the program used vast amounts of memory. Also, the encoding took very long and the files it created were huge. On top of all that, the resulting GIFs looked horrible.
So while it only took me one Sunday afternoon to create a working prototype, it took me several months to fix the above issues. Especially the large file size and the bad visual appearance of the resulting GIFs required a lot of research.

Getting the most out of a 30 year old file format

The original GIF specification (GIF87a) was written in 1987 – almost 30 years ago. Animation features were added in GIF89a, which is still the most recent version of the format.
So how is it possible that a file format designed for low resolution screens and 256 colors is still in use today?
It turns out that the GIF specification contains some sections that open room for exploitation. Additionally, the visual nature of GIFs allows for optimizations to trick human color perception.

The format is simple and has the following basic structure:

  1. Header
  2. Logical Screen Descriptor
  3. Global Color Table
  4. Graphic Control Extension (Frame #1)
    – Delay
    – Disposal Method
    – Local Color Table
    – Image Descriptor
    – Image Data
  5. Graphic Control Extensions (Frame #2)
  6. Graphic Control Extension (Frame #3)
  7. … (1 GCE for each animation frame)
  8. Trailer

Header and Trailer are basically just magic numbers that mark the start and the end of the file. The Logical Screen Descriptor contains some general image information like width, height and background color. The Global Color Table is a simple list of colors that may contain a maximum of 256 entries.
Main image information is stored in one or more Graphic Control Extension blocks.

Color Table Generation

The color table sections of the format specification are a good starting point to optimize the visual quality of an animated GIF.
Both palettes are restricted by the format’s infamous 256 color limit. When reducing an image that uses 32bit (16.777.216 colors, 256 alpha values) to 8bit (255 colors, 1 alpha bit) it becomes really important which colors you leave out. The process of reducing large palettes to small ones is called Color Quantization. Choosing a good quantization algorithm is crucial when aiming for visually similar images with a reduced palette.
Naïve quantization implementations are based on occurrence, where seldom used colors are left out in the final image. More elaborate algorithms use techniques like dimensional clustering or tree partitioning.

When developing for Apple devices there are several libraries that provide color quantization functionality. macOS and iOS even have basic color quantization algorithms built-in. Apple’s implementation is part of the ImageIO framework’s CGImageDestination API.

The following sample images were created using different quantization techniques. They illustrate the quality impact of the used algorithm on the final image.

CGImageDestination Quantization

The first image shows the output of CGImageDestination. The resulting colors are noticeably off. Apple’s encoder also messes up the transparency color in the GIF palette, which leads to holes in some areas of the image (e.g. the titlebar).

FFmpeg Quantization

The open source library FFmpeg also includes a color quantizer. FFmpeg produces way better results than CGImageDestination. The colors are more vibrant and the transparency color is set correctly.

Claquette Quantization

The color quantization library used by Claquette also outputs a good choice of colors. Additionally the app performs color matching to avoid color shifts and to guarantee correct gamma values.

Frame Difference Calculation

Another important factor during GIF generation is efficient frame difference calculation.
The disposal mode in the Graphic Control Extension allows an encoder to specify how the context is set up before the next frame gets rendered.
GIF89a defines 4 disposal modes:

  • Unspecified: Replaces the existing canvas with the full contents of the current frame.
  • Do not Dispose: Leaves the existing canvas as-is and composites the current (sub)frame over it.
  • Restore to Background: Sets a defined background color and draws the current frame. Areas outside of the subsection in the Image Descriptor shine through.
  • Restore to Previous: Fully restores the canvas to the last frame that did not specify a disposal method.

The Image Descriptor section can be used to define a sub-image which does not provide pixel data for a full frame. Instead it contains coordinates and pixel data for a subsection of the full image.
By using frame differences and sub-images with a proper disposal mode, redundant image data can be avoided. Depending on the nature of the input video, this can greatly reduce the file size of the final GIF.
Modern video codecs like H.264 use techniques like macro blocks and motion compensation. Those methods introduce small errors that propagate from frame to frame. Propagated errors show up as noise when calculating frame diffs and eventually lead to unnecessary large files.
Claquette uses a custom lossless codec, that only stores regions that actually changed. This guarantees exact frame diffs.

The following images show the difference between frame #1 and frame #2 of a screen recording. The only effective change between those frames is a change in the mouse cursor location. An exact diff should therefore only contain an offsetted cursor image.

FFmpeg Diff

The above diff image was created between 2 frames of an H.264 encoded movie. The visible noise is a result of intra-frame encoding errors.

Claquette Diff

The second image was created by Claquette’s image diff algorithm. It only contains the mouse cursor – The only image element that actually changed between frame #1 and #2.

Finishing Touches

After implementing technical details like encoding and optimization, there were still some features missing. Claquette needed an editing UI to handle the whole GIF creation workflow.
As I wanted to keep the app lightweight and simple to use, I decided to add only a small set of editing capabilities: Trim and Crop.
Claquette uses AVFoundation, and therefore I was able to use the AVPlayer class, which comes with a built-in trim tool.
Crop functionality was a bit harder to implement. AVFoundation doesn’t provide any UI component to display crop handles so I had to implement my own.
Besides the standard drag & move interface, my implementation also provides some unique features. It offers alignment guides with haptic feedback and the possibility to enter crop coordinates.

You can see the final implementation of the crop utility in the animated GIF below:

ClaquetteCrop

Launch

To launch the animated GIF feature, I prepared a press kit and wrote mails to review sites that mostly cover Mac software.
Additionally I submitted the app to Product Hunt and informed Apple’s App Store Marketing team.
I can really recommend to launch on Product Hunt: Claquette received over 400 upvotes and finished in the top 3 on launch day. The site also hosts a friendly community, that makes extensive use of the Q&A section below each hunted product.
I was also lucky to get some mentions from high profile Twitter users and good App Store reviews.
Two weeks after launch, Apple suddenly moved Claquette into the “New and Noteworthy” feature section on the Mac App Store front page. Of course this also lead to a noticeable spike in the sales charts.
Overall I was very pleased with the release and the reception of Claquette 1.5.


Thomas Zoechling is an independent software developer living in Vienna, Austria.
Besides working on his own products, he is also doing contract work. Currently he is helping IdeasOnCanvas to develop the excellent mind mapping software MindNode (macOS, iOS).

Guest Blog Post: The Story Behind Gestimer

[Note: This is a guest blog post written by Martin Nguyen (@iMaddin on twitter), an OS X- and iOS developer based in Austria, about his Mac app Gestimer]

Gestimer Icon

I don’t like to keep too many thoughts in my head at the same time. Also, my short-term memory isn’t the greatest. If I had to cook dinner and then went back to my Mac to continue whatever I was working on, I’d probably forget about my dinner.

That’s especially true while coding where I have to be completely focused. Other unrelated thoughts are too distracting when writing code. I feel comfortable knowing that an app will take care of such thoughts as its memory is most likely better than mine.

Not too long ago – while I was at university – I noticed that todo apps weren’t entirely fitting all my needs. Sometimes I had these little tasks like reminding me to make dinner (because I’d forget and be too busy or focused with other things) or that I had to leave for a lecture in half an hour. It was too much of a hassle to set alerts for those tasks that have a short lifespan. To me it just feels slow to enter numbers with a keyboard for inputing dates and times, especially without a num pad.

As the type person who sits at my Mac most of the time, I decided to make a Mac app to work around this problem. After a couple of months and failed attempts at such an app, the idea that later became Gestimer popped into my mind: “Wouldn’t it be great if I could just drag down from the menu bar to create a quick reminder?” This seemed so simple and fast. It was the perfect solution.

Development

With this idea in my mind and a few sketches in my notebook, it was time for the execution. This was back in 2012 when I had just begun learning to code. As every beginner knows, coding is frustrating. Everything can break easily and you have no clue why. Objective-C was also not the easiest thing to learn without any prior programming knowledge. Additionally, making Mac apps appeared to be much more difficult than making iOS apps.
I shelved the project. There was nothing that was anywhere close to Gestimer out there so it was impossible finding resources that would help me realize the app.

With iOS 7, Apple introduced UIKit Dynamics. It seemed like a fun way to make interactions so I played around with it. I noticed that UIKit Dynamics allowed me to easily do something close to what I had in mind. It was only available for iOS and not OS X but it still allowed me to produce a version of Gestimer, even if it wasn’t in the intended environment. Here is the iOS version which was available from 2013 to 2014:

Gestimer_iOS

Gestimer for iOS didn’t do too well but that’s okay. I didn’t do any marketing as I simply put it up on the App Store and I was already happy to have an app that I made and used every day. Creating the iOS version taught me a lot and as I learned from more projects over the last couple years, I felt comfortable enough to tackle the Mac version again. I was especially motivated by the announcement and release of Swift.

I made some good progress on Gestimer for the Mac during the summer of 2014. The idea never changed: drag & drop from the menu bar to create a reminder. I worked on the app on and off, whenever I felt like it, whenever I slept off the frustration and head-scratching of the previous day.

As there was no UIKit Dynamics for the Mac, it was a lot more difficult to imitate the iOS version and to get things behaving as intended. By late 2014 I had a rough but useable version. I was never in a rush to release Gestimer. In fact, I stopped working on it for a couple months after that. I was again content with having an app I made and used every day. It also gave me time to simply use the app and think about if it truly did the things well that I wanted it to do.

If you haven’t seen Gestimer yet, have a look at a short clip here.

Marketing

Sometime around mid-April 2015 I started sharing a beta of Gestimer with people who I thought might be interested. Besides gathering feedback, it got me excited about the prospect of launching and hear what even more people will say about it. That’s where I decided to do some proper marketing. I won’t go into detail about this here as it would double the size of this post but I took marketing very seriously.

The basic outline of what I had:
– a short 10s clip of the interaction on the website
– collected email addresses for launch day
– made a YouTube video (currently over 50k views)
– a nice press kit
– localized Gestimer into 9 languages (now even more!)

Launch

There was little press coverage on launch day, but I had Gestimer up on Product Hunt thanks to Matthias who kindly sent me an invite. Someone had also posted the app to Hacker News. Both sites led to a lot of traffic. At the end of the day Gestimer was sitting on the 3rd spot on Product Hunt. To this date, the PH submission for the app has received over 400 upvotes. Twitter also helped a bit, though I believe people overestimate its effectiveness.

More press coverage followed and an increasing number of people spread the word. During launch week Gestimer reached the #1 spot in the Top Paid charts on the Mac App Store in multiple countries including the US, UK, and Germany. While sales numbers on the Mac App Store are small compared to the iOS App Store – even if you reach the top charts – it’s still been good. It’s nothing to complain about.

The reception for Gestimer has been overwhelming and I would have never imagined it becoming this successful. It makes me very proud to have done all the design, code, and marketing work on my own.

If you’d like, you can find out more about Gestimer here.

——
Martin Nguyen (@iMaddin on twitter) sometimes works on iOS and OS X apps and lives in Austria. While he enjoys coding, he is still trying to figure out the next step in his life.

Guest Blog Post: The Story Behind Review Times

[ Note: This is a guest blog post written by Frank Gregor (@TheCocoaNaut on twitter), an OS X- and iOS developer based in Austria, about his Mac app Review Times ] Review Times Icon

Once upon a time… No, only fairytales start that way. And this is no fairytale. It is a “true story”, like, I’m sure, many other developers have experienced one way or another. (-:

Some time around Christmas 2014, I stumbled upon a tweet, linking to appreviewtimes.com. Many of you may know about this website already. It gives you the average time Apple is currently taking to review apps for submission on the iOS and Mac App Stores.

I thought, hey, that would make a nice little Mac tool. So I asked a couple of developers on Twitter what they thought of such an app. The response I got was great. Without exception, everyone I asked wanted something like that. I had had some free time on my hands, so the idea manifested.

I wanted to build a small app that would live exclusively in the menu bar and offered a Today Widget. The information I would display in the app I would get from appreviewtimes.com. So I contacted Dave Verwer (@daveverwer on twitter), founder of Curated and publisher of the well-known iOSDevWeekly newsletter. He was the contact listed for the Shiny Development team, who are the creators of appreviewtimes.

I asked Dave if they perhaps already had such an app available or in development, and if that wasn’t the case, if they’d mind if I developed the app and used their data for it:

Hey Dave,

I found you as contact for Shiny Development, the maker of App-Review-Times. So I think it would be a great thing to have a little OS X tool that shows in an app extension the current review times via Notification Center. I’m building exactly such a tool and I have to grab and parse the website to get all the needed data.

So, to make things easier for development: Would it be possible to get all that raw data (iOS & OS X) as JSON or XML? Would be really great! (-;

Cheers, phranck

Dave answered promptly:

Hi Frank

I’m afraid that we don’t have either JSON or XML feeds of the information.

Please feel free to scrape the HTML though, as long as you include a link back to the original site.

Thanks Dave

Great! Now nothing stood in the way of me selling this App on the App Store (though I would learn better later). I got to work and within two days, I had a working prototype.

The fact that this app would run as a menu bar tool was very beneficial to me. I had been working on a piece of open source code, which does exactly that: place an icon in the menu bar and display a popover when clicked. This gave me a very good reason to further develop and improve the open source code.

Screenshot of Review Times Popover

Now was the time to tweet some screenshots, to whet the appetite of potential customers. It worked well. I received a lot of inquiries about what the app was about. This way, I got my first beta testers.

Review Times Today Widget

All in all, about three to four weeks went into developing the app and I believed the app was ready. I needed a nice icon that should really catch the eye. I made the acquaintance of Dan (@derpixeldan on twitter) and he created something truly wonderful at an unbeatable price… (-;

Around Mid-January, I submitted the app to the Mac App Store. Excitedly I waited for the notification on my iPhone that the review process had begun. About three weeks later, I received the message I longed for.

It didn’t take long and the review team contacted me again. But this message wasn’t what I had hoped for. My app got rejected! The reason Apple gave me was

…featuring speculative information about Apple products/services…

which I didn’t find reasonable at all. I was shocked. Every developer who ever received a “Rejected” notice knows this feeling of unease. I was annoyed and angry at the same time. Why in the world… ?!?! Did I go about this entire thing too naively?

Appstore Rejection

If you are familiar with Apple, you know they like to have control. And speculative information – like the average time it may take for Apple to review an app until submission to the App Store, shown by an app by some developer – well, that was completely out of their control. So Apple showed me, who’s boss.

That took the wind out of my wings in respects to this tool. I didn’t want to get into a discussion with Apple, it wouldn’t have lead anywhere anyway. I vented on twitter and let the whole thing rest for a couple of days – until, again on twitter, I received inquiries about what had happened to the app and how I would proceed with it. There were two possible options for me: 1) publish it as open source code 2) sell it outside of the Mac App Store from my website

On Twitter, I asked for input.

Since previously, people had stated their interest in paying for this app, I decided to go with option 2. After some research and testing how to best implement selling it from my website, I came to the conclusion that I should use Paddle. Their integration into an app is absurdly easy to do and they have first-class support.

All said and done, it took three more days of coding and testing and then everything was ready. I built a one-page website, wrote to many Mac-Blogs and magazines (none of whom replied!) and announced the release on twitter. Since so many developers wanted this tool, I was preparing for incredible sales-days… (-:

Poppycock. Virtually nothing happened. I sold a couple of copies, but all in all it went very, very slowly. Even after two months – with heavy-duty tweeting about it – I didn’t even make up for the cost of the icon. Reality had its grip on me again. So I had to act. Without thinking about it too long, I deleted all license- and purchase-handling code and released the app for free from my website.

Now everyone can download and install the app from http://reviewtimes.cocoanaut.com. Since then, I’ve had about 1-2 downloads a day.


Frank Gregor (@TheCocoaNaut on twitter) is an OS X- and iOS developer based in Austria. Among others, he is responsible for the Mac apps Review Times, Nekrologger and the iOS app f4analyse.