Tuesday, October 8, 2013

Calculating the next Thanksgivukkah with remind

Apparently, this year will see a rare coincidence of Thanksgiving with the first day of Hanukkah. It has been reported that this will not occur again for 79,043 years. I was suspicious of this and wanted to find for myself when the next Thanksgivukkah might occur. Now, this is a fairly complicated prospect as Thanksgiving (in the US) is defined as the last Thursday of November, while Hanukkah begins on the 25th of Kislev on the lunisolar Hebrew calendar. It turns out that there are some very powerful free software tools for GNU/Linux for calculating dates which can handle even this kind of complicated question.

I used a handy tool called remind. I'm sure you could do the same thing with Emacs calendar. (Actually by the time I was done, I was thinking I really should have tried Emacs instead...) With remind you store your reminders in a specially formatted text file. It is a command-line tool with many options and gui frontends available, but here I will just illustrate using the command-line tool to calculate the next date of Thanksgivukkah.

First, let's look at how to individually find the dates of Thanksgiving and Hanukkah. Here is what we need to set a reminder for Thanksgiving:

REM Nov Thurs 22 MSG Thanksgiving

This reminder will be triggered on the first Thursday on or after the 22nd of November, which is always the fourth Thursday.

Now, for Hanukkah remind thankfully supplies functions to support the Hebrew calendar, so here is what we will use for Hanukkah:

REM [trigger(hebdate(25, "Kislev"))] MSG Hanukkah

So remind calculates what day the 25th of Kislev falls on in our Gregorian calendar and all is right with the world. So how do we find when the two fall on the same day? This is where it gets complicated. First, we need to write a user-defined function that will check whether a date is Hanukkah:

FSET isHanukkah(date) \
     trigger(date) == trigger(hebdate(25, "Kislev", trigdate()))


This function compares the current date being evaluated with the date of Hanukkah for that year. Now, we will use the SATISFY clause to search for a Thanksgiving that is also Hanukkah and print a reminder:

REM Nov Thurs 22 SATISFY [isHanukkah(trigdate())] MSG Thanksgivukkah

So, to look just for the next date of Thanksgivukkah, create a remind file that contains only:

FSET isHanukkah(date) \
     trigger(date) == trigger(hebdate(25, "Kislev", trigdate()))
REM Nov Thurs 22 SATISFY [isHanukkah(trigdate())] MSG Thanksgivukkah

Now, in the process of writing this I discovered that in order to get this to work, you need a 64-bit system, and you need to recompile remind to take advantage of the larger dates a 64-bit signed integer can handle, otherwise you just get a date overflow error. (When I initially had used the pre-1942 definition of Thanksgiving, I did not run into this problem, see the note at the end. But since I had already published the mistake, I shall show the correct way even if we must edit and recompile from source. Onward!)

If you are brave enough to proceed with compiling your own modified remind (and have a 64-bit system), once you have downloaded the source and unpacked it, you will need to edit config.h.in and change

#define YR_RANGE 4000

to

#define YR_RANGE 17536635926176

To compile, just run:

wish ./build.tk

If you wish to install it system-wide, just do:

make install

Now, you can set you system clock to some time after Thanksgivukkah this year and print the next date with:

remind -n -x77030 /path/to/Thanksgivukkah-reminder-file

You can avoid the silliness with (falsely) resetting the system clock by printing a list of dates, but this performs very poorly and may take hours to run:

remind -s853000 -x77030 /path/to/Thanksgivukkah-reminder-file

 (Note that -xn sets how many times the SATISFY clause will be evaluated and the default is only 150)

Either way, we can confirm that the next date of Thanksgivukkah is November 23, 79043. So it's not quite 79,043 years in the future, but actually the year 79043.

EDIT

I initially used the pre-1942 definition of Thanksgiving, which was the last Thursday of November, rather than the fourth Thursday of November. For that we use:

REM Dec Thurs 1 -7 MSG Thanksgiving

Now I bet you are thinking that looks mighty odd, especially since Thanksgiving is in November, not December. It is not a typo, what we are doing here is to find the first Thursday in December and then counting back 7 days to get to the last Thursday in November.

