Showing posts with label software. Show all posts
Showing posts with label software. Show all posts

Friday, February 18, 2011

Exporting slices from Inkscape, part 2

I previously wrote about how to export slices from an Inkscape file, using a bash script. Here's a better script, using Python, which doesn't require you to give your slices any special label.

The new process is as follows:

  • First, draw your image as usual.
  • Then, add a layer that will hold the slices; name it slices (this is important). Set the layer's opacity to about 50% to be able to see what you're doing. Enable the grid, and make sure it is set to pixels: you want your slices to align with pixel boundaries.
  • Draw your slice rectangles onto the slices layer, aligned to the grid. Ensure that the rectangles have no border; the fill is irrelevant (I use red).
  • Right-click a slice, and choose Object Properties. Change Id field to the name of the eventual PNG file, without the extension. The area defined by a rectangle named foo will be saved to foo.png. Repeat this for all slices.
  • Hide the slices layer. If you forget this, the script will print a warning.
  • Save your image. Let's say you called it layout.svg.
  • Run the script as follows:
    ./export.py layout.svg
    You should see each of your slices being exported to a PNG file in the same directory.

Here's the code for the script. Save this to a file export.py and make it executable.

#!/usr/bin/env python

import sys
import os
from xml.dom import minidom

if len(sys.argv) < 2:
    print 'Usage:  %s filename.svg' % sys.argv[0]
    sys.exit(0)
input_file = sys.argv[1]

dom = minidom.parse(input_file)
groups = dom.getElementsByTagName('g')
for group in groups:
    if group.getAttribute('inkscape:groupmode') == 'layer' and group.getAttribute('inkscape:label') == 'slices':
        if 'display:none' not in group.getAttribute('style'):
            print 'Warning: slices layer might still be visible'
        for element in group.getElementsByTagName('rect'):
            export_id = element.getAttribute('id')
            filename = '%s.png' % export_id
            print 'Exporting %s...' % filename
            os.system('inkscape --export-id="%s" --export-png="%s" --file="%s"' % (export_id, filename, input_file))
        break
else:
    print 'No layer named "slices" found; not exporting anything'
    sys.exit(1)

Wednesday, February 2, 2011

Editor's Prick?

Some time ago, I received an e-mail concerning my little open source program Taekwindow:

Monday, Jan 17, 2011, 10:27
From: F.R.
To: me

My name is F., Customer Manager of WareSeeker.com, a professional software directory. I would like to propose a solution to promote your software on our site.

We would like to take this opportunity to introduce ourselves. Wareseeker is one of top 5 professional software directories in the world and currently serving about 2 million page views per day. Many renowned software publishers rely on us as their primary media of promoting their products, thus increasing the sales or download dramatically.

We have tested thoroughly and guarantee that Taekwindow 0.3.1 is 100% SAFE TO INSTALL, which means it does not contain any form of malware: spyware, viruses, trojans and dialers.

Taekwindow 0.3.1 has been received Editor’s Pick Award from us.

We hope that you will gain more benefit through this Award. Moreover, we would like to request you add our link and Editor's Pick icon on your Awards category at http://taekwindow.sourceforge.net/download.html

It's not the first time Taekwindow receives such an award, and they generally don't mean very much. But still, it's a nice gesture, and I've done other download sites the same favour, so I replied in the positive.

Since the Taekwindow site is largely built by an automated build system that only runs on Windows, and I am spending all my time in Linux lately, I did not make any promises when I would get round to it. It would probably have been later that week.

Two days later, I received two e-mails in quick succession.

Wed, Jan 19, 2011, 02:40
From: F.R.
To: me

How about our request of our link and Editor's Pick icon at http://taekwindow.sourceforge.net/download.html

You will do that, ok? but when

Keep contact me

Wed, Jan 19, 2011, 09:46
From: F.R.
To: me

How long you got message of mine? I will remind you in final time for our link and Editor's Pick icon on your site.

Give me the respond when you reached this email

