Cutting a Large Sheet of Paper in Half

22. April, 2009

Here is a simple trick how to cut a large piece of paper or cardboard into two perfectly symmetrical halves:

Cutting large piece of cardboard in half

Cutting large piece of cardboard in half

  1. Fold the paper. Make sure that the open side matches perfectly. Put some weights on them to keep them in place.
  2. Now sharpen the fold. Use a book or the handles of your scissors. It doesn’t have to be razor sharp, though.
  3. Cut the fold away with a knife or scissors.

It’s simple to make a straight cut when you only have to keep 1-2mm distance to the edge of the fold. Also, even if you’re completely inept, the two pieces will have the exact same width at the point where you started. If you need to glue them together, they will match perfectly.


PyScan: A Little Helper For The HP CM1312nfi MFP Scanner

18. April, 2009

Update: Find the latest version (0.6) here.

I recently bought a HP CM1312nfi MFP scanner (multi function device with scanner and color laser printer). After scanning some 1’000 pages, I’m still satisfied with the device. The document feeder (ADF) sometimes tries to eat the paper after spitting it out and the colors could be a little more brilliant but overall, a good deal for the price.

What bothered me was that the “Start scan” button doesn’t work on Linux. But someone posted a script in the bug report which can poll the button by reading the URL http://$ip/hp/device/notifications.xml (replace “$ip” with the IP address or DNS name of the scanner). This returns some XML with two interesting elements: StartScan and ADFLoaded. The first one becomes 1 when someone presses the “Start scan” button on the scanner and the second one tells us whether there is some paper in the ADF.

With that and some source code, it was simple to create a little tool that works quite like xsane but fixes a couple of things that annoyed me for a long time:

  1. The UI of xsane is dead while it scans
  2. There is no online preview of the scan; you have to open the file in some extra tool to verify that the scan looks OK
  3. xsane doesn’t know about scan “projects”
  4. xsane doesn’t start to scan when I press the button on the scanner

As with all OSS software, this thing can seriously ruin your day, so be a bit careful. One of the biggest problems is the file size: To be able to edit files without loss of quality, TIFF format is the default. Each full page scan takes 26MB, 100 pages need 2.6GB!

Plans for 0.5: Allow to edit projects in the UI, select them, save and load them. Right now, you must define your projects via the command line or by editing the source code.

Download: PyScan-0.4.tar.gz (12KB, MD5 checksum)

Dependencies (see README.txt for download links):

  • Python 2.6
  • PyQt4 4.4.3
  • Python Imaging Library 1.1.6
  • Python Imaging SANE 1.1.6 (needs included patch; see README.txt for instructions).

Features

  • Code to load images in a background thread, generate thumbnails (compatible to Konqueror/Dolphin) and display them in a list view
  • Display a (big) image with various manual and automatic zoom levels and modes (fit to window, percent) with zoom and pan
  • Online preview of scan in progress

Hideous details of the source

Again and again, I’m astonished how simple some tasks are in Python and Qt … if you’re willing to accept some “non-OO-ness” of the solution. I’ll explain some things I did here to give you an idea what’s going on.

Online preview

PyScan has an online preview of the currently active scan. If you look at the documentation, the Python Imaging SANE interface offers no way to do that. After looking at the source, I found that the SANE interface simply reads bytes from the SANE scanner module and copies these into a PIL image which was created on the Python side.

So my solution is to be notified that a scan is in progress and then copy said image every second (all 26MB) into a string. That string is then used to build a QImage which is turned into a QPixmap which is then displayed in the right pixmap view. See pilImage2QImage() for the details.

Background threads

I also moved all expensive code into threads: Loading big TIFF images, scaling them down to thumbnails, saving the images, etc. All threads have a method to add work to their input queues and they send Qt signals when they’re done. Continuing the scanning when there is paper in the ADF tray was a bit of a problem, through.

Since the saving of the images is happening in a background thread, the code could start the next scan before the saving was completed. This wasn’t such a big problem except that the “scan next image” code looks for files on the disk to determine the next filename. This would lead to overwrites. So I had to synchronize this somehow. My simple hack was to set a boolean “waiting” in the scanner thread which indicates that the scanner has more paper to process and waits for the save thread to complete. When the UI gets the “image saved” signal, it triggers the scanner to continue.

Generating thumbnails