So in this case we would use:

FSET isHanukkah(date) \
     trigger(date) == trigger(hebdate(25, "Kislev", trigdate()))
REM Dec Thurs 1 -7 SATISFY [isHanukkah(trigdate())] MSG Thanksgivukkah

If you didn't proceed with the recompilation described above, this example should still work fine for you, just run:

remind -s2965 -x247 /path/to/Thanksgivukkah-reminder-file

Now, the answer we get is:

2013/11/28 * * * * Thanksgivukkah
2108/11/29 * * * * Thanksgivukkah

2260/11/29 * * * * Thanksgivukkah

So the next date of Thanksgivukkah would only be 95 years away, on November 29, 2108, if we still celebrated Thanksgiving on the traditional date of the last Thursday of November. So, if you really want more Thanksgivukkah, you should petition Congress to change the date of Thanksgiving back! (Although this really only gives you two more Thanksgivukkahs before Hanukkah drifts away from Thanksgiving for millennia.)

It is also noteworthy that there will be a few more instances when Thanksgiving coincides with the first night of Hanukkah. That is, the first candle will be lit on the evening of Thanksgiving, but it won't technically be Hanukkah until sunset on Thanksgiving evening. We can find these dates simply by using the 24th of Kislev instead of the 25th, and this is another example you can run without modifying remind. This will give us:

2070/11/27 * * * * Thanksgivukkah?
2165/11/28 * * * * Thanksgivukkah?


Well, that's kind of like Thanksgivukkah, I suppose.

Sunday, September 15, 2013

Creating animated GIFs and APNGs from videos

Linux Setup

For this project we will need two or three tools. We will need avconv to pull frames from a video file, and we will need gifsicle if we want to created animated GIFs and apngasm if we want to create animate PNGs. If you are on Debian, you can install libav-tools (which provides avconv) and gifsicle in the normal way, but see my previous post on how to install apngasm from source (you will also find an explanation of the differences between animated GIFs and PNGs, and when to use each). If you use another Linux distribution, check your package management system.

Windows Setup

To get this to work similarly on Windows, we will need some extra tools and the setup is a bit more complicated. To get glob expansion and redirection, we will install Cygwin. Cygwin provides a Linux-like environment on Windows, including the Bash shell and the GNU coreutils (basic commands like ls, cp, rm, mv, etc). The installer also serves as a package manager, allowing you to select the various software packages you want to install or upgrade. If you are not sure what you want, just install the default packages. This will provide a lot more than we need, but you will have a useful environment if you need it later. You can always run the installer again later if you want to install more packages.

You will need to install 7zip, since Libav binaries come in a .7z archive you will need 7zip to extract them. When using the most recent version of Libav (0.9.7) on Windows, all of the GIFs came out in grayscale, so I tried the same version that was included with Debian Wheezy (0.8.6) and found it to be working on Windows (YMMV).  Gifsicle and apngasm come in .zip archives. Gifsicle and apngasm both contain a single binary you can extract to wherever you would like. Libav is a bit more complicated, you will need to extract the bin, lib, and share directories. For simplicity, you could extract all of these directories to C:\, and then put the gifsicle.exe and apngasm.exe in C:\bin (or choose whatever directory structure seems suitable for you).

Now, it would be nice to put  the directory (or directories) containing our new tools in the system path variable, so Windows (and Cygwin) will know where to find them without us having to type the full path to the command. You can do that in cmd.exe like this:

setx path "%PATH%;C:\bin"

Now, for any of the following commands, we will use the Cygwin Terminal. If you are from a Windows background, you will notice that all of the paths are separated with forward slashes instead of back slashes (C:/Users/Name/Documents, rather than C:\Users\Name\Documents). If you have used Cygwin before, you will need to note that these are not Cygwin binaries we are using, so the path arguments they take will use Windows drive designations (C:/Users/Name/Documents, rather than /cygdrive/c/Users/Name/Documents). However, this only applied to arguments passed to the commands, if you are giving the full path to the command, you will be using the Cygwin form (/cygdrive/c/bin/avconv.exe).