Okay, so he expects me to answer to e-mail within 7 hours and 6 minutes, while I'm asleep. And he's getting pushy. But at least I could tell him that I received his mails.

Wed, Jan 19, 2011, 12:04
From: me
To: F.R.

I got your messages alright. I'm a busy person, and I do not appreciate your impatience about me doing you a favour. Please stop pushing me. I'll get to it as soon as I have time.

I might still have done it later that week, but I didn't get round to it. Today, another e-mail appeared.

Tue, Jan 25, 2011, 02:42
From: F.R.
To: me

I don't know how are you busy, I'm also a busy man with a huge business volume each day but I still spend some minutes to write for me to remind you about our request.

Today If you don't reply my mail, I will remove our award for your product on my site. Contact me immediately when you reached this mail

Is that how you treat people when you want them to do you a favour? Not appreciated.

Tue, Jan 25, 2011, 11:45
From: me
To: F.R.

Dear Mr. R.,

The usual nature of awards is that they are given without requesting anything in return. In spite of that, I graciously agreed to return the favour, although due to other obligations I couldn't say when. After a few days, a gentle reminder might certainly have been appropriate. However, two reminders within eight hours (during which I was asleep, I might add), of an increasingly unfriendly nature, did not increase the likelihood that I would answer to your request. Your further pushy behaviour did not improve the situation, and now you request has turned into a demand, with a corresponding punishment should I not comply.

I noticed that Taekwindow has received 13 downloads through your site, and this number has not changed in the last few days. Compared to 149 downloads at Softoxi and 1121 downloads at Softpedia, I doubt there is much value for Taekwindow to be hosted on your site. Given the apparent attitude of the site's employees, it might even do more harm than good.

If it must be like this, I would prefer not to have anything to do with you or your site anymore. I have removed the staged modifications to the Taekwindow website. I will now proceed to write a post about our exchange on my blog, which receives a moderate amount of traffic. Good luck with your future endeavours.

Sincerely,

Thomas

P.S. Incidentally, the download page for Taekwindow on WareSeeker reads: "Software piracy is theft, Using crack, password, serial numbers, registration codes, key generators, cd key, hacks is illegal and prevent future development of Taekwindow 0.3.1 Edition." None of these statements are true. Software piracy may be considered a crime in most countries, but it is distinct from theft. The use of password[s], serial numbers, registration codes and/or cd keys is often a part of software installation required by the software's manufacturer, without which the software will not function, so this can hardly be considered illegal. Finally, the use of any of these will not impact the future development of Taekwindow 0.3.1 in the slightest.

Here's that blog post. See? I do keep my promises — mostly.

Saturday, October 9, 2010

Installing Rails 3 in Ubuntu 10.4

For the record, and for those of my friends who are going to participate in the Rails Rumble next weekend: here's how you install Rails 3 on your Ubuntu Karmic system. (10.10, known as Maverick, is supposed to arrive tomorrow and might make this post obsolete. But I won't be risking an upgrade before the weekend.)

  1. Install Ruby; apt contains the required version:
    sudo apt-get install ruby
  2. Uninstall RubyGems, because we'll install a more recent version from source:
    sudo apt-get remove rubygems
  3. Install RubyGems from source:
    cd /tmp
    wget http://production.cf.rubygems.org/rubygems/rubygems-1.3.7.tgz
    tar xzf rubygems-1.3.7.tgz
    cd rubygems-1.3.7
    sudo ruby setup.rb
    sudo ln -s gem1.8 /usr/bin/gem
  4. Install Rails:
    sudo gem install rails

Sunday, July 18, 2010

Exporting slices from Inkscape

If you have a Python interpreter available, you can use the slightly better alternative from Part 2.

In Photoshop, it's possible to “slice” an image into pieces, name the individual pieces, and export each to a separate file. This is really useful for web design: you can do the whole design in one image, then export the bits and pieces for later reassembling in HTML/CSS. Can we do the same slicing trick with Inkscape?