The last hack in the code is the generation of the thumbnails. The main issue here was that I need the thumbnails for the gallery view really deep down in the Qt render code. Wasting time at that level is really a no-no but at first glance, the API offers no way to defer loading of the images and then later update the items in the list view when the data is available. Keep in mind what I need to do:

  1. Load a 26MB file from disk
  2. Scale it with antialiasing
  3. … for hundreds, possibly thousands of files!

My solution: In the render code, I create a LazyPixmap. This is just dumb object to save the filename and a placeholder pixmap which is used into the real thumbnail becomes available. The LazyPixmap will schedule a job for the LoaderThread.

In my first code, I tried to create a QPixmap in the LoaderThread but that doesn’t work: Only the UI thread is allowed to create a QPixmap. Duh. But luckily, Qt offers the QImage class which works even without a UI and which offers basically the same API as QPixmap. So the LoaderThread can load the image from disk and scale it down (to save memory and avoid heavy computation in the UI thread) right before emitting a “loaded” signal.

There are two places where a LazyPixmap is used: In the PixmapWidget (which can display and zoom a QPixmap) and in the ThumbnailDelegate which draws the thumbnails for the filenames in the GalleryModel.

In the case of the PixmapWidget, the signal will be handled in lazyLoaded(). Here, we convert the QImage into a QPixmap (in lpm.getPixmap()) and assign that pixmap, recalculate the zoom factor, realign the view, etc.

The GalleryModel, I have the problem that I need to tell Qt somehow that the pixmap has changed but the API offers nothing except rendering the whole widget by calling update(). This will render at most (on a huge screen) 30 pixmaps. Happens one time per visible pixmap, causes no flicker. Probably not worth to waste another second on it.

If you look at the code, you’ll see that a class called KDEThumbnailCache is used. This class accesses the same thumbnails als konqueror (KDE3) or Dolphin (KDE4). This means once the images are scaled down (either by my code or Dolphin), all tools can quickly load the small, precalculated thumbnails instead of having to scale the 26MB files again.

Conclusion

Well, that’s it for a small walk through the code. Feel free to give feedback if you like PyScan (or not) or when you have patches.


On Uniqueness

3. April, 2009

It’s not the individual strengths and flaws which make a human unique, it’s the combination. Which is why an expert, who knows many strengths and flaws, knows all humans.


Can You Operate a Light Switch?

1. April, 2009

I greatly enjoy my daily WTF. This time, it was The Executive Summit. Great stuff but it got me thinking. Can you operate a light switch? How much longer?

It’s fun to read how high-paid executives of a company can’t turn on the lights or make a phone ring. Technology is advancing and not everyone expects the light switch to have a dimmer or a way to turn the phone off (and if you’re a bit like me, you’d love such a switch). There is a high demand for such functions, no doubt, but they come at a price.

As humans with human brains, we expect the same things to stay the same things. A house doesn’t suddenly turn unto a whale (well, rockets sometimes do … but not houses!). When a light switch doesn’t switch the light, it must be broken, or so our brain tells us because a light switch is a light switch is a light switch.

Beware when you “add functionality” to something which people are used to because they aren’t used to it.


Testing the Impossible: Asserting Several Values At Once

23. March, 2009

So you want to check several values at once, maybe because that helps you to locate the error more easily. Simple:

int v1 = list1.size();
int v2 = list2.size();
int v3 = list3.size();