Essentially, when you are running the following commands in Cygwin terminal on Windows, you will just add the drive letter (C:) in front of the file paths, and the commands will end with the .exe extension.

Extracting Images from the Video

The first step is to convert our video to a series of image files. Now when we do this, we need to know what frame rate we want our animation to run at, and how if we want to make it faster (or slower) than the original video. If we want it to run at the same speed, we will use the same frame rate when extracting the images as we will use when we create the animation. If we want to alter it's speed or playing time, we'll want to do a little math. For instance, suppose I want to make an animation of these roses blooming from youtube. The video runs for about a minute and a half, but let's say we want to see the whole process in about ten seconds in our animation. If we want our animation to run at 30 frames per second, then we need 300 frames for a 10 second animation. To find the frame rate we want to pull from the video, we take 300 frames divided by 90 seconds, which gives us a frame rate of 3.33 fps.

Now that we have chosen the frame rate, let's look at the command:

avconv -i /path/to/rosesblooming.mp4 -r 3 -vsync 1 /path/to/rosesblooming%03d.png

Of course, if you are creating an animated GIF, you will use the same command with a .gif extension. Now you should have a collection of PNG and/or GIF images extracted from your video.

Putting together an animated GIF

Now when we create the animated GIF, gifsicle takes a delay in centiseconds (or hundredths of a second) rather than a frame rate. So a frame rate of 30 fps is equivalent to 1 second divided by 30 and multiplied by 100, or about 3 centiseconds.

Here is the command:

gifsicle -d 3 -l /path/to/rosesblooming*.gif > /path/to/rosesblooming.gif

Putting together an animated PNG

When we create the animated PNG, apngasm takes a delay as two integers composing a fraction of a second, so if we have chosen a frame rate, the first integer is one and the second is the frame rate.

Here is the command:

apngasm /path/to/rosesblooming.png /path/to/rosesblooming*.png 1 30

Creating a thumbnail in an animated PNG

The APNG format allows you to specify that the first frame will be skipped during the animation so it is only shown in viewers that don't support animation. To those viewers, the APNG we just created with look like a bunch of leaves. If we want them to see the fully opened roses instead, copy the last frame to /path/to/rosesblooming000.png and add the /f option to the command, like this:

apngasm /path/to/rosesblooming.png /path/to/rosesblooming*.png 1 30 /f

Looping

The above commands create animations that repeat indefinitely. This is the default for apngasm, for gifsicle the -l option specifies this behavior. If you want the animation to play through only once, you can just omit the -l for gifsicle since this is the default, but for apngasm you will add /l1 to specify this. For apngasm, you can use any number in place of 1 to play through a given number of times. For gifsicle, the -l option will take a number as well, but it is separated by a space.

Conclusion

Now you should have all of the tools you need to create your own animated GIF and PNG images. And you can always learn more by reading the documentation for these tools.

Sunday, September 8, 2013

Installing APNG Assembler (apngasm) on Debian Wheezy

Why you would use animated PNG instead of GIF

If you are reading this post, it is likely you may already know the virtues of APNG, but in case you've found this an aren't sure let me give a quick explanation. While animated PNGs are not as widely supported as animated GIFs, they are technically superior. GIF files support only 256 colors, while PNG supports 16,777,216. PNG files support alpha transparency, which means that parts of the image can be semi-transparent. With GIF files, a pixel is either completely transparent or completely opaque, which results in jagged outlines on images with transparency when the background is unknown. You can see the differences for yourself with this demonstration.

Unfortunately, as previously mentioned, support for APNG is somewhat limited. It was developed by Mozilla and has been supported by Firefox since 3.0. Opera supported it from 9.5-12.1, but unfortunately they gave up support for APNG when they moved from their own Presto engine to the Blink (formerly WebKit) engine used by Chrome. It is not natively supported by Chrome, currently the most popular browser in use, but there is an extension that will add support for APNG.

So, if you want the widest support, you may still want to use an animated GIF. But if you want quality, you need APNG and you can suggest your users try Firefox or the APNG extension for Chrome.

Installing APNG Assembler on Debian