It turns out that we can; it's even on the Inkscape Tips and Tricks page. However, the exporting itself remains manual labour. I wrote a bash script to automate that; the code is given below.

The process is as follows:

  • First, draw your image as usual.
  • Then, add a layer that will hold the slices; name it, for example, slices. Set the layer's opacity to about 50% to be able to see what you're doing. Enable the grid, and make sure it is set to pixels: you want your slices to align with pixel boundaries.
  • Draw your slice rectangles onto the slices layer, aligned to the grid. Ensure that the rectangles have no border; the fill is irrelevant (I use red).
  • Right-click a slice, and choose Object Properties. Change Id field to EXP-something and hit Enter. The tag EXP- indicates that this rectangle is intended for export; something will become the filename (something.png). Repeat this for all slices.
  • Hide the slices layer, and save your image. Let's say you called it layout.svg.
  • Run the script as follows:
    ./export.sh layout.svg
    You should see each of your slices being exported to a PNG file in the same directory.

Here's the code for the script. Save this to a file export.sh and make it executable.

#!/bin/bash

if [[ -z $1 ]] ; then
 echo "Usage: $0 [FILE]"
 exit 0
else
 FILENAME=$1
fi

PREFIX=EXP-

for ID in `grep -o "id=\"$PREFIX.*\"" $FILENAME | cut -d\" -f2` ; do
 OUTPUT=${ID#$PREFIX}.png
 echo "Exporting area $ID to $OUTPUT..."
 inkscape --export-id=$ID --export-png=$OUTPUT --file=$FILENAME
done

Monday, April 5, 2010

So long, and thanks for all the glass

When I first installed Windows 7 after nearly a decade of using XP, I decided I'd not customize it. I'd just leave the settings at their default values and see what the wise men at Microsoft had decided for me. After all, there are thousands of hours of usability testing behind those decisions, so it seemed a good idea to give them a chance.

Now, half a year later, I've gotten used to most of Windows 7. Although I've tweaked the occasional thing here and there (show me the damn file extensions already!), I think most of it is pretty reasonable. But there's one thing I just can't get used to: the Aero theme.

It's not that it's semi-transparent. It's not that it fades and zooms and zips and zaps. It's just the minor little thing that I can't see the difference anymore between active and inactive windows.

When you activate a window, the title bar and borders become a little bit darker, the shadow becomes a little bit blacker, and the close button changes its colour from glassy to red. You can see the changes happen while you're switching focus, but telling the difference at a glance from a static image is hard. And because the title bar is transparent, the colour depends on the things behind it, making it even harder. There's just no single, consistent look for active and inactive title bars. I kept having to look at the close button to tell which window was active.

The subtle difference between an inactive and active title bar in Windows Aero

So what am I to do? Am I to magically know which window is active? When I've just clicked it, or when I'm typing into it, sure, I'll know. But being the Alt+Tab guy that I am, I shift focus without clicking all the time, and not always to the correct window right away. And what if some unexpected window suddenly pops up that might have stolen my focus, like an auto-updater? How can I tell if I can continue typing, or that I'd better yank my hands away from the keyboard in case I inadvertedly activate the Launch Nukes button?

Unfortunately, there is no way to change the look. The wise men at Microsoft have decided that a “theme” will be nothing more than a single colour for the glass, along with a set of wallpapers. There's no way to select different colours for active and inactive windows, like there is for the “classic” themes. There's also no way to install a clearer Aero theme without resorting to commercial third-party software like WindowBlinds.

So in the end, after my millionth focus fuckup, I switched back to the classic Windows 2000 lookalike theme. Blue versus gray seems like a distinction my eyes can handle.

Why do I have to sacrifice good looks to gain usability? Why can't Microsoft just make them get along?

Saturday, March 20, 2010

A harmonograph in JavaScript

What's a harmonograph, you ask? Well, it's something like a Spirograph for grown-ups. A harmonograph uses a construction with pendulums to draw pretty patterns.

One particular incarnation uses two pendulums of nearly equal length, each about two metres. To the right pendulum, a slowly revolving disk is attached, which is driven by a small electrical motor. The drawing paper is taped onto the disk. To the left pendulum, an arm is attached with the pen at the end. When the pressure and thus the friction of the pen is sufficiently low, the pendulums can keep swinging for tens of minutes.

For learning and fun, I replicated this harmonograph in JavaScript with the HTML5 canvas element. The pendulum motion is approximated by a sine function, and friction by an exponential, but apart from that it should be pretty physically accurate.

Without further ado, I present to you: Harmonograph in JavaScript. Usage should be self-evident. Although some input validation is done, you will be able to break it with strange values.

With the link at the top, you can save and bookmark your creations or send them to your friends. Enjoy!

Update, 2017-01-22: Hosting is now done here on GitHub Pages. The old location redirects you. I also published the source code (“View Source” still works just fine, but it's now officially MIT licensed as well).

Sunday, March 14, 2010

Capitalizing MP3s from the command line

For my own future reference and your enjoyment, here's a neat little oneliner to transform 01 - some song.mp3 into 01 - Some Song.mp3:

rename "s/([^._'])\b(\w)(\w*)/\$1\U\$2\L\$3/g" *.mp3

It needs the prename utility from Perl, which on Ubuntu is available by default under the name rename.

Friday, February 5, 2010

Ubuntu fails to load nvidia kernel module

As much a note to myself, as a warning to others…

After a kernel upgrade, my Ubuntu Karmic started the X server in low-resolution mode. My Xorg.0.log said:

(II) LoadModule: "nvidia"
(II) Loading /usr/lib/xorg/modules/drivers//nvidia_drv.so
(II) Module nvidia: vendor="NVIDIA Corporation"
        compiled for 4.0.2, module version = 1.0.0
        Module class: X.Org Video Driver
(EE) NVIDIA: Failed to load the NVIDIA kernel module. Please check your
(EE) NVIDIA:     system's kernel log for additional error messages.
(II) UnloadModule: "nvidia"
(II) Unloading /usr/lib/xorg/modules/drivers//nvidia_drv.so
(EE) Failed to load module "nvidia" (module-specific error, 0)
(EE) No drivers available.

I tried modprobe nvidia and such, but it seemed that the module actually did not exist. This module should be installed by the package nvidia-185-kernel-source, which was present on my system. However, it turns out that the kernel module is compiled on-the-fly by a program called jockey which controls DKMS, the Dynamic Kernel Module Support.

It is possible to force a recompile using dpkg-reconfigure:

$ sudo dpkg-reconfigure nvidia-185-kernel-source
Removing all DKMS Modules
Done.
Loading new nvidia-185.18.36 DKMS files...
Building for architecture x86_64
Module build for the currently running kernel was skipped since the
kernel source for this kernel does not seem to be installed.

I need the kernel source, eh? Why the hell is that not a dependency, if the driver package is useless without it? Anyway, let's install the kernel source then:

$ uname -r
2.6.31-19-generic
$ sudo apt-get install linux-source-2.6.31

Installs fine, but makes no difference. Turns out that dpkg-reconfigure was lying: I just need the headers. Here we go:

$ sudo apt-get install linux-headers-2.6.31-19-generic
...
$ sudo dpkg-reconfigure nvidia-185-kernel-source
Removing all DKMS Modules
Done.
Loading new nvidia-185.18.36 DKMS files...
Building for architecture x86_64
Building initial module for 2.6.31-19-generic
Done.

nvidia.ko:
Running module version sanity check.
 - Original module
   - No original module exists within this kernel
 - Installation
   - Installing to /lib/modules/2.6.31-19-generic/updates/dkms/

depmod......

DKMS: install Completed.
$ modprobe nvidia
$

That's better.

Several bug reports indicate similar problems, but the current way this is handled is terribly inadequate. The driver package should pull in the kernel headers if it needs them. There was no warning about this when the kernel was upgraded. There was no warning when the module failed to compile on boot. A fix for a problem with the same symptoms was released back in December; another one is in the upcoming Lucid release.

Oh yeah, I ended up rebooting my system. Whatever happened to Ctrl+Alt+Backspace? (Answer.)

Update, 2010-08-04: After another kernel upgrade, my display driver was hosed again. After hours of tinkering, I typed sudo dpkg-reconfigure nvidia-current and was greeted with the message gzip: stdout: No space left on device. Apparently, my /boot partition was full (of abandoned kernels). Something to check, for whoever runs into similar problems! Also, the kernel module appears to have been renamed from nvidia to nvidia-current.

Sunday, January 24, 2010

Review of free C++ IDEs for Linux

For my new project, I started looking into IDEs for Linux for the C++ language. And since I'm testing them anyway, I might as well write some quick reviews. ‘Quick’, because I'll mostly be going on first impressions, and some things I say might be quite wrong. Feel free to correct me in the comments!

My previous IDE experience includes Visual Studio for C++ and for C#, Eclipse for Java. I will sometimes compare to these.

Code::Blocks

I am greeted with very nice wizards, and it's easy to get up to speed. There is even a template for GLFW projects, which I select. But when trying to compile (using shortcuts nothing like any other IDE I know) I get a linker error; some XF86 library is missing, and even apt-file cannot tell me where to get it.

Hunting through the build settings, I notice many other problems. The settings are nested three levels deep: a bar with huge icons on the left, scrolling tabs (the horror) on the right, and nested tabs below those. Many options are unclear. When I press Esc to cancel my changes and dismiss the dialog, nothing happens.

Some parts of the Code::Blocks UI are really good, other parts are… not so good. I wouldn't want to work in this for a long time.

KDevelop

It starts up with a blank screen, so I have to ask it to create a new project myself. Not a big deal. The New Project wizard is reminiscent of Visual Studio, so I feel quickly at home. It allows me to create a CMake project; I like CMake. The wizard gives me a Hello World program, but I cannot run it: I have to create a Launch Configuration first. Then I run my program, I think, but where does the output go? The Debug Area (‘Perspective’) is empty. Turns out that building failed, because I moved the project in the mean time, and the project file contains absolute paths. Bad!

Support for external tools seems good. I already mentioned CMake; the Valgrind profiler and Git versioning system can also be used right from the IDE.

The IDE itself actually seems like a blend of Eclipse (borrowing much of its concepts and terminology), Visual Studio (some wizards and the layout of dialogs) and Kate (the general KDE stuff). Not bad at all. Still, I had some trouble getting everything set up, but once you've taken the time to do that, KDevelop might be a decent IDE.

Eclipse

Big, bloated, but feature-rich and quite user-friendly once you've warmed up to it. That's been my impression of Eclipse for Java, which I'm quite familiar with. For Java, it's easily the best IDE around; the refactoring options alone make it worthwhile. Let's see how Eclipse with the CDT plugin performs for C++.

I install Eclipse, grab the CDT plugin through its update site and restart Eclipse. A few clicks later, I have an empty C++ project. I add a main Hello World file, and after some strange trouble with the Debug Configuration, it runs. I add a library to link with, finding the option without any difficulty. Not being unhappy about this, I continue to write some more code, to try the completion and refactoring features.

Completion pleasantly surprises me. This stuff is better than Visual Studio's. It's fast, it's accurate, it gets the contents of a newly included header file right after I saved… nice! Smart insert mode adds closing paretheses, braces and quotes, but if I type them myself as well, they are overwritten.

Error highlighting is equally fancy. Unlike Visual Studio, syntax errors are highlighted in real time, without even having to save the file.

I ask it to create a new class, and get a header and source file with a nice skeleton. It's not exactly the way I would write it, but I'm sure it's customizable.

Refactoring, unfortunately, is not as fancy as it is for Java. It is limited to renaming identifiers, and doesn't rename the source and header file accordingly. It can also extract selected expressions/statements into a separate function, but it does not create this as a member function. There are no “quick fix” options for adding include directives, like with Java. Yet, it's better than what Visual Studio offers on this front.

Eclipse with the CDT plugin is not perfect, but it's good. I could live with it.

Anjuta

I am greeted with a welcome screen, which I ask to create a new project. I am asked for all kinds of needless details, like the license type and my e-mail address. No wonder: it creates an entire autotools project for me. I tried to add a library to the linker command, but couldn't find the option anywhere. Do I really have to edit the Makefile.am?

I've only had a brief look, and Anjuta seems like a nice IDE if you want what it wants, but at first sight doesn't seem flexible enough to cope with everything.

Qt Creator

Would this work for non-Qt applications as well? It wouldn't seem so at a first glance, but I imported an empty directory as a Makefile project, which seemed to work. I had to write a Makefile, of course, which failed because the IDE quietly changed my tab to four spaces. After fixing that, and some directory issues, I could build the program. Running it required similar trickery.

Code completion works very well, and identifiers from a newly included header are available quickly. The entire IDE looks and feels smooth and polished, and is reminiscent of Visual Studio in many details.

The build system remains weird, though. It created an autotools project for me, with about a dozen files, and not offering me any choice in the matter. There is a reference to CMake in the Preferences, but no clue how to create a CMake project.

Qt Creator is a slick, clean, usable IDE. I like it. Still, it is very Qt-centric, and its build system seems inflexible. Too bad.

NetBeans

Yes, another Java IDE that can be used for C++. I have actually never used NetBeans for Java before, so I have no preconceptions about how it should work.

I apt-get the IDE and install the C/C++ plugin; this is very straightforward. I create a new C++ project, and a Makefile gets created automatically. I run the empty main function, and the program pops up in an external terminal.

Then I start editing the code, and I'm pleasantly surprised by the editor. Not just syntax errors, but unknown identifiers get highlighted in real time. Function signatures pop up in a large, but helpful tooltip. Even the filenames of include files are autocompleted! The contents of the include file become available without even having to save the file.

Yet, not all compile errors are highlighted, even though you can click to them from the compiler output window. I could not manage to get the function signature to reappear while I was typing arguments. Refactoring options are all grayed out; I assume those work for Java only.

The project settings are very much like Visual Studio, but allow for little customization. It's just enough to add a -l flag to the linker command line to link in an external library. There is also Git integration (if you install the plugin) but I didn't try it.

I checked out NetBeans as an afterthought, but that seems to have been a mistake. Of all the IDEs I tried, this is actually one of the nicest. It doesn't have many bells and whistles, and its build system might be inflexible, but the code editor makes up for it.

Conclusion

Are IDEs for C++ worth the trouble? I'm not sure. The value of an IDE lies in fast code editing, refactoring options, easy building, and error highlighting, and integrated debugging. None of the IDEs I tried score highly on all these fronts. I can understand: a flexible, usable IDE for C++ is almost impossible to create. Maybe I'll just go back to my trusted old Kate and gnome-terminal…

Tuesday, January 12, 2010

Programmers are not artists

As you may know, it takes a long time to install Visual Studio. Even on a modern system like mine, it took around twenty minutes. No program I know has ever gotten close to that, except Microsoft Office.

This means that the guy below is on your screen for a long time. Seriously, the longer you look at it, the more disturbing his face becomes.

In the style of Photoshop Disasters, I'm supposed to write a witty comment below the photo. How about this:

Management: “Hey, this guy is not smiling! Do something about it!”
Intern: “Whatever, I'll just photograph my girlfriend's mouth from this entirely different angle and slap it on. It's not as if this photo will be visible for a long time, anyway.”

Wednesday, December 16, 2009

Unfortunate cutoff

If you are writing a piece of text that may be cut off, pay some extra attention to your first sentence…

Sunday, December 6, 2009

Reinstalling GRUB with LVM from the Ubuntu cd

This post is mostly a reminder to myself. Every time I reinstall Windows, it overwrites my boot sector, and I need to reinstall it from the Ubuntu live CD to get my dual-boot system back. However, since my Ubuntu install is inside an LVM partition, this is not very straightforward. Here are the instructions. I kept them general so that they may be of use to someone else as well.

  • Start from the Ubuntu CD and open a terminal.
  • Install LVM:
    sudo apt-get install lvm2
  • Find the name of the volume group:
    sudo vgdisplay
  • Make the volume group available:
    sudo vgchange -ay name-of-vg
  • Mount the root and boot file systems, and bind the dev file system:
    sudo mkdir foo
    sudo mount /dev/name-of-vg/name-of-root-lv foo
    sudo mount /dev/name-of-boot-partition foo/boot
    sudo mount -obind /dev foo/dev
  • Change to the root of your system:
    sudo chroot foo
  • Drop into the GRUB prompt:
    sudo grub
  • Install the GRUB MBR (assuming that (hd0) is your boot drive and (hd0,0) your boot partition):
    root (hd0,0)
    setup (hd0)
  • Reboot and have your boot menu back!

Saturday, October 17, 2009

Disabled for your protection

My Firefox, on Windows, just reported that it had disabled the Microsoft .NET Framework Assistant 1.1 extension and the Windows Presentation Foundation plugin. Supposedly, these were security issues. If I'd be so kind as to restart the browser for the changes to take effect.

Well, whatever, go ahead. After the restart, the Extensions window pops up, showing .NET Framework Assistant as “Disabled for your protection.” Phew, thank you.

But now I'm curious. What's so evil about these Microsoft plugins that Mozilla feels the need to block them automatically? Luckily, there is a “More Information” link right there in the dialogue! So I click it:

It's great to see that Mozilla really cares about my security.

Friday, July 3, 2009

Speeding up Kile

Even though I'm mostly a Gnome user, my LaTeX editor of choice is Kile. Unfortunately, it can become a bit sluggish, especially when dealing with long lines. (I hate artificial line breaks, so I just type one line per paragraph and turn on dynamic word wrapping.)

This seems to have something to do with rendering. To make Kile considerably faster, start it like this:
kile --graphicssystem raster
Instead of raster, you can also try opengl, which is supposed to be even faster, but not considered stable yet. YMMV.

Monday, June 15, 2009

Creating a multi-page PDF from images

It is often convenient to pour a series of JPEG (or PNG, or GIF) files into a PDF, for example for printing or for e-mailing. Given the power of the Linux command line, this is surprisingly difficult, but I found a fairly straightforward way to do it. Skip to the bottom if you just want the oneliner.

Many websites will tell you the following:
convert *.jpg output.pdf
Easy, no? Don't do this. Why? Look at this:

-rw-r--r--  1 thomas thomas 129826204 2009-06-15 15:29 output.pdf
-rw-r--r--  1 thomas thomas    947022 2009-06-15 15:04 page1.jpg
-rw-r--r--  1 thomas thomas    962956 2009-06-15 15:05 page2.jpg
-rw-r--r--  1 thomas thomas    925291 2009-06-15 12:54 page3.jpg
-rw-r--r--  1 thomas thomas    952717 2009-06-15 12:54 page4.jpg
-rw-r--r--  1 thomas thomas    642471 2009-06-15 15:08 page5.jpg

The original JPG files are less than 5 MB altogether, but the resulting PDF is a whopping 124 MB! Clearly, convert (from the otherwise excellent ImageMagick bundle) re-encodes the images somehow, instead of embedding them straight into the PDF file.

Enter the little-known utility sam2p. It comes in an Ubuntu package of the same name. In its simplest form, it converts a single image file into a PDF by embedding the image file into the PDF file. For example:
sam2p page1.jpg page1.pdf
One of the shortcomings of sam2p is that it does not allow you to set the page size directly, so you'll end up with PDFs that exactly fit the original images.

Now we can generate all the pages as separate PDFs, but sam2p cannot create a PDF with multiple pages. Enter pdfjoin from the pdfjam package (available in Ubuntu under that name). It is simple to use:
pdfjoin page*.pdf --outfile output.pdf
This will use a consistent page size, so it is no problem that sam2p spit out pages of arbitrary size. It defaults to A4 paper; specify --paper letterpaper to use the Letter format.

Because I'm lazy, I wrote a little bash oneliner to do the trick, then let my readers improve upon it (thanks Mark, thanks Eamon!). It is now a twoliner, but who cares:
find . -maxdepth 1 -iname 'page*.jpg' -exec sam2p '{}' '{}'.pdf \;
pdfjoin page*.pdf --outfile output.pdf
This assumes that your input images are named page1.jpg, page2.jpg etcetera, and that there are no files named like page*.pdf in the current directory. If you have more than 9 pages, remember to prefix a zero to keep them in order. If you want to do this for PNG or other images, remember to change the extension in both places.

Tuesday, May 19, 2009

Wednesday, May 13, 2009

Accepted for Google Summer of Code!

I have been accepted for Google Summer of Code 2009! The title of my project is “Extend EclipseFP functionality for Haskell.” I have just set up a blog where I can keep all posts together that are related to this project. (This blog will also allow me to test-drive Wordpress, because as we all know Blogger sucks.) You can find more information at my new blog: EclipseFP GSoC '09.

Tuesday, February 3, 2009

Thursday, January 22, 2009

Sequential page numbering in LaTeX

Did you ever notice that the page number that your PDF reader gave you was not the same as the page number printed at the bottom of the page? By default, some LaTeX commands, such as \tableofcontents, reset the page number to 1.

I don't like this behaviour. I just want my cover page to be numbered 1, the next to be numbered 2, etcetera. This way, the ‘physical’ and ‘virtual’ page numbers line up nicely. It also prevents some problems with hyperref, which will otherwise create duplicate page labels.

You can get sequential page numbering by putting the following snippet in your document preamble:

\let\oldsetcounter=\setcounter
\renewcommand\setcounter[2]{%
    \def\arg{#1}\def\pg{page}%
    \ifx\arg\pg\else\oldsetcounter{#1}{#2}\fi}

This simply overrides \setcounter, such that it ignores any attempt to set the page counter, which holds the current page number. Ugly, but it works.

Tuesday, November 18, 2008

gluLookAt documentation is wrong

Today I noticed a strange omission in the documentation for the GLU function gluLookAt. As the specification says, the function is designed to place the camera at a certain point in the scene, point it at a certain other point, and roll it such that a certain given vector points upward in the view.

First, the function computes a front vector, F, by subtracting the eye point from the centre point. This normalized version of this front vector is called f and is the vector that should be mapped to the −z axis. To find the side vector, the one that maps to the x axis, the cross product between the normalized front vector and the normalized up vector UP' is computed. Both vectors have unit length, but the user may have specified an up vector that is not perpendicular to the front vector, so the result s might not have unit length. If we used it like this, then the resulting matrix would include a scale component in the x direction, resulting in a scaled scene. Hence, the side vector s has to be normalized as well, which is exactly what the Mesa source code for gluLookAt does in line 134:

/* Side = forward x up */
cross(forward, up, side);
normalize(side);

However, the gluLookAt documentation does not mention this! It says “s = f × UP'”, and follows by plugging this s straight into the resulting matrix M. If you implement the algorithm precisely as stated in that manual page, like I did, you will end up with an incorrect matrix.

Note that, after computing the side vector, the ‘official’ up vector is recomputed as the cross product between the side vector and the front vector. If you did it correctly and not follow the documentation literally, both have unit length. Since these are guaranteed to be perpendicular you should end up with a unit-length up vector that does not have to be normalized afterwards; and indeed the Mesa code does not do this. But if you did follow the documentation, then your up vector will also be wrong, resulting in a scene that is scaled in the y direction as well.

I am trying to get in touch with the OpenGL people about the problem in the documentation. I'm curious to see what will come of it.