assertEquals (
      "list1=5\n"
    + "list2=2\n"
    + "list3=0\n"
    , "list1="+v1+"\n"
    + "list2="+v2+"\n"
    + "list3="+v3+"\n"

hpaio: unable to read device-id

21. March, 2009

I recently bought a multi-function device printer scanner (HP Color LaserJet CM1312nfi MFP). Setup on openSUSE 11.1 was pretty painless with the hplip package (version 3.9.2) from packman. The original openSUSE package would core dump. Duh.

Today, I had a strange error all of a sudden:

scan/sane/soapht.c 486: unable to open device hp:/net/HP_Color_LaserJet_CM1312nfi_MFP?ip=xxx.xxx.xxx.xxx
io/hpmud/jd.c 84: unable to read device-id

Of course, I hadn’t changed anything in my setup … until I remembered that, for security reasons, I had disabled SMNP in the web interface of the printer. Guess what, after enabling “SNMP-Lese-Schreib-Zugriff aktivieren” (“Activate SNMP-Read-Write access”), the error went away.

For the record: Most functions of the device are accessible from Linux:

  • Color printing
  • Scanner
  • Automatic document feeder (ADF)
  • Remote printing and scanning

I haven’t yet managed to make the “Scan to PC” button on the front of the device work but that’s just a minor issue for me.

The price/performance ratio is very good. The printouts look very good and the ADF could cope with all media that I’ve fed him so far (even these thin, glossy, cohesive catalogue pages; you just have to spoon feed them one at a time).

The scanner is good, but not top notch. The quality of the scans is OK, colors are pretty close to the original but the images could be sharper. The scanner uses a CCD line, so no warmup time (if you don’t have to switch on the whole machine).

If you want better quality color copies, set the resolution to 300 DPI (factory setting is a poor 150 DPI which makes thin lines really smear).


On Strength

16. March, 2009

Strength means you can afford to be polite.


Found My Friends From The Talon Company

5. March, 2009

Disclaimer: This is a cynical virtual diary of my journey through Fallout 3. If you don’t like strong language or cynicism, this is not for you.


While wandering the landscape, I ran into this fort. Fort Bannister. Guess who lives here? The friendly guys of Talon Company! You know, the guys who supply me with ammo, guns and armor in the field? Whenever I need it, three of them would show up and, after a friendly round of sparring, they’d hand over their goods to me. XP for free, too!

What can I say? As I saw their crest, I had to drop in and say hello! Until I reached the poorly hidden access grate, like seven guards had forced their stuff onto me. I could barely walk under the weight!

Down in the guts, the boss, a Commander Jacobs or Jabsco or something, couldn’t really hear him over the firing of my brand new laser rifle, stood target himself so I could improve my skills in energy weapons! Whow! That’s customer service, eh? And every time I as about to run out of anything, another of his chaps would shop up and leave me stuffed!

Guys, I’ll miss you.


Random Idea: Public Data Safe

5. March, 2009

A lot of places offer free data storage these days but I’m concerned about security. How safe it is to store something sensitive there? You may think that your address is not sensitive data but you’ll have to reconsider as soon as some crook uses it to open a new eBay account…

So my idea is create a public data safe where you have full control what someone else can see. For example your address: Instead of giving a online shop your address, you give them a random ID and you give access rights for the delivery service to resolve that ID. The shop doesn’t know where you live (and your address doesn’t go “somewhere” when the shop goes bankrupt) and you still get your goods.

Imagine you have an accident. You’re unconscious and are brought into a hospital. They need to run tests to figure out your blood group. If they have to give you medicine, then you’re better not allergic to it. And how about alerting your relatives? Here, a random ID which only registered health care services can decode would help: You could put your health data (allergies, medicine that works better on you than other, blood group, relatives to alert, important facts like whether you have a heart disease, etc) online without risking to find them on the loose.

How would it work? The service itself would only store data which you send encrypted. So the encryption would happen on your computer. Better get that anti-virus up to date, though. Health or delivery services would put their “public keys” online on this site, too, so you could encrypt the data in such a way that you and they can read it (basically, you make a copy and encrypt both). This way only certain people can read the data.

When data is uploaded, it gets tagged as “address”, “name”, “age”, “medical information”, etc. and each piece gets a unique, random ID (so you can’t tell from the ID who it belongs to). When another service should be allowed to see some of your data, you take their key to encrypt a copy for them and send them the ID.

If your address changes (because you move), you’d have to update it only in a single place.

Drop me a comment if you like to implement this idea.


Random Idea: Guided Public Transport

5. March, 2009

Just got this idea: You can download train and bus schedules on your mobile, you can buy tickets online, so why doesn’t the system combine the two to guide me through the public transport?

The idea is that I send a request to travel to some spot. The software should know which coupons and other discounts apply for me, what tickets I already own, etc. So the first step would be to tell me what tickets I need in addition to what I already have and what that would cost.

If I pay, the system should guide me to the next bus stop or train station where I can start my journey. During the travel, the system should inform me a few minutes before arrivial at my next destination. This should include the estimated time of arrival, where I’ll arrive (which platform), where I need to go next (platform or location on a map), how much time I have and what connections are available.

It should also be possible to interrupt a travel, say, to have lunch on a long trip. As necessary, the system should buy new tickets and cancel preordered ones. If I stay overnight, I should get a list of connections on the next morning so I can ask the hotel service to wake me at the right time.

If you like the idea and want to implement it, drop me a note.