APNG Assembler, or apngasm on the command-line, is a simple tool for creating APNGs from a series of PNG files. However, you might notice that it is not available in the official Debian repositories for Wheezy. The project has a Linux binary, but it didn't work for me on Debian Wheezy. However, building it from source is incredibly simple. Go to the project files on sourceforge, select the latest version, and download apngasm-x.x-src.zip. Then use the following commands (these work for 2.7, adjust accordingly if using a newer version):

unzip apngasm-2.7-src.zip
make
sudo cp apngasm /usr/local/bin


Now apngasm is installed and ready for use. (Note that you must be in the sudo group to use the last command.)

Usage

APNG Assembler doesn't come with a man page, but the command is documented in the readme.txt that comes with the source. Nevertheless, here is a quick overview.

 In order to make an animated PNG, you need a series of PNG images whose names end with sequential numbers, like this:

frame01.png
frame02.png
frame03.png


and so forth.

Basic usage is:

apngasm animation.png frame*.png

This produces an animated PNG that loops at 10 frames per second forever. If you want to change the delay between frames, you add two number to the command that represent a fraction of a second delay time. So, to produce an animated PNG that loops at 25fps (1/25 second delay) you would use:

apngasm animation.png frame*.png 1 25

If you what the animation to loop a limited number of times and then stop, you can use the /l options like this:

apngasm animation.png frame*.png /l2

This will cause the animation to play through twice, and then stop.

For backwards compatibility, animated PNGs can be displayed as a regular, non-animated PNG, but only the first frame will be shown. However, animated PNG also has a feature that allows you to skip the first frame. This way, you can use the first frame to display a thumbnail to non-supporting applications while omitting it from the animation. This thumbnail could be a single frame from the middle or end of the animation, possibly with a message informing the viewer that the image contains an animation their browser or viewer is not able to display. Once you have created this thumbnail as your first frame, simply add the /f option:

apngasm animation.png frame*.png /f

Now the first frame will be displayed for viewers that don't support APNG, but omitted from the animation.

Now you are ready go and fill the internet with much better animated images!

Protip #1

Some of you already do this and will think it is comically obvious. But someone out there will read this and think, "Oh, wow... that is such a great idea!"  and it will save them many a headache in the future. That person will achieve enlightenment.

Protip #1:

Whenever you are working on a computer and come across some oddity or have to configure things in an unusual or non-obvious way to make it work, make a note of it and document this information for future use. This will keep you from spinning your wheels trying to solve the same strange problem again later on (you don't think at the time that you will forget this stuff, but you will). One way to do this is to file this information away wherever you store important documents and information. This particularly works well if you maintain a lot of machines and want to keep your records in a centralized location. A simple alternative method (one I really like) is to simply write the information on a note card or something of that nature and put it inside of the case. That way, you can always find it when you are working on that machine.

Upon hearing this, the reader was enlightened.1

Sunday, August 11, 2013

Fixing ugly fonts on Tim Berners-Lee's (and other) webpages

Have you ever visited a webpage, such as Tim Berners-Lee's page (for those who don't know, he invented the World Wide Web), and found the font was wobbly, bumpy, jagged, or uneven? Various letters seem to be rendered at different sizes, making the text ugly and difficult to read. The problem is that on GNU/Linux and other Unix systems with FontConfig, URW Palladio L (which is the clone used for Palatino) suffers from really bad font hinting. Normally, hinting improves the appearance of fonts, particularly at small sizes and low resolutions. However, in this case it has gone horribly wrong. You can see the effect in these screenshots:



Fortunately, the fix is fairly simple once the problem has been identified. We can turn off hinting specifically for URW Palladio L with a little configuration. As the link above suggests, you can fix this on a per-user basis, but if you want to fix it system wide, simply create the file /etc/fonts/local.conf containing:

<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
  <match target="font">
    <test name="family">
      <string>URW Palladio L</string>
    </test>
    <edit name="hinting">
      <bool>false</bool>
    </edit>
  </match>
</fontconfig>

Then run:

fc-cache -f -v

to update the font cache information. You will need to close any applications that are currently open and reopen them for the changes to take effect. Now you should see much improved rendering for URW Palladio L, as seen in these screenshots:


