Saturday, 12 July 2008

It's the little things

Yesterday afternoon I was walking up the hill from work, headed to Starbucks to buy some coffee filters.

The area where I work is full of little boutiques that survive on a steady flow of tourists offloaded from package tour buses. One boutique that sells (as near as I can determine from glancing in the window) very expensive letter paper and body parts for Pinocchio dolls of various sizes had a sign in the window saying that it was open and "Back in 5 minutes". The door was ajar. The proprietor was nowhere to be seen. I was greatly amused that they had left the door open so customers could come in from the cold and look around.

Back to the coffee filters. At home we make American-style drip coffee, i.e. what they call "coffee" (with no modifiers) in the US. Coffee filters are something of a specialty item in New Zealand and surprisingly expensive in the supermarkets. At Starbucks the filters are about half the price of the supermarkets.

I picked two boxes of 100 filters and took them to the counter. The cashiers looked at the boxes as if they had never seen them before, turning them around hunting for the price sticker. They rang them up then asked if I wanted them to remove the stickers -- i.e. they thought these novelty items must be gifts. I just chuckled. I declined the special little carry bag too.

I guess we're not in Seattle any more.

Tuesday, 8 July 2008

Anticipatory medicine

My 6.5 year old son was asking why doctors can't cure the common cold. I explained that one problem is that the various viruses keep mutating, so you can't just have one medicine to solve the problem. He suggested that the scientists should anticipate the way that the viruses will mutate and make the medicine for that scenario. Then when the viruses mutate the medicine will get them.

OpenXML Packages

I am taking the various files that users refer to when documenting the process flow in their organization and putting them all in an OpenXML package (using System.IO.Packaging).

Office provides an additional layer around these packages to make it a bit easier to produce Office documents (which are just packages with a particular internal structure). See here for the SDK.

The Office SDK makes some things a little easier, although some of the names had me a bit confused at first (CustomXmlPart for example has nothing XML-ish about it, it's just a nice way to put things in the place in a .docx file where Word expects the custom XML to go). But with that extra layer you lose some of the functionality of the underlying System.IO.Packaging. For example, the Office SDK provides some nice functions to add images but you don't get to specify the compression. One JPG file ended up going from 276,216 bytes to 403,084 bytes, i.e. actually getting bigger. Using the underlying System.IO.Packaging, I am able to specify no compression for JPGs -- they have such low entropy all you do is add the overhead of the ZIP housekeeping bits.

Curiously, with both the Office SDK and the underlying classes you have to specify the image type. I couldn't find anything in the DotNet foundation classes to tell me the image type given a stream or even given a file name, so I had to bake something trivial. Fortunately, a lot of the time I know exactly what the image type is anyway.

DotNet Stream to IStream

Lately I have been grafting some new cloth on to our legacy code. In this case, that means writing C# COM servers that get called from legacy Delphi.Win32 code.

I have been taking the various files that together comprise a user's model of the process flow in their organization and bundling them together using System.IO.Packaging (a nice wrapper on a ZIP file).

In all the places in the legacy Delphi code where it might try to get a TFileStream (Delphi people like to start their class names with the letter T) it will instead be getting a TOleStream on a C# object that implements IStream.

Here's the kicker. C# Stream objects don't implement IStream so you need a wrapper. Blech. Luckily for me, Oliver Sturm has already posted a partial solution (it implements Read but not Write) here so I was spared too much grief. Then it was just a matter of regenerating the Delphi wrappers for the assembly and now we're as good as gold, as they say in this country.