Archive for August, 2012

Monthly Donation Time: cURL and the “Friends to the Animals” Foundation

Thursday, August 30th, 2012

This month I’m not going to wait till the very last minute with my donations. Let’s do it.

The open source project that I’m supporting this month is cURL, a powerful swiss-army knife kind of utility for transferring data using various protocols. It’s most often used as command-line HTTP-testing tool, but it does waaay more than just that — look at the list of its features and be amazed. Lately I’ve been doing a lot of work with web APIs, and cURL has helped me with testing lots of times. Thanks and kudos to Daniel Stenberg, the original author and project leader, and to all the contributors!

Traditionally, my second donation is not related to open source or any technology stuff, and traditionally it is to an animal charity. I’m donating to the “Friends to the Animals” Foundation in Katowice, dedicated to helping mistreated animals and raising awareness of animal welfare issues. Their website lists many stories of animals that were saved by them — I was touched by the story of Manio, a cat that fell out of a window on 10th floor and survived with just a broken leg, but his owners could not afford to pay for his treatment and wanted to put him down. The Foundation took Manio in, had him operated, and is now taking care of him while he’s recovering. Get well soon, Manio!

Auto-cropping Transparent Images in Python Imaging Library

Sunday, August 26th, 2012

When I was writing the Font Awesome to PNG utility, I used a nice image processing library for Python — Python Imaging Library (PIL). It offers a lot of features, is easy to use, and comes with good documentation. And since it’s rather popular, there are many code examples for it all around the intertubes.

I couldn’t, however, find a comprehensive example of implementing an auto-crop feature for transparent images (specifically, PNG icons with a transparent background), so when I managed to put it together based on a few other examples, I thought I’d post it here in case anyone else finds it useful. So, here’s a function that autocrops a PIL image, optionally with a “border” of empty space around the contents:

def autocrop_image(image, border = 0):
    # Get the bounding box
    bbox = image.getbbox()

    # Crop the image to the contents of the bounding box
    image = image.crop(bbox)

    # Determine the width and height of the cropped image
    (width, height) = image.size

    # Add border
    width += border * 2
    height += border * 2

    # Create a new image object for the output image
    cropped_image = Image.new("RGBA", (width, height), (0,0,0,0))

    # Paste the cropped image onto the new image
    cropped_image.paste(image, (border, border))

    # Done!
    return cropped_image

And here’s a sample program that uses it:

#!/usr/bin/env python

import sys
import Image

def autocrop_image(image, border = 0):
    ...

if len(sys.argv) < 3:
    # Not enough arguments -- show usage information and exit
    print "Usage: " + sys.argv[0] + " infile outfile [border]"
    exit(1)

# Get input and output file names
infile = sys.argv[1]
outfile = sys.argv[2]

# Check if border size was provided
if sys.argv[3]:
    border = int(sys.argv[3])
else:
    border = 0

# Open the input image
image = Image.open(infile)

# Do the cropping
image = autocrop_image(image, border)

# Save the output image
image.save(outfile)

Disclaimer: I’m a Python noob. If you find something wrong about the above code, let me know.

JQuery valHooks

Friday, August 24th, 2012

In selectList version 0.5, I made use of an interesting feature of jQuery, called valHooks. It’s used internally in jQuery (since version 1.6) and there’s not much documentation on it, but it can be very useful for plugin authors.

Valhooks allow you to change the way the jQuery method .val() works for certain elements, giving you control over how element values are set and retrieved. You define a function and assign it to a specific element type, and whenever .val() is called on that element type, your function is invoked to process the call.

Let’s take a look at an example — the code below is a very simple jQuery plugin that makes use of a get valhook to convert the value of an input field before it is retrieved. In practical terms, it allows you to enter an expression representing the number of bytes, with the ability to parse quantifiers like “kB” for kilobytes or “MB” for megabytes, and automatically translate them into bytes. So, “1k” or “1kB” becomes “1024″, “1M” or “1MB” becomes “1048576″, and so on.