Considering how bad the rendering is (I would consider it utterly broken), I'm not sure why hinting isn't turned off for URW Palladio L in the default configuration, but now at least you know how to fix it. And Tim Berners-Lee's home page should look much nicer.

Friday, July 26, 2013

Installing Kazam screencaster on Debian Wheezy from CrunchBang repos

When I went looking for a cool screen recording app for Linux that had native support for WebM, I didn't find anything in the Debian repositories that fit my criteria. Gnome 3 has a very handy built-in screen recorder that supports WebM, but I don't know of an easy way to use it outside of Gnome. However, there where a few cool-looking options available for Ubuntu, so I decided to see if I could find a way to install one of them on Debian. Kazam looked pretty cool, so I decided to give it a try. A little searching found that it is available for CrunchBang, a distribution derived from Debian, and the packages are apparently compatible.

However, I did it slightly different from how it was described as I didn't want to go installing third-party packages willy-nilly or by accident. I could have just installed kazam and then removed (or commented out) the CrunchBang repository, but then it wouldn't get updates. So what I did was to use apt-pinning to tell the package manager that I don't want any CrunchBang packages installed unless I explicitly install them (or they are pulled in as dependencies of something I explicitly install).

To do this, I first added:

deb http://packages.crunchbang.org/waldorf waldorf main

to my /etc/apt/sources.list with a comment to explain what it is doing there. Next, I added the CrunchBang key with:

wget -O - http://packages.crunchbang.org/statler-dev/crunchbang.key | sudo apt-key add -

Now, to set my preferences, I created /etc/apt/preferences like so:

Package: *
Pin: release n=wheezy
Pin-Priority: 900

Package: *
Pin: release n=waldorf
Pin-Priority: -10


Setting Pin-Priority less than zero is what indicates I don't want packages installed from this repository unless specifically requested. Note that this also means that it will not be upgraded by the usual commands, you must use the command you originally used to install it, but it will be possible to upgrade it with a single command without updating any configuration files again.

Now, I update the package list and explicitly install kazam from CrunchBang Waldorf (Waldorf is the CrunchBang release corresponding to Debian Wheezy):

aptitude update
aptitude -t waldorf install kazam


Now you should have Kazam available to record your own screencasts. All of the options are right there when you open it, to select video and audio sources, codec (VP8/WebM or H264/MP4), framerate, use a countdown timer, capture the mouse (or not), or select a region of the screen to record.

Kazam on Debian (KDE 4)

Note that all of the above commands (including editing files) need to be done as root, except for wget. Also, the line starting with wget uses sudo to run the apt-key command, so you need to be in the sudo group or else run the whole thing as root without using sudo.

Thursday, July 25, 2013

Installing the Tor Browser Bundle for all users on Linux

The Tor Browser Bundle provides a great way to browse the web anonymously through the Tor network. It is super simple to use and in addition to providing anonymity by routing your connection through multiple computers on the network it also blocks a lot of potential data leaks that could reveal your identity. It includes a patched version of Firefox with the HTTPS Everywhere and NoScript extensions.

