RESIZING TRANSPARENT IMAGES WITH DJANGO + PIL

February 1st, 2009

I can’t seem to get sorl thumbnail to play nice with transparent PNGs, it keeps adding weird black and grey backgrounds because it’s doesn’t maintain the alpha channel in it’s output.


Python’s PIL Module uses different versions of the Image.save() method depending on the format of the image being saved. sorl thumbnail uses the following call when it creates the final image output:

im.save(self.dest, quality=self.quality)

This call utilizes a parameter call quality which, according to the documentation is only available on JPEGs. Even changing the THUMBNAIL_EXTENSION in my settings.py file to “png” still didn’t make it maintain the alpha channel the way I had expected it to. Bug 56 is currently open for this issue at the sorl thumbnail project home.

The solution

I wanted to setup a way to pull the images off of the transparency resize them and then drop them on an opaque background of it’s own independent size.

So the first thing I did was to load in an image via PIL:

im = Image.open(filename)

So now that we’ve got our image we need to create the opaque background for it… right now we’ll just use a solid black one. Use the following PIL method call to create a background at an identical size to the original image:

bg = Image.new('RGBA', im.size, (0, 0, 0))

At this point I’ve got two images, im the logo file and bg the opaque black background. Using the PIL paste method I can stick there two together.

bg.paste(im)

which gives us the following image:

If you’re like me, you’re like – “WHAT THE HELL?!?! I just pasted a transparent PNG on a black background, why is it all white???” The answer is because you didn’t tell Python to maintain the alpha channel when it pasted.

The way that PIL deals with transparency when saving or pasting PNGs (that have a mode of “RGBA” or “P”) is to allow for a “transparency” parameter which is an integer from 0 – 255 which is sort of like a transparency tolerance for that image, and represents the “opaqueness” of the pixels to maintain transparency for. Since this is different for every image what we need to do is just maintain the value of the PNG we’re working with.

Note: that if you paste an “RGBA” image (WE ARE!), the alpha band is ignored in a paste. You can work around this by using the same image as both source image and mask – like we have below. More information at the PIL Handbook

Change the paste call to look like this:

bg.paste(im, (0, 0), im)

which produces this:

Read the rest of this entry »

Wordpress: Get Posts By Custom Field Values

January 3rd, 2009

Thought Wordpress nerds might find this useful, a function to retrieve a list of posts by passing in a custom filed key=>value pair, with an optional count parameter.

Just drop this in your “functions.php”:

function getPostsByMeta($key, $value, $count = -1)
{
    global $wpdb;
 
    $sql = "SELECT DISTINCT wp_posts.post_title,
    wp_posts.ID FROM $wpdb->posts,
    $wpdb->postmeta 
    WHERE $wpdb->posts.ID = $wpdb->postmeta.post_id 
    AND $wpdb->posts.post_status = 'publish' 
    AND $wpdb->postmeta.meta_key = '$key' 
    AND $wpdb->postmeta.meta_value = '$value' 
    ORDER BY post_date DESC";
 
    $sql .= ($count != -1) ? " LIMIT ".$count : "" ; 
 
    return $wpdb->get_results($sql);
}

and then you can use it like this:

$news_home = getPostsByMeta('_tb_post_section', 'News', 3); 
 
<?php foreach ($news_home as $news) : ?>
    <!-- OUTPUT TEMPLATED HTML -->
<?php endforeach; ?>

Files from Wordcamp Session

September 27th, 2008

Here are the files from my presentation today at Wordcamp Portland.

PDF of my Keynote

Email Update Plugin Files


…. trust me. I have a lot more to say about Wordcamp, but I’ll have to get to it tomorrow – I’m exhausted. That was a LONG day.

Electrolux Virtual Kitchen

September 23rd, 2008


URL: http://www.electroluxappliances.com/node58.aspx
AGENCY: Struck Creative / DDB-NY
LAUNCH: January 2008
ROLE: Lead Developer


I relied heavily upon Arthur Debert’s Bulk Loader to create this video and audio heavy media site. Media files load in the background and you view other content, to create as seemless an experience as possible.

GM USED CAR AMBUSH

September 22nd, 2008


URL: http://www.usedcarambush.com/
AGENCY: STRUCK Creative
LAUNCH: July 2008
ROLE: Lead Developer / Technical Architect


This was the last project that I worked on at STRUCK before I left for NEMO. The site is built entirely in ActionScript3 and I personally built the Papervision 3D powered van interior, and the media queue and streaming system.

HP + VOODOODNA

September 22nd, 2008


URL: http://www.hp.com/voodoodna/
AGENCY: NEMO
LAUNCH: June 2008
ROLE: Lead Developer / Technical Architect

The Wi-Life

September 21st, 2008


URL: http://thewilife.urbandaddy.com/
AGENCY: Left Fields Labs
LAUNCH: August 2008
ROLE: Lead Developer
TECHNOLOGIES: Flash


Flash based site for UrbanDaddy and Sony to help travelers locate Wi-Fi hot-spots in San Francisco and New York. ActionScript 3 that integrates with the flash-based Yahoo Maps API.

UTAH OFFICE OF TOURISM

September 21st, 2008


URL: http://utah.travel/
AGENCY: Struck Creative
LAUNCH: March 2008
ROLE: Lead Developer
TECHNOLOGIES: Flash, Python + Django


Flash based site I did while at Struck for the Utah Office of Tourism. The data is all dynamic and is pulled from a Django based CMS that allow the client to update the content at any time.

I’M SPEAKING AT WORDCAMP PDX

September 21st, 2008


I am speaking this Saturday September 27th @ WordCamp Portland.


I’ll be talking about extending the functionality of Wordpress by writing custom plug-ins, and creating your own administration menus & functionality.


Registration is still open but they’re capping attendence at 150, and I hear that they’re pretty close – so if you wanna go register now.

GRANT SKINNER ON AS3 RESOURCE MANAGEMENT

September 21st, 2008

This is an oldie but a goodie – Grant Skinner gives the straight dope on Garbage Collection and resource management in ActionSctipt 3. Topics that are all too often overlooked.

While on the subject you might also want to check out his articlce Understanding the DELETE Keyword.