(function ($) {
    // jQuery plugin definition
    $.fn.bytesInput = function () {
        $(this).filter('input[type="text"]').each(function() {
            $(this).data('bytesInput', true);
        });
        return this;
    };

    var origHook;

    // There might already be valhooks for the "text" type
    if ($.valHooks.text)
        // Preserve the original valhook function
        origHook = $.valHooks.text.get;
    else
        // Make room for a new valhook
        $.valHooks.text = {};

    $.valHooks.text.get = function (el) {
        // Does this element have our data field?
        if (!$(el).data('bytesInput'))
            // No -- check if there was a valhook function already defined
            if (origHook)
                // There was, so go ahead and call it
                return origHook(el);
            else
                // No previous function, return undefined to have jQuery
                // take care of retrieving the value
                return undefined;

        // Try parsing the expression
        if (matches = el.value.match(/(\d+)\s*([kKmMgG]?)[bB]?/)) {
            switch (matches[2].toLowerCase()) {
                case 'k':
                    // Kilobytes
                    return matches[1] * 1024;
                case 'm':
                    // Megabytes
                    return matches[1] * 1048576;
                case 'g':
                    // Gigabytes
                    return matches[1] * 1073741824;
                default:
                    // Just bytes
                    return matches[1];
            }
        }
        else
            // Can't parse the expression -- just return the current value
            return el.value;
    };
})(jQuery);

The example is pretty straightforward, and if you’re familiar with how jQuery plugins work, you should have no trouble understanding it. One specific thing that might be worth pointing out is how the .data() method is used to distinguish the special input field from other inputs (for which the .val() method should work the usual way). The plugin initialization function attaches data to the element at the "bytesInput" key — the get valhook function then checks for the presence of that key, and only does its thing if the key is there. Otherwise, it either falls back to the original valhook function (if there was one), or returns undefined, which makes jQuery process it in the traditional manner. This way the plugin can be used with other plugins or pieces of code that set their own valhooks for input elements, and not interfere with them.

If you’d like to see the above example in action, I put it up on jsFiddle.

SelectList 0.5.1

Saturday, August 18th, 2012

I have just released a new version of selectList. It turned out the previous release that I announced a couple days back had a bug that broke the jQuery .val() method for regular (non-selectList) select elements and made it impossible to set their values. This release fixes that.

The bug was spotted and reported by James White — thanks!

I also used this as an opportunity to test the plugin with the latest 1.8 release of jQuery, and all the tests passed with flying colors (yay!), so version 1.8 is now bundled with the plugin.

Font Awesome to PNG

Saturday, August 11th, 2012

If you have anything to do with web design and haven’t been living under a rock for the past few months, you probably heard about Font Awesome. If not, let me tell you that it’s a fantastic set of icons packaged as a font, designed to be used with Twitter Bootstrap.

Displaying icons using a font has several advantages over the use of traditional images, most notably that the icons are vectorized and thus fully scalable, and all fit in one lightweight font file. However, there are still cases when you need (or prefer) to use plain old images, for example when you want to use the image as CSS background (which isn’t possible with a font) or when you want just one or two icons from the set and using the whole font would be an overkill. That was my case recently when I was making a Bootstrap skin for selectList and needed a Bootstrap-style “remove” icon.

I could use a pre-generated Font Awesome icon, as these are available, but I thought it might be useful to have a tool that lets me render a PNG image of any icon in the set, using the size and color of my choice. So I quickly hacked together a program that does just that. Here’s an example of how it can be used to generate PNG images of the “folder-open” and “folder-close” icons, sized at 24×24 pixels:

font-awesome-to-png.py --size 24 folder-open folder-close

The program is available at Github. To use it, you also need the Font Awesome font file in TTF format, which you can grab from Font Awesome Github repository.

I wrote the program in Python — yes, I know, that’s probably the most perverted thing that a Perl programmer can do, but I like trying something different every now and then.

  • Archives

  • Categories

  • Meta

  • Latest Tweets


    Warning: Illegal string offset 'last_access' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 334

    Warning: Illegal string offset 'time_limit' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 334

    Warning: Illegal string offset 'last_access' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 336

    Warning: Illegal string offset 'twitter_api' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 234

    Warning: Illegal string offset 'user_token' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 262

    Warning: Illegal string offset 'user_secret' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 263

    Warning: Illegal string offset 'consumer_key' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 264

    Warning: Illegal string offset 'consumer_secret' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 265

    Warning: Illegal string offset 'twitter_username' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 270

    Warning: Illegal string offset 'show_retweets' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 272

    Warning: Illegal string offset 'exclude_replies' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 275

    Warning: Illegal string offset 'twitter_data' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 282

    Warning: Illegal string offset 'twitter_data' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 350

    Warning: Illegal string offset 'twitter_data' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 351
    Twitter outputted an error:
    .
    Warning: Illegal string offset 'time_format' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 484
  • Follow odyniec on Twitter

<