Now the Tor Browser Bundle is intended to run without installation, even from a flash drive, but what if you want to install the Tor Browser Bundle to be available for all users on the system and show up in their application menus? I often install the official Mozilla build of Firefox and Thunderbird in /usr/local/bin, owned by my primary user (as described here). That way, all users on the system can use the applications and automatic updates work for my user, which updates the application for everyone. However, this approach will not work for the Tor Browser Bundle as it needs to be owned by the user to work properly. It may be possible to get a single installation to work globally by adjusting permissions (although I'm not certain if this might still introduce a security flaw), but the way I went was to configure the system to install it for all new users automatically.

First, put the Tor Browser Bundle directory in /etc/skel. The contents of this directory are automatically copied to each new user's home directory when it is created. Of course, you will have to do this manually for existing users (or perhaps write a script to do it, if you have a lot of users already set up). Next, create the file /etc/skel/.local/share/applications/torbrowser.desktop with these contents:

[Desktop Entry]
Type=Application
Name=Tor Browser
GenericName=Anonymous Web Browser
Exec=./tor-browser_en-US/start-tor-browser %u
Icon=/usr/local/share/icons/torbrowser128.png
Comment=Browse the Web Anonymously
Terminal=false
X-MultipleArgs=false
Categories=Network;WebBrowser;
MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/vnd.mozilla.xul+xml;application/rss+xml;application/rdf+xml;image/gif;image/jpeg;image/png;x-scheme-handler/http;x-scheme-handler/https;
StartupWMClass=Firefox-bin
StartupNotify=true


Now copy /etc/skel/tor-browser_en-US/App/Firefox/icons/mozicon128.png  to /usr/local/share/icons/torbrowser128.png. Each new user will get their own copy of the Tor Browser Bundle in their home directory, with a launch icon in the applications menu.

 Tor Browser on the Gnome 3 menu

 Tor Browser on the KDE 4 menu

Tor Browser running on KDE 4

Note that you will have to adjust these directions if your locale is not en-US. As a final caveat, browsing through Tor is slower due to being routed through multiple computers and popular plugins like Flash are disabled for security reasons. But this is the best way to browse the web with a reasonable degree of anonymity.

Wednesday, July 24, 2013

Installing official Mozilla builds of Firefox and Thunderbird on Debian

The Debian GNU/Linux distribution includes their own versions of Firefox and Thunderbird, rebranded as Iceweasel and Icedove, which are maintained with security updates for the life of the release. However, some people prefer to use the official Mozilla releases to get the most up-to-date versions. They come in a simple archive file that you can unpack and run right from your home directory, but what if you want to install them system-wide and have them included in the applications menu? Here is how I do it.

First, download the appropriate tarball for your system. The 32-bit builds are easy enough to find (see links above), but if you want to get a 64-bit build they can be found at https://download.mozilla.org/?product=firefox-latest&os=linux64&lang=en-US and https://download.mozilla.org/?product=thunderbird-latest&os=linux64&lang=en-US (note the locale at the end). Simply place the unpacked directories in /usr/local/bin.

The easiest way to keep Firefox and Thunderbird up-to-date is to use the built-in automatic update feature. In order for this to work, Firefox and Thunderbird need to be owned by a user who will actually run them on a regular basis. In my case, they are owned by my user account. Other users who have an account on my machine can use them, but all of the updates get installed by my user. You can just chown -R user /usr/local/bin/firefox, etc.

Now we just need to get them put into the applications menus. For this, we just need to put .desktop files in /usr/local/share/applications.

firefox.desktop should look something like:

[Desktop Entry]
Type=Application
Name=Firefox
GenericName=Web Browser
Exec=/usr/local/bin/firefox/firefox %u
Icon=/usr/local/bin/firefox/browser/icons/mozicon128.png
Comment=Browse the World Wide Web
Terminal=false
X-MultipleArgs=false
Categories=Network;WebBrowser;
MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/vnd.mozilla.xul+xml;application/rss+xml;application/rdf+xml;image/gif;image/jpeg;image/png;x-scheme-handler/http;x-scheme-handler/https;
StartupWMClass=Firefox-bin
StartupNotify=true


thunderbird.desktop should look something like:

[Desktop Entry]
Type=Application
Name=Thunderbird
GenericName=Mail Client
Exec=/usr/local/bin/thunderbird/thunderbird %u
Icon=/usr/local/bin/thunderbird/chrome/icons/default/default256.png
Comment=Read/Write Mail/News with Thunderbird
Terminal=false
X-MultipleArgs=false
Categories=Network;Email;News;GTK;
MimeType=message/rfc822;x-scheme-handler/mailto;
StartupWMClass=thunderbird-bin
StartupNotify=true


For KDE 4, you may need to run kbuildsycoca4 to update the menus. Now you should see the official builds of Firefox and Thunderbird in the applications menus.

 Firefox icon on Gnome 3 menu on Debian Wheezy

Firefox and Thunderbird icons on KDE 4 menu on Debian Wheezy

Update: I now have a video on DailyMotion demonstrating